OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import 'dart:collection' show HashMap, HashSet; | 5 import 'dart:collection' show HashMap, HashSet; |
6 import 'dart:math' show min, max; | 6 import 'dart:math' show min, max; |
7 | 7 |
8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; | 10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 FunctionBody _currentFunction; | 111 FunctionBody _currentFunction; |
112 | 112 |
113 /// Helper class for emitting elements in the proper order to allow | 113 /// Helper class for emitting elements in the proper order to allow |
114 /// JS to load the module. | 114 /// JS to load the module. |
115 ElementLoader _loader; | 115 ElementLoader _loader; |
116 | 116 |
117 BuildUnit _buildUnit; | 117 BuildUnit _buildUnit; |
118 | 118 |
119 String _buildRoot; | 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 /// Whether we are currently generating code for the body of a `JS()` call. | 126 /// Whether we are currently generating code for the body of a `JS()` call. |
122 bool _isInForeignJS = false; | 127 bool _isInForeignJS = false; |
123 | 128 |
124 CodeGenerator(AnalysisContext c, this.options, this._extensionTypes) | 129 CodeGenerator(AnalysisContext c, this.options, this._extensionTypes) |
125 : context = c, | 130 : context = c, |
126 types = c.typeProvider, | 131 types = c.typeProvider, |
127 _asyncStreamIterator = | 132 _asyncStreamIterator = |
128 _getLibrary(c, 'dart:async').getType('StreamIterator').type, | 133 _getLibrary(c, 'dart:async').getType('StreamIterator').type, |
129 _jsArray = _getLibrary(c, 'dart:_interceptors').getType('JSArray'), | 134 _jsArray = _getLibrary(c, 'dart:_interceptors').getType('JSArray'), |
130 dartCoreLibrary = _getLibrary(c, 'dart:core'), | 135 dartCoreLibrary = _getLibrary(c, 'dart:core'), |
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
588 _registerPropertyOverrides(classElem, className, superclasses, allFields, | 593 _registerPropertyOverrides(classElem, className, superclasses, allFields, |
589 virtualFields, virtualFieldSymbols, staticFieldOverrides); | 594 virtualFields, virtualFieldSymbols, staticFieldOverrides); |
590 | 595 |
591 var classExpr = _emitClassExpression(classElem, | 596 var classExpr = _emitClassExpression(classElem, |
592 _emitClassMethods(node, ctors, fields, superclasses, virtualFields), | 597 _emitClassMethods(node, ctors, fields, superclasses, virtualFields), |
593 fields: allFields); | 598 fields: allFields); |
594 | 599 |
595 var body = <JS.Statement>[]; | 600 var body = <JS.Statement>[]; |
596 var extensions = _extensionsToImplement(classElem); | 601 var extensions = _extensionsToImplement(classElem); |
597 _initExtensionSymbols(classElem, methods, fields, body); | 602 _initExtensionSymbols(classElem, methods, fields, body); |
| 603 _emitSuperHelperSymbols(_superHelperSymbols, body); |
598 | 604 |
599 // Emit the class, e.g. `core.Object = class Object { ... }` | 605 // Emit the class, e.g. `core.Object = class Object { ... }` |
600 _defineClass(classElem, className, classExpr, body); | 606 _defineClass(classElem, className, classExpr, body); |
601 | 607 |
602 // Emit things that come after the ES6 `class ... { ... }`. | 608 // Emit things that come after the ES6 `class ... { ... }`. |
603 _setBaseClass(classElem, className, body); | 609 _setBaseClass(classElem, className, body); |
604 _defineNamedConstructors(ctors, body, className); | 610 _defineNamedConstructors(ctors, body, className); |
605 _emitVirtualFieldSymbols(virtualFieldSymbols, body); | 611 _emitVirtualFieldSymbols(virtualFieldSymbols, body); |
606 _emitClassSignature(methods, classElem, ctors, extensions, className, body); | 612 _emitClassSignature(methods, classElem, ctors, extensions, className, body); |
607 _defineExtensionMembers(extensions, className, body); | 613 _defineExtensionMembers(extensions, className, body); |
608 _emitClassMetadata(node.metadata, className, body); | 614 _emitClassMetadata(node.metadata, className, body); |
609 | 615 |
610 JS.Statement classDef = _statement(body); | 616 JS.Statement classDef = _statement(body); |
611 var typeFormals = classElem.typeParameters; | 617 var typeFormals = classElem.typeParameters; |
612 if (typeFormals.isNotEmpty) { | 618 if (typeFormals.isNotEmpty) { |
613 classDef = _defineClassTypeArguments(classElem, typeFormals, classDef); | 619 classDef = _defineClassTypeArguments(classElem, typeFormals, classDef); |
614 } | 620 } |
615 | 621 |
616 body = <JS.Statement>[classDef]; | 622 body = <JS.Statement>[classDef]; |
617 _emitStaticFields(staticFields, staticFieldOverrides, classElem, body); | 623 _emitStaticFields(staticFields, staticFieldOverrides, classElem, body); |
618 _registerExtensionType(classElem, body); | 624 _registerExtensionType(classElem, body); |
619 return _statement(body); | 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 void _registerPropertyOverrides( | 636 void _registerPropertyOverrides( |
623 ClassElement classElem, | 637 ClassElement classElem, |
624 JS.Expression className, | 638 JS.Expression className, |
625 List<ClassElement> superclasses, | 639 List<ClassElement> superclasses, |
626 List<FieldDeclaration> fields, | 640 List<FieldDeclaration> fields, |
627 Map<FieldElement, JS.TemporaryId> virtualFields, | 641 Map<FieldElement, JS.TemporaryId> virtualFields, |
628 List<JS.Statement> virtualFieldSymbols, | 642 List<JS.Statement> virtualFieldSymbols, |
629 Set<FieldElement> staticFieldOverrides) { | 643 Set<FieldElement> staticFieldOverrides) { |
630 for (var field in fields) { | 644 for (var field in fields) { |
631 for (VariableDeclaration field in field.fields.variables) { | 645 for (VariableDeclaration field in field.fields.variables) { |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
890 // helper on a parent class. This pattern is common in the core libraries | 904 // helper on a parent class. This pattern is common in the core libraries |
891 // (e.g. IterableMixin<E> and IterableBase<E>). | 905 // (e.g. IterableMixin<E> and IterableBase<E>). |
892 // | 906 // |
893 // (We could do this same optimization for any interface with an `iterator` | 907 // (We could do this same optimization for any interface with an `iterator` |
894 // method, but that's more expensive to check for, so it doesn't seem worth | 908 // method, but that's more expensive to check for, so it doesn't seem worth |
895 // it. The above case for an explicit `iterator` method will catch those.) | 909 // it. The above case for an explicit `iterator` method will catch those.) |
896 if (!hasJsPeer && !hasIterator && _implementsIterable(type)) { | 910 if (!hasJsPeer && !hasIterator && _implementsIterable(type)) { |
897 jsMethods.add(_emitIterable(type)); | 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 return jsMethods.where((m) => m != null).toList(growable: false); | 918 return jsMethods.where((m) => m != null).toList(growable: false); |
901 } | 919 } |
902 | 920 |
903 /// This is called whenever a derived class needs to introduce a new field, | 921 /// This is called whenever a derived class needs to introduce a new field, |
904 /// shadowing a field or getter/setter pair on its parent. | 922 /// shadowing a field or getter/setter pair on its parent. |
905 /// | 923 /// |
906 /// This is important because otherwise, trying to read or write the field | 924 /// This is important because otherwise, trying to read or write the field |
907 /// would end up calling the getter or setter, and one of those might not even | 925 /// would end up calling the getter or setter, and one of those might not even |
908 /// exist, resulting in a runtime error. Even if they did exist, that's the | 926 /// exist, resulting in a runtime error. Even if they did exist, that's the |
909 /// wrong behavior if a new field was declared. | 927 /// wrong behavior if a new field was declared. |
(...skipping 713 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1623 return new JS.Fun(params, js.statement('{ return this.#; }', [name])); | 1641 return new JS.Fun(params, js.statement('{ return this.#; }', [name])); |
1624 } else if (node.isSetter) { | 1642 } else if (node.isSetter) { |
1625 return new JS.Fun( | 1643 return new JS.Fun( |
1626 params, js.statement('{ this.# = #; }', [name, params.last])); | 1644 params, js.statement('{ this.# = #; }', [name, params.last])); |
1627 } else { | 1645 } else { |
1628 return new JS.Fun( | 1646 return new JS.Fun( |
1629 params, js.statement('{ return this.#(#); }', [name, params])); | 1647 params, js.statement('{ return this.#(#); }', [name, params])); |
1630 } | 1648 } |
1631 } | 1649 } |
1632 | 1650 |
1633 JS.Method _emitMethodDeclaration(DartType type, MethodDeclaration node) { | 1651 JS.Method _emitMethodDeclaration(InterfaceType type, MethodDeclaration node) { |
1634 if (node.isAbstract) { | 1652 if (node.isAbstract) { |
1635 return null; | 1653 return null; |
1636 } | 1654 } |
1637 | 1655 |
1638 JS.Fun fn; | 1656 JS.Fun fn; |
1639 if (_externalOrNative(node)) { | 1657 if (_externalOrNative(node)) { |
1640 fn = _emitNativeFunctionBody(node); | 1658 fn = _emitNativeFunctionBody(node); |
1641 // TODO(vsm): Remove if / when we handle the static case above. | 1659 // TODO(vsm): Remove if / when we handle the static case above. |
1642 if (fn == null) return null; | 1660 if (fn == null) return null; |
1643 } else { | 1661 } else { |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1949 // `await` is generated as `yield`. | 1967 // `await` is generated as `yield`. |
1950 // runtime/_generators.js has an example of what the code is generated as. | 1968 // runtime/_generators.js has an example of what the code is generated as. |
1951 var savedController = _asyncStarController; | 1969 var savedController = _asyncStarController; |
1952 List jsParams = visitFormalParameterList(parameters); | 1970 List jsParams = visitFormalParameterList(parameters); |
1953 if (kind == 'asyncStar') { | 1971 if (kind == 'asyncStar') { |
1954 _asyncStarController = new JS.TemporaryId('stream'); | 1972 _asyncStarController = new JS.TemporaryId('stream'); |
1955 jsParams.insert(0, _asyncStarController); | 1973 jsParams.insert(0, _asyncStarController); |
1956 } else { | 1974 } else { |
1957 _asyncStarController = null; | 1975 _asyncStarController = null; |
1958 } | 1976 } |
| 1977 var savedSuperAllowed = _superAllowed; |
| 1978 _superAllowed = false; |
1959 // Visit the body with our async* controller set. | 1979 // Visit the body with our async* controller set. |
1960 var jsBody = _visit(body); | 1980 var jsBody = _visit(body); |
| 1981 _superAllowed = savedSuperAllowed; |
1961 _asyncStarController = savedController; | 1982 _asyncStarController = savedController; |
1962 | 1983 |
1963 DartType returnType = _getExpectedReturnType(element); | 1984 DartType returnType = _getExpectedReturnType(element); |
1964 JS.Expression gen = new JS.Fun(jsParams, jsBody, | 1985 JS.Expression gen = new JS.Fun(jsParams, jsBody, |
1965 isGenerator: true, returnType: emitTypeRef(returnType)); | 1986 isGenerator: true, returnType: emitTypeRef(returnType)); |
1966 if (JS.This.foundIn(gen)) { | 1987 if (JS.This.foundIn(gen)) { |
1967 gen = js.call('#.bind(this)', gen); | 1988 gen = js.call('#.bind(this)', gen); |
1968 } | 1989 } |
1969 | 1990 |
1970 var T = _emitTypeName(returnType); | 1991 var T = _emitTypeName(returnType); |
(...skipping 25 matching lines...) Expand all Loading... |
1996 return new JS.Block([ | 2017 return new JS.Block([ |
1997 declareFn, | 2018 declareFn, |
1998 _emitFunctionTagged(name, func.element.type).toStatement() | 2019 _emitFunctionTagged(name, func.element.type).toStatement() |
1999 ]); | 2020 ]); |
2000 } | 2021 } |
2001 | 2022 |
2002 /// Emits a simple identifier, including handling an inferred generic | 2023 /// Emits a simple identifier, including handling an inferred generic |
2003 /// function instantiation. | 2024 /// function instantiation. |
2004 @override | 2025 @override |
2005 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { | 2026 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { |
2006 return _applyFunctionTypeArguments( | 2027 var typeArgs = _getTypeArgs(node.staticElement, node.staticType); |
2007 _emitSimpleIdentifier(node), 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 /// Emits a simple identifier, handling implicit `this` as well as | 2035 /// Emits a simple identifier, handling implicit `this` as well as |
2011 /// going through the qualified library name if necessary, but *not* handling | 2036 /// going through the qualified library name if necessary, but *not* handling |
2012 /// inferred generic function instantiation. | 2037 /// inferred generic function instantiation. |
2013 JS.Expression _emitSimpleIdentifier(SimpleIdentifier node) { | 2038 JS.Expression _emitSimpleIdentifier(SimpleIdentifier node) { |
2014 var accessor = node.staticElement; | 2039 var accessor = node.staticElement; |
2015 if (accessor == null) { | 2040 if (accessor == null) { |
2016 return js.commentExpression( | 2041 return js.commentExpression( |
2017 'Unimplemented unknown name', new JS.Identifier(node.name)); | 2042 'Unimplemented unknown name', new JS.Identifier(node.name)); |
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2377 if (result != null) return result; | 2402 if (result != null) return result; |
2378 | 2403 |
2379 var target = _getTarget(node); | 2404 var target = _getTarget(node); |
2380 if (target == null || isLibraryPrefix(target)) { | 2405 if (target == null || isLibraryPrefix(target)) { |
2381 return _emitFunctionCall(node); | 2406 return _emitFunctionCall(node); |
2382 } | 2407 } |
2383 | 2408 |
2384 return _emitMethodCall(target, node); | 2409 return _emitMethodCall(target, node); |
2385 } | 2410 } |
2386 | 2411 |
| 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 |
2387 /// Emits a (possibly generic) instance method call. | 2459 /// Emits a (possibly generic) instance method call. |
2388 JS.Expression _emitMethodCall(Expression target, MethodInvocation node) { | 2460 JS.Expression _emitMethodCallInternal( |
| 2461 Expression target, |
| 2462 MethodInvocation node, |
| 2463 List<JS.Expression> args, |
| 2464 List<JS.Expression> typeArgs) { |
2389 var type = getStaticType(target); | 2465 var type = getStaticType(target); |
2390 var name = node.methodName.name; | 2466 var name = node.methodName.name; |
2391 var element = node.methodName.staticElement; | 2467 var element = node.methodName.staticElement; |
2392 bool isStatic = element is ExecutableElement && element.isStatic; | 2468 bool isStatic = element is ExecutableElement && element.isStatic; |
2393 var memberName = _emitMemberName(name, type: type, isStatic: isStatic); | 2469 var memberName = _emitMemberName(name, type: type, isStatic: isStatic); |
2394 | 2470 |
2395 JS.Expression jsTarget = _visit(target); | 2471 JS.Expression jsTarget = _visit(target); |
2396 var typeArgs = _emitInvokeTypeArguments(node); | |
2397 List<JS.Expression> args = _visit(node.argumentList); | |
2398 if (DynamicInvoke.get(target)) { | 2472 if (DynamicInvoke.get(target)) { |
2399 if (typeArgs != null) { | 2473 if (typeArgs != null) { |
2400 return js.call('dart.dgsend(#, #, #, #)', | 2474 return js.call('dart.dgsend(#, #, #, #)', |
2401 [jsTarget, new JS.ArrayInitializer(typeArgs), memberName, args]); | 2475 [jsTarget, new JS.ArrayInitializer(typeArgs), memberName, args]); |
2402 } else { | 2476 } else { |
2403 return js.call('dart.dsend(#, #, #)', [jsTarget, memberName, args]); | 2477 return js.call('dart.dsend(#, #, #)', [jsTarget, memberName, args]); |
2404 } | 2478 } |
2405 } | 2479 } |
2406 if (_isObjectMemberCall(target, name)) { | 2480 if (_isObjectMemberCall(target, name)) { |
2407 // Object methods require a helper for null checks & native types. | 2481 // Object methods require a helper for null checks & native types. |
2408 assert(typeArgs == null); // Object methods don't take type args. | 2482 assert(typeArgs == null); // Object methods don't take type args. |
2409 return js.call('dart.#(#, #)', [memberName, jsTarget, args]); | 2483 return js.call('dart.#(#, #)', [memberName, jsTarget, args]); |
2410 } | 2484 } |
2411 | 2485 |
2412 jsTarget = new JS.PropertyAccess(jsTarget, memberName); | 2486 jsTarget = new JS.PropertyAccess(jsTarget, memberName); |
| 2487 |
2413 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs); | 2488 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs); |
2414 | 2489 |
2415 if (DynamicInvoke.get(node.methodName)) { | 2490 if (DynamicInvoke.get(node.methodName)) { |
2416 // This is a dynamic call to a statically known target. For example: | 2491 // This is a dynamic call to a statically known target. For example: |
2417 // class Foo { Function bar; } | 2492 // class Foo { Function bar; } |
2418 // new Foo().bar(); // dynamic call | 2493 // new Foo().bar(); // dynamic call |
2419 return js.call('dart.dcall(#, #)', [jsTarget, args]); | 2494 return js.call('dart.dcall(#, #)', [jsTarget, args]); |
2420 } | 2495 } |
2421 | 2496 |
2422 return new JS.Call(jsTarget, args); | 2497 return new JS.Call(jsTarget, args); |
(...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3537 (_extensionTypes.hasNativeSubtype(type) && target is! SuperExpression); | 3612 (_extensionTypes.hasNativeSubtype(type) && target is! SuperExpression); |
3538 } | 3613 } |
3539 | 3614 |
3540 /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. | 3615 /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. |
3541 JS.Expression _emitAccess( | 3616 JS.Expression _emitAccess( |
3542 Expression target, SimpleIdentifier memberId, DartType resultType) { | 3617 Expression target, SimpleIdentifier memberId, DartType resultType) { |
3543 Element member = memberId.staticElement; | 3618 Element member = memberId.staticElement; |
3544 if (member is PropertyAccessorElement) { | 3619 if (member is PropertyAccessorElement) { |
3545 member = (member as PropertyAccessorElement).variable; | 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 bool isStatic = member is ClassMemberElement && member.isStatic; | 3659 bool isStatic = member is ClassMemberElement && member.isStatic; |
3548 var name = _emitMemberName(memberId.name, | 3660 var name = _emitMemberName(memberName, |
3549 type: getStaticType(target), isStatic: isStatic); | 3661 type: getStaticType(target), isStatic: isStatic); |
3550 if (DynamicInvoke.get(target)) { | 3662 if (DynamicInvoke.get(target)) { |
3551 return js.call('dart.dload(#, #)', [_visit(target), name]); | 3663 return js.call('dart.dload(#, #)', [_visit(target), name]); |
3552 } | 3664 } |
3553 | 3665 |
3554 var jsTarget = _visit(target); | 3666 var jsTarget = _visit(target); |
3555 bool isSuper = jsTarget is JS.Super; | 3667 bool isSuper = jsTarget is JS.Super; |
3556 | 3668 |
3557 if (isSuper && member is FieldElement && !member.isSynthetic) { | 3669 if (isSuper && member is FieldElement && !member.isSynthetic) { |
3558 // If super.x is actually a field, then x is an instance property since | 3670 // If super.x is actually a field, then x is an instance property since |
3559 // subclasses cannot override x. | 3671 // subclasses cannot override x. |
3560 jsTarget = new JS.This(); | 3672 jsTarget = new JS.This(); |
3561 } | 3673 } |
3562 | 3674 |
3563 JS.Expression result; | 3675 JS.Expression result; |
3564 if (member != null && member is MethodElement && !isStatic) { | 3676 if (member != null && member is MethodElement && !isStatic) { |
3565 // Tear-off methods: explicitly bind it. | 3677 // Tear-off methods: explicitly bind it. |
3566 if (isSuper) { | 3678 if (isSuper) { |
3567 result = js.call('dart.bind(this, #, #.#)', [name, jsTarget, name]); | 3679 result = js.call('dart.bind(this, #, #.#)', [name, jsTarget, name]); |
3568 } else if (_isObjectMemberCall(target, memberId.name)) { | 3680 } else if (_isObjectMemberCall(target, memberName)) { |
3569 result = js.call('dart.bind(#, #, dart.#)', [jsTarget, name, name]); | 3681 result = js.call('dart.bind(#, #, dart.#)', [jsTarget, name, name]); |
3570 } else { | 3682 } else { |
3571 result = js.call('dart.bind(#, #)', [jsTarget, name]); | 3683 result = js.call('dart.bind(#, #)', [jsTarget, name]); |
3572 } | 3684 } |
3573 } else if (_isObjectMemberCall(target, memberId.name)) { | 3685 } else if (_isObjectMemberCall(target, memberName)) { |
3574 result = js.call('dart.#(#)', [name, jsTarget]); | 3686 result = js.call('dart.#(#)', [name, jsTarget]); |
3575 } else { | 3687 } else { |
3576 result = js.call('#.#', [jsTarget, name]); | 3688 result = js.call('#.#', [jsTarget, name]); |
3577 } | 3689 } |
3578 return _applyFunctionTypeArguments(result, member, resultType); | 3690 if (typeArgs == null) { |
3579 } | 3691 return result; |
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; | |
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 return js.call('dart.gbind(#, #)', [result, typeArgs]); | 3693 return js.call('dart.gbind(#, #)', [result, typeArgs]); |
3597 } | 3694 } |
3598 | 3695 |
3599 /// Emits a generic send, like an operator method. | 3696 /// Emits a generic send, like an operator method. |
3600 /// | 3697 /// |
3601 /// **Please note** this function does not support method invocation syntax | 3698 /// **Please note** this function does not support method invocation syntax |
3602 /// `obj.name(args)` because that could be a getter followed by a call. | 3699 /// `obj.name(args)` because that could be a getter followed by a call. |
3603 /// See [visitMethodInvocation]. | 3700 /// See [visitMethodInvocation]. |
3604 JS.Expression _emitSend( | 3701 JS.Expression _emitSend( |
3605 Expression target, String name, List<Expression> args) { | 3702 Expression target, String name, List<Expression> args) { |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3783 } | 3880 } |
3784 | 3881 |
3785 @override | 3882 @override |
3786 visitContinueStatement(ContinueStatement node) { | 3883 visitContinueStatement(ContinueStatement node) { |
3787 var label = node.label; | 3884 var label = node.label; |
3788 return new JS.Continue(label?.name); | 3885 return new JS.Continue(label?.name); |
3789 } | 3886 } |
3790 | 3887 |
3791 @override | 3888 @override |
3792 visitTryStatement(TryStatement node) { | 3889 visitTryStatement(TryStatement node) { |
3793 return new JS.Try(_visit(node.body), _visitCatch(node.catchClauses), | 3890 var savedSuperAllowed = _superAllowed; |
3794 _visit(node.finallyBlock)); | 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 _visitCatch(NodeList<CatchClause> clauses) { | 3898 _visitCatch(NodeList<CatchClause> clauses) { |
3798 if (clauses == null || clauses.isEmpty) return null; | 3899 if (clauses == null || clauses.isEmpty) return null; |
3799 | 3900 |
3800 // TODO(jmesserly): need a better way to get a temporary variable. | 3901 // TODO(jmesserly): need a better way to get a temporary variable. |
3801 // This could incorrectly shadow a user's name. | 3902 // This could incorrectly shadow a user's name. |
3802 var savedCatch = _catchParameter; | 3903 var savedCatch = _catchParameter; |
3803 | 3904 |
3804 if (clauses.length == 1 && clauses.single.exceptionParameter != null) { | 3905 if (clauses.length == 1 && clauses.single.exceptionParameter != null) { |
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4292 } | 4393 } |
4293 | 4394 |
4294 bool isLibraryPrefix(Expression node) => | 4395 bool isLibraryPrefix(Expression node) => |
4295 node is SimpleIdentifier && node.staticElement is PrefixElement; | 4396 node is SimpleIdentifier && node.staticElement is PrefixElement; |
4296 | 4397 |
4297 LibraryElement _getLibrary(AnalysisContext c, String uri) => | 4398 LibraryElement _getLibrary(AnalysisContext c, String uri) => |
4298 c.computeLibraryElement(c.sourceFactory.forUri(uri)); | 4399 c.computeLibraryElement(c.sourceFactory.forUri(uri)); |
4299 | 4400 |
4300 bool _isDartRuntime(LibraryElement l) => | 4401 bool _isDartRuntime(LibraryElement l) => |
4301 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; | 4402 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; |
OLD | NEW |