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