@@ -4,90 +4,47 @@ import {untracked} from "../core/derivation";
44import { isSpyEnabled , spyReportStart , spyReportEnd } from "../core/spy" ;
55import { ComputedValue } from "../core/computedvalue" ;
66import { globalState } from "../core/globalstate" ;
7+ import { createClassPropertyDecorator } from "../utils/decorators" ;
8+
9+ const actionDecorator = createClassPropertyDecorator (
10+ function ( target , key , value , args , originalDescriptor ) {
11+ const actionName = ( args && args . length === 1 ) ? args [ 0 ] : ( value . name || key || "<unnamed action>" ) ;
12+ const wrappedAction = action ( actionName , value ) ;
13+ if ( originalDescriptor && originalDescriptor . value && target . constructor && target . constructor . prototype ) {
14+ // shared method, replace this very property on the prototype with the right value
15+ Object . defineProperty ( target . constructor . prototype , key , {
16+ configurable : true , enumerable : false , writable : false ,
17+ value : wrappedAction
18+ } ) ;
19+ } else {
20+ // bound instance methods
21+ Object . defineProperty ( target , key , {
22+ configurable : true , enumerable : false , writable : false ,
23+ value : wrappedAction
24+ } ) ;
25+ }
26+ } ,
27+ function ( key ) {
28+ return this [ key ] ;
29+ } ,
30+ function ( ) {
31+ invariant ( false , "It is not allowed to assign new values to @action fields" ) ;
32+ } ,
33+ false ,
34+ true
35+ ) ;
736
837export function action < T extends Function > ( fn : T ) : T ;
938export function action < T extends Function > ( name : string , fn : T ) : T ;
1039export function action ( customName : string ) : ( target : Object , key : string , baseDescriptor ?: PropertyDescriptor ) => void ;
1140export function action ( target : Object , propertyKey : string , descriptor ?: PropertyDescriptor ) : void ;
1241export function action ( arg1 , arg2 ?, arg3 ?, arg4 ?) : any {
13- switch ( arguments . length ) {
14- case 1 :
15- // action(someFunction)
16- if ( typeof arg1 === "function" )
17- return actionImplementation ( arg1 . name || "<unnamed action>" , arg1 ) ;
18- // @action ("custom name") someFunction () {}
19- // @action ("custom name") someFunction = () => {}
20- else
21- return ( target , key , descriptor ) => actionDecorator ( arg1 , target , key , descriptor ) ;
22- case 2 :
23- // action("custom name", someFunction)
24- if ( typeof arg2 === "function" )
25- return actionImplementation ( arg1 , arg2 ) ;
26- else
27- return actionDecorator ( arg2 , arg1 , arg2 , undefined ) ; // See #269
28- case 3 :
29- // @action someFunction () {}
30- // @action someFunction = () => {}
31- return actionDecorator ( arg2 , arg1 , arg2 , arg3 ) ;
32- default :
33- invariant ( false , "Invalid arguments for (@)action, please provide a function, name and function or use it as decorator on a class instance method" ) ;
34- }
35- }
36-
37- function actionDecorator ( name : string , target : any , key : string , descriptor : PropertyDescriptor ) {
38- if ( descriptor === undefined ) {
39- // typescript: @action f = () => { }
40- typescriptActionValueDecorator ( name , target , key ) ;
41- return ;
42- }
43- if ( descriptor . value === undefined && typeof ( descriptor as any ) . initializer === "function" ) {
44- // typescript: @action f = () => { }
45- return babelActionValueDecorator ( name , target , key , descriptor ) ;
46- }
47- const base = descriptor . value ;
48- descriptor . value = actionImplementation ( name , base ) ;
49- }
50-
51- /**
52- * Decorators the following pattern @action method = () => {} by desugaring it to method = action(() => {})
53- */
54- function babelActionValueDecorator ( name : string , target , prop , descriptor ) : PropertyDescriptor {
55- return {
56- configurable : true ,
57- enumerable : false ,
58- get : function ( ) {
59- const v = descriptor . initializer . call ( this ) ;
60- invariant ( typeof v === "function" , `Babel @action decorator expects the field '${ prop } to be initialized with a function` ) ;
61- const implementation = action ( name , v ) ;
62- addBoundAction ( this , prop , implementation ) ;
63- return implementation ;
64- } ,
65- set : function ( ) {
66- invariant ( false , `Babel @action decorator: field '${ prop } ' not initialized` ) ;
67- }
68- } ;
69- }
70-
71- function typescriptActionValueDecorator ( name : string , target , prop ) {
72- Object . defineProperty ( target , prop , {
73- configurable : true ,
74- enumerable : false ,
75- get : function ( ) {
76- invariant ( false , `TypeScript @action decorator: field '${ prop } ' not initialized` ) ;
77- } ,
78- set : function ( v ) {
79- invariant ( typeof v === "function" , `TypeScript @action decorator expects the field '${ prop } to be initialized with a function` ) ;
80- addBoundAction ( this , prop , action ( name , v ) ) ;
81- }
82- } ) ;
83- }
42+ if ( arguments . length === 1 && typeof arg1 === "function" )
43+ return actionImplementation ( arg1 . name || "<unnamed action>" , arg1 ) ;
44+ if ( arguments . length === 2 && typeof arg2 === "function" )
45+ return actionImplementation ( arg1 , arg2 ) ;
8446
85- function addBoundAction ( target , prop , implementation ) {
86- Object . defineProperty ( target , prop , {
87- enumerable : false ,
88- writable : false ,
89- value : implementation
90- } ) ;
47+ return actionDecorator . apply ( null , arguments ) ;
9148}
9249
9350export function actionImplementation ( actionName : string , fn : Function ) : Function {
0 commit comments