@@ -652,22 +652,15 @@ const evaluate_map: EvaluateMap = {
652
652
MemberExpression ( path ) {
653
653
const { node, scope, ctx} = path ;
654
654
const { object, property, computed} = node ;
655
- if ( types . isSuper ( node . object ) ) {
656
- const $var = scope . $find ( "this" ) ;
657
- if ( $var ) {
658
- const __this = $var . $get ( ) ;
659
- if ( ctx . SuperClass ) {
660
- return ctx . SuperClass . prototype [ ( < any > property ) . name ] . bind ( __this ) ;
661
- } else {
662
- throw node ;
663
- }
664
- }
665
- }
666
- if ( computed ) {
667
- return evaluate ( path . $child ( object ) ) [ evaluate ( path . $child ( property ) ) ] ;
668
- } else {
669
- return evaluate ( path . $child ( object ) ) [ ( < types . Identifier > property ) . name ] ;
670
- }
655
+
656
+ const propertyName : string = computed
657
+ ? evaluate ( path . $child ( property ) )
658
+ : ( < types . Identifier > property ) . name ;
659
+
660
+ const obj = evaluate ( path . $child ( object ) ) ;
661
+ const target = obj [ propertyName ] ;
662
+
663
+ return typeof target === "function" ? target . bind ( obj ) : target ;
671
664
} ,
672
665
AssignmentExpression ( path ) {
673
666
const { node, scope} = path ;
@@ -781,10 +774,10 @@ const evaluate_map: EvaluateMap = {
781
774
}
782
775
} ;
783
776
784
- Object . defineProperties ( func , {
785
- length :{ value :node . params . length } ,
786
- name : { value :node . id ? node . id . name : "" }
787
- } )
777
+ Object . defineProperties ( func , {
778
+ length : { value : node . params . length } ,
779
+ name : { value : node . id ? node . id . name : "" }
780
+ } ) ;
788
781
789
782
return func ;
790
783
} ,
@@ -800,96 +793,75 @@ const evaluate_map: EvaluateMap = {
800
793
return path . node . value . raw ;
801
794
} ,
802
795
ClassDeclaration ( path ) {
796
+ const ClassConstructor = evaluate (
797
+ path . $child ( path . node . body , path . scope . $child ( "block" ) )
798
+ ) ;
799
+ path . scope . $const ( path . node . id . name , ClassConstructor ) ;
800
+ } ,
801
+ ClassBody ( path ) {
803
802
const { node, scope} = path ;
804
- const constructor : types . ClassMethod | void = < types . ClassMethod | void > node . body . body . find (
803
+ const constructor : types . ClassMethod | void = < types . ClassMethod | void > node . body . find (
805
804
n => types . isClassMethod ( n ) && n . kind === "constructor"
806
805
) ;
807
- const methods : types . ClassMethod [ ] = < types . ClassMethod [ ] > node . body . body . filter (
806
+ const methods : types . ClassMethod [ ] = < types . ClassMethod [ ] > node . body . filter (
808
807
n => types . isClassMethod ( n ) && n . kind !== "constructor"
809
808
) ;
810
- const properties : types . ClassProperty [ ] = < types . ClassProperty [ ] > node . body . body . filter (
809
+ const properties : types . ClassProperty [ ] = < types . ClassProperty [ ] > node . body . filter (
811
810
n => types . isClassProperty ( n )
812
811
) ;
813
812
814
- let SuperClass ;
815
-
816
- if ( node . superClass ) {
817
- const superClassName : string = ( < any > node . superClass ) . name ;
818
- const $var = scope . $find ( superClassName ) ;
819
-
820
- if ( $var ) {
821
- SuperClass = $var . $get ( ) ;
822
- } else {
823
- throw new ErrNotDefined ( superClassName ) ;
824
- }
825
- }
813
+ const parentNode = ( < Path < types . ClassDeclaration > > path . parent ) . node ;
826
814
827
815
const Class = ( function ( SuperClass ) {
828
816
if ( SuperClass ) {
829
817
_inherits ( Class , SuperClass ) ;
830
818
}
819
+
831
820
function Class ( ...args ) {
832
821
_classCallCheck ( this , Class ) ;
833
-
834
- const newScope = scope . $child ( "function" ) ;
835
-
836
- // babel way to call super();
837
- const __this = _possibleConstructorReturn (
838
- this ,
839
- ( ( < any > Class ) . __proto__ || Object . getPrototypeOf ( Class ) ) . apply (
840
- this ,
841
- args
842
- )
843
- ) ;
844
-
845
- newScope . $const ( "super" , this . __proto__ ) ;
846
-
847
- // typescript way to call super()
848
- // const __this = superClass ? superClass.apply(this, args) || this : this;
849
-
850
- newScope . $const ( "this" , __this ) ;
822
+ const classScope = scope . $child ( "function" ) ;
823
+ classScope . $var ( "this" , this ) ;
851
824
852
825
// define class property
853
826
properties . forEach ( p => {
854
- __this [ p . key . name ] = evaluate ( path . $child ( p . value , newScope ) ) ;
827
+ this [ p . key . name ] = evaluate ( path . $child ( p . value , classScope ) ) ;
855
828
} ) ;
856
829
857
830
if ( constructor ) {
858
831
// defined the params
859
832
constructor . params . forEach ( ( p : types . LVal , i ) => {
860
833
if ( types . isIdentifier ( p ) ) {
861
- newScope . $const ( p . name , args [ i ] ) ;
834
+ classScope . $const ( p . name , args [ i ] ) ;
862
835
} else {
863
836
throw new Error ( "Invalid params" ) ;
864
837
}
865
838
} ) ;
839
+ constructor . body . body . forEach ( n =>
840
+ evaluate (
841
+ path . $child ( n , classScope , {
842
+ SuperClass,
843
+ ClassConstructor : Class ,
844
+ ClassConstructorArguments : args ,
845
+ ClassEntity : this
846
+ } )
847
+ )
848
+ ) ;
866
849
867
- if ( node . superClass ) {
868
- // make sure super exist in first line
869
- const superCallExpression : types . ExpressionStatement = < types . ExpressionStatement > ( < any > constructor ) . body . body . shift ( ) ;
870
-
871
- if (
872
- ! types . isExpressionStatement ( superCallExpression ) ||
873
- ! types . isCallExpression ( superCallExpression . expression ) ||
874
- ! types . isSuper ( superCallExpression . expression . callee )
875
- ) {
850
+ if ( parentNode . superClass ) {
851
+ // if not apply super in construtor
852
+ // FIXME: should define the var in private scope
853
+ if ( ! scope . $find ( "@super" ) ) {
876
854
throw ErrNoSuper ;
877
- } else {
878
- // TODO: run super
879
855
}
880
856
}
881
-
882
- constructor . body . body . forEach ( n =>
883
- evaluate ( path . $child ( n , newScope , { SuperClass} ) )
884
- ) ;
885
857
}
886
858
887
- return __this ;
859
+ return this ;
888
860
}
889
861
890
862
// define class name
891
863
Object . defineProperties ( Class , {
892
- name : { value : node . id . name } ,
864
+ name : { value : parentNode . id . name } ,
893
865
length : { value : constructor ? constructor . params . length : 0 }
894
866
} ) ;
895
867
@@ -907,7 +879,12 @@ const evaluate_map: EvaluateMap = {
907
879
} ) ;
908
880
909
881
const result = evaluate (
910
- path . $child ( method . body , newScope , { SuperClass} )
882
+ path . $child ( method . body , newScope , {
883
+ SuperClass,
884
+ ClassConstructor : Class ,
885
+ ClassMethodArguments : args ,
886
+ ClassEntity : this
887
+ } )
911
888
) ;
912
889
if ( result === RETURN_SINGAL ) {
913
890
return result . result ? result . result : result ;
@@ -934,17 +911,54 @@ const evaluate_map: EvaluateMap = {
934
911
_createClass ( Class , _methods ) ;
935
912
936
913
return Class ;
937
- } ) ( SuperClass ) ;
914
+ } ) (
915
+ parentNode . superClass
916
+ ? ( ( ) => {
917
+ const $var = scope . $find ( ( < any > parentNode . superClass ) . name ) ;
918
+ return $var ? $var . $get ( ) : null ;
919
+ } ) ( )
920
+ : null
921
+ ) ;
938
922
939
- scope . $const ( node . id . name , Class ) ;
923
+ return Class ;
940
924
} ,
941
925
ClassMethod ( path ) {
942
926
return evaluate ( path . $child ( path . node . body ) ) ;
943
927
} ,
944
928
ClassExpression ( path ) { } ,
945
929
Super ( path ) {
946
- // FIXME: check it include in Class expression
947
- return function ( ) { } ;
930
+ const { scope, ctx} = path ;
931
+ const {
932
+ SuperClass,
933
+ ClassConstructor,
934
+ ClassConstructorArguments,
935
+ ClassEntity
936
+ } = ctx ;
937
+ const ClassBodyPath = path . $findParent ( "ClassBody" ) ;
938
+ // make sure it include in ClassDeclaration
939
+ if ( ! ClassBodyPath ) {
940
+ throw new Error ( "super() only can use in ClassDeclaration" ) ;
941
+ }
942
+ const parentPath = path . parent ;
943
+ if ( parentPath ) {
944
+ // super()
945
+ if ( types . isCallExpression ( parentPath . node ) ) {
946
+ return function inherits ( ...args ) {
947
+ _possibleConstructorReturn (
948
+ ClassEntity ,
949
+ (
950
+ ( < any > ClassConstructor ) . __proto__ ||
951
+ Object . getPrototypeOf ( ClassConstructor )
952
+ ) . apply ( ClassEntity , args )
953
+ ) ;
954
+ ClassBodyPath . scope . $const ( "@super" , true ) ;
955
+ } . bind ( ClassEntity ) ;
956
+ } else if ( types . isMemberExpression ( parentPath . node ) ) {
957
+ // super.eat()
958
+ // then return the superclass prototype
959
+ return SuperClass . prototype ;
960
+ }
961
+ }
948
962
} ,
949
963
SpreadElement ( path ) {
950
964
return evaluate ( path . $child ( path . node . argument ) ) ;
0 commit comments