@@ -119,6 +119,11 @@ class CodeGenerator extends GeneralizingAstVisitor
119
119
120
120
String _buildRoot;
121
121
122
+ bool _superAllowed = true ;
123
+
124
+ List <JS .TemporaryId > _superHelperSymbols = < JS .TemporaryId > [];
125
+ List <JS .Method > _superHelpers = < JS .Method > [];
126
+
122
127
/// Whether we are currently generating code for the body of a `JS()` call.
123
128
bool _isInForeignJS = false ;
124
129
@@ -596,6 +601,7 @@ class CodeGenerator extends GeneralizingAstVisitor
596
601
var body = < JS .Statement > [];
597
602
var extensions = _extensionsToImplement (classElem);
598
603
_initExtensionSymbols (classElem, methods, fields, body);
604
+ _emitSuperHelperSymbols (_superHelperSymbols, body);
599
605
600
606
// Emit the class, e.g. `core.Object = class Object { ... }`
601
607
_defineClass (classElem, className, classExpr, body);
@@ -620,6 +626,14 @@ class CodeGenerator extends GeneralizingAstVisitor
620
626
return _statement (body);
621
627
}
622
628
629
+ void _emitSuperHelperSymbols (
630
+ List <JS .TemporaryId > superHelperSymbols, List <JS .Statement > body) {
631
+ for (var id in superHelperSymbols) {
632
+ body.add (js.statement ('const # = Symbol(#)' , [id, js.string (id.name)]));
633
+ }
634
+ superHelperSymbols.clear ();
635
+ }
636
+
623
637
void _registerPropertyOverrides (
624
638
ClassElement classElem,
625
639
JS .Expression className,
@@ -898,6 +912,10 @@ class CodeGenerator extends GeneralizingAstVisitor
898
912
jsMethods.add (_emitIterable (type));
899
913
}
900
914
915
+ // Add all of the super helper methods
916
+ jsMethods.addAll (_superHelpers);
917
+ _superHelpers.clear ();
918
+
901
919
return jsMethods.where ((m) => m != null ).toList (growable: false );
902
920
}
903
921
@@ -1631,7 +1649,7 @@ class CodeGenerator extends GeneralizingAstVisitor
1631
1649
}
1632
1650
}
1633
1651
1634
- JS .Method _emitMethodDeclaration (DartType type, MethodDeclaration node) {
1652
+ JS .Method _emitMethodDeclaration (InterfaceType type, MethodDeclaration node) {
1635
1653
if (node.isAbstract) {
1636
1654
return null ;
1637
1655
}
@@ -1957,8 +1975,11 @@ class CodeGenerator extends GeneralizingAstVisitor
1957
1975
} else {
1958
1976
_asyncStarController = null ;
1959
1977
}
1978
+ var savedSuperAllowed = _superAllowed;
1979
+ _superAllowed = false ;
1960
1980
// Visit the body with our async* controller set.
1961
1981
var jsBody = _visit (body);
1982
+ _superAllowed = savedSuperAllowed;
1962
1983
_asyncStarController = savedController;
1963
1984
1964
1985
DartType returnType = _getExpectedReturnType (element);
@@ -2004,8 +2025,12 @@ class CodeGenerator extends GeneralizingAstVisitor
2004
2025
/// function instantiation.
2005
2026
@override
2006
2027
JS .Expression visitSimpleIdentifier (SimpleIdentifier node) {
2007
- return _applyFunctionTypeArguments (
2008
- _emitSimpleIdentifier (node), node.staticElement, node.staticType);
2028
+ var typeArgs = _getTypeArgs (node.staticElement, node.staticType);
2029
+ var simpleId = _emitSimpleIdentifier (node);
2030
+ if (typeArgs == null ) {
2031
+ return simpleId;
2032
+ }
2033
+ return js.call ('dart.gbind(#, #)' , [simpleId, typeArgs]);
2009
2034
}
2010
2035
2011
2036
/// Emits a simple identifier, handling implicit `this` as well as
@@ -2385,17 +2410,66 @@ class CodeGenerator extends GeneralizingAstVisitor
2385
2410
return _emitMethodCall (target, node);
2386
2411
}
2387
2412
2388
- /// Emits a (possibly generic) instance method call.
2389
2413
JS .Expression _emitMethodCall (Expression target, MethodInvocation node) {
2414
+ List <JS .Expression > args = _visit (node.argumentList);
2415
+ var typeArgs = _emitInvokeTypeArguments (node);
2416
+
2417
+ if (target is SuperExpression && ! _superAllowed) {
2418
+ return _emitSuperHelperCall (typeArgs, args, target, node);
2419
+ }
2420
+
2421
+ return _emitMethodCallInternal (target, node, args, typeArgs);
2422
+ }
2423
+
2424
+ JS .Expression _emitSuperHelperCall (List <JS .Expression > typeArgs,
2425
+ List <JS .Expression > args, SuperExpression target, MethodInvocation node) {
2426
+ var fakeTypeArgs =
2427
+ typeArgs? .map ((_) => new JS .TemporaryId ('a' ))? .toList (growable: false );
2428
+ var fakeArgs =
2429
+ args.map ((_) => new JS .TemporaryId ('a' )).toList (growable: false );
2430
+ var combinedFakeArgs = < JS .TemporaryId > [];
2431
+ if (fakeTypeArgs != null ) {
2432
+ combinedFakeArgs.addAll (fakeTypeArgs);
2433
+ }
2434
+ combinedFakeArgs.addAll (fakeArgs);
2435
+
2436
+ var forwardedCall =
2437
+ _emitMethodCallInternal (target, node, fakeArgs, fakeTypeArgs);
2438
+ var superForwarder = _getSuperHelperFor (
2439
+ node.methodName.name, forwardedCall, combinedFakeArgs);
2440
+
2441
+ var combinedRealArgs = < JS .Expression > [];
2442
+ if (typeArgs != null ) {
2443
+ combinedRealArgs.addAll (typeArgs);
2444
+ }
2445
+ combinedRealArgs.addAll (args);
2446
+
2447
+ return js.call ('this.#(#)' , [superForwarder, combinedRealArgs]);
2448
+ }
2449
+
2450
+ JS .Expression _getSuperHelperFor (String name, JS .Expression forwardedCall,
2451
+ List <JS .Expression > helperArgs) {
2452
+ var helperMethod =
2453
+ new JS .Fun (helperArgs, new JS .Block ([new JS .Return (forwardedCall)]));
2454
+ var helperMethodName = new JS .TemporaryId ('super\$ $name ' );
2455
+ _superHelperSymbols.add (helperMethodName);
2456
+ _superHelpers.add (new JS .Method (helperMethodName, helperMethod));
2457
+ return helperMethodName;
2458
+ }
2459
+
2460
+ /// Emits a (possibly generic) instance method call.
2461
+ JS .Expression _emitMethodCallInternal (
2462
+ Expression target,
2463
+ MethodInvocation node,
2464
+ List <JS .Expression > args,
2465
+ List <JS .Expression > typeArgs) {
2390
2466
var type = getStaticType (target);
2391
2467
var name = node.methodName.name;
2392
2468
var element = node.methodName.staticElement;
2393
2469
bool isStatic = element is ExecutableElement && element.isStatic;
2394
2470
var memberName = _emitMemberName (name, type: type, isStatic: isStatic);
2395
2471
2396
2472
JS .Expression jsTarget = _visit (target);
2397
- var typeArgs = _emitInvokeTypeArguments (node);
2398
- List <JS .Expression > args = _visit (node.argumentList);
2399
2473
if (DynamicInvoke .get (target)) {
2400
2474
if (typeArgs != null ) {
2401
2475
return js.call ('dart.dgsend(#, #, #, #)' ,
@@ -2411,6 +2485,7 @@ class CodeGenerator extends GeneralizingAstVisitor
2411
2485
}
2412
2486
2413
2487
jsTarget = new JS .PropertyAccess (jsTarget, memberName);
2488
+
2414
2489
if (typeArgs != null ) jsTarget = new JS .Call (jsTarget, typeArgs);
2415
2490
2416
2491
if (DynamicInvoke .get (node.methodName)) {
@@ -3545,8 +3620,45 @@ class CodeGenerator extends GeneralizingAstVisitor
3545
3620
if (member is PropertyAccessorElement ) {
3546
3621
member = (member as PropertyAccessorElement ).variable;
3547
3622
}
3623
+ String memberName = memberId.name;
3624
+ var typeArgs = _getTypeArgs (member, resultType);
3625
+
3626
+ if (target is SuperExpression && ! _superAllowed) {
3627
+ return _emitSuperHelperAccess (target, member, memberName, typeArgs);
3628
+ }
3629
+ return _emitAccessInternal (target, member, memberName, typeArgs);
3630
+ }
3631
+
3632
+ JS .Expression _emitSuperHelperAccess (SuperExpression target, Element member,
3633
+ String memberName, List <JS .Expression > typeArgs) {
3634
+ var fakeTypeArgs =
3635
+ typeArgs? .map ((_) => new JS .TemporaryId ('a' ))? .toList (growable: false );
3636
+
3637
+ var forwardedAccess =
3638
+ _emitAccessInternal (target, member, memberName, fakeTypeArgs);
3639
+ var superForwarder = _getSuperHelperFor (
3640
+ memberName, forwardedAccess, fakeTypeArgs ?? const []);
3641
+
3642
+ return js.call ('this.#(#)' , [superForwarder, typeArgs ?? const []]);
3643
+ }
3644
+
3645
+ List <JS .Expression > _getTypeArgs (Element member, DartType instantiated) {
3646
+ DartType type;
3647
+ if (member is ExecutableElement ) {
3648
+ type = member.type;
3649
+ } else if (member is VariableElement ) {
3650
+ type = member.type;
3651
+ }
3652
+
3653
+ // TODO(jmesserly): handle explicitly passed type args.
3654
+ if (type == null ) return null ;
3655
+ return _emitFunctionTypeArguments (type, instantiated);
3656
+ }
3657
+
3658
+ JS .Expression _emitAccessInternal (Expression target, Element member,
3659
+ String memberName, List <JS .Expression > typeArgs) {
3548
3660
bool isStatic = member is ClassMemberElement && member.isStatic;
3549
- var name = _emitMemberName (memberId.name ,
3661
+ var name = _emitMemberName (memberName ,
3550
3662
type: getStaticType (target), isStatic: isStatic);
3551
3663
if (DynamicInvoke .get (target)) {
3552
3664
return js.call ('dart.dload(#, #)' , [_visit (target), name]);
@@ -3566,34 +3678,19 @@ class CodeGenerator extends GeneralizingAstVisitor
3566
3678
// Tear-off methods: explicitly bind it.
3567
3679
if (isSuper) {
3568
3680
result = js.call ('dart.bind(this, #, #.#)' , [name, jsTarget, name]);
3569
- } else if (_isObjectMemberCall (target, memberId.name )) {
3681
+ } else if (_isObjectMemberCall (target, memberName )) {
3570
3682
result = js.call ('dart.bind(#, #, dart.#)' , [jsTarget, name, name]);
3571
3683
} else {
3572
3684
result = js.call ('dart.bind(#, #)' , [jsTarget, name]);
3573
3685
}
3574
- } else if (_isObjectMemberCall (target, memberId.name )) {
3686
+ } else if (_isObjectMemberCall (target, memberName )) {
3575
3687
result = js.call ('dart.#(#)' , [name, jsTarget]);
3576
3688
} else {
3577
3689
result = js.call ('#.#' , [jsTarget, name]);
3578
3690
}
3579
- return _applyFunctionTypeArguments (result, member, resultType);
3580
- }
3581
-
3582
- /// If this is an inferred instantiation of a generic function/method, this
3583
- /// will add the inferred type arguments.
3584
- JS .Expression _applyFunctionTypeArguments (
3585
- JS .Expression result, Element member, DartType instantiated) {
3586
- DartType type;
3587
- if (member is ExecutableElement ) {
3588
- type = member.type;
3589
- } else if (member is VariableElement ) {
3590
- type = member.type;
3691
+ if (typeArgs == null ) {
3692
+ return result;
3591
3693
}
3592
-
3593
- // TODO(jmesserly): handle explicitly passed type args.
3594
- if (type == null ) return result;
3595
- var typeArgs = _emitFunctionTypeArguments (type, instantiated);
3596
- if (typeArgs == null ) return result;
3597
3694
return js.call ('dart.gbind(#, #)' , [result, typeArgs]);
3598
3695
}
3599
3696
@@ -3791,8 +3888,12 @@ class CodeGenerator extends GeneralizingAstVisitor
3791
3888
3792
3889
@override
3793
3890
visitTryStatement (TryStatement node) {
3794
- return new JS .Try (_visit (node.body), _visitCatch (node.catchClauses),
3795
- _visit (node.finallyBlock));
3891
+ var savedSuperAllowed = _superAllowed;
3892
+ _superAllowed = false ;
3893
+ var finallyBlock = _visit (node.finallyBlock);
3894
+ _superAllowed = savedSuperAllowed;
3895
+ return new JS .Try (
3896
+ _visit (node.body), _visitCatch (node.catchClauses), finallyBlock);
3796
3897
}
3797
3898
3798
3899
_visitCatch (NodeList <CatchClause > clauses) {
0 commit comments