| 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 |