| 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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 /// Usually a [SimpleIdentifier], but it can also be other expressions | 74 /// Usually a [SimpleIdentifier], but it can also be other expressions |
| 75 /// that are safe to evaluate multiple times, such as `this`. | 75 /// that are safe to evaluate multiple times, such as `this`. |
| 76 Expression _cascadeTarget; | 76 Expression _cascadeTarget; |
| 77 | 77 |
| 78 /// The variable for the current catch clause | 78 /// The variable for the current catch clause |
| 79 SimpleIdentifier _catchParameter; | 79 SimpleIdentifier _catchParameter; |
| 80 | 80 |
| 81 /// In an async* function, this represents the stream controller parameter. | 81 /// In an async* function, this represents the stream controller parameter. |
| 82 JS.TemporaryId _asyncStarController; | 82 JS.TemporaryId _asyncStarController; |
| 83 | 83 |
| 84 /// The top-level reference to 'self' if this is a library tagged with @JS() |
| 85 JS.TemporaryId _self; |
| 86 |
| 84 final _privateNames = | 87 final _privateNames = |
| 85 new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>(); | 88 new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>(); |
| 86 final _initializingFormalTemps = | 89 final _initializingFormalTemps = |
| 87 new HashMap<ParameterElement, JS.TemporaryId>(); | 90 new HashMap<ParameterElement, JS.TemporaryId>(); |
| 88 | 91 |
| 89 final _dartxVar = new JS.Identifier('dartx'); | 92 final _dartxVar = new JS.Identifier('dartx'); |
| 90 final _runtimeLibVar = new JS.Identifier('dart'); | 93 final _runtimeLibVar = new JS.Identifier('dart'); |
| 91 final namedArgumentTemp = new JS.TemporaryId('opts'); | 94 final namedArgumentTemp = new JS.TemporaryId('opts'); |
| 92 | 95 |
| 93 final _hasDeferredSupertype = new HashSet<ClassElement>(); | 96 final _hasDeferredSupertype = new HashSet<ClassElement>(); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 _libraries[library] = libraryTemp; | 215 _libraries[library] = libraryTemp; |
| 213 items.add(new JS.ExportDeclaration( | 216 items.add(new JS.ExportDeclaration( |
| 214 js.call('const # = Object.create(null)', [libraryTemp]))); | 217 js.call('const # = Object.create(null)', [libraryTemp]))); |
| 215 | 218 |
| 216 // dart:_runtime has a magic module that holds extenstion method symbols. | 219 // dart:_runtime has a magic module that holds extenstion method symbols. |
| 217 // TODO(jmesserly): find a cleaner design for this. | 220 // TODO(jmesserly): find a cleaner design for this. |
| 218 if (_isDartRuntime(library)) { | 221 if (_isDartRuntime(library)) { |
| 219 items.add(new JS.ExportDeclaration( | 222 items.add(new JS.ExportDeclaration( |
| 220 js.call('const # = Object.create(null)', [_dartxVar]))); | 223 js.call('const # = Object.create(null)', [_dartxVar]))); |
| 221 } | 224 } |
| 225 |
| 226 if (findAnnotation(library, isPublicJSAnnotation) != null) { |
| 227 _self = new JS.TemporaryId('self'); |
| 228 items.add(js.statement('const # = window;', [_self])); |
| 229 } |
| 222 } | 230 } |
| 223 | 231 |
| 224 // Collect all Element -> Node mappings, in case we need to forward declare | 232 // Collect all Element -> Node mappings, in case we need to forward declare |
| 225 // any nodes. | 233 // any nodes. |
| 226 var nodes = new HashMap<Element, AstNode>.identity(); | 234 var nodes = new HashMap<Element, AstNode>.identity(); |
| 227 var sdkBootstrappingFns = new List<FunctionElement>(); | 235 var sdkBootstrappingFns = new List<FunctionElement>(); |
| 228 for (var unit in compilationUnits) { | 236 for (var unit in compilationUnits) { |
| 229 if (_isDartRuntime(unit.element.library)) { | 237 if (_isDartRuntime(unit.element.library)) { |
| 230 sdkBootstrappingFns.addAll(unit.element.functions); | 238 sdkBootstrappingFns.addAll(unit.element.functions); |
| 231 } | 239 } |
| (...skipping 2086 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2318 if (jsArgs != null) { | 2326 if (jsArgs != null) { |
| 2319 var genericName = _emitTopLevelName(element, suffix: '\$'); | 2327 var genericName = _emitTopLevelName(element, suffix: '\$'); |
| 2320 return js.call('#(#)', [genericName, jsArgs]); | 2328 return js.call('#(#)', [genericName, jsArgs]); |
| 2321 } | 2329 } |
| 2322 } | 2330 } |
| 2323 | 2331 |
| 2324 return _emitTopLevelName(element); | 2332 return _emitTopLevelName(element); |
| 2325 } | 2333 } |
| 2326 | 2334 |
| 2327 JS.PropertyAccess _emitTopLevelName(Element e, {String suffix: ''}) { | 2335 JS.PropertyAccess _emitTopLevelName(Element e, {String suffix: ''}) { |
| 2336 if (e is TopLevelVariableElement && |
| 2337 e.getter != null && |
| 2338 findAnnotation(e.getter, isPublicJSAnnotation) != null) { |
| 2339 var annotationName = getAnnotationName(e.getter, isPublicJSAnnotation); |
| 2340 var name = js.string(annotationName ?? e.name); |
| 2341 return new JS.PropertyAccess(_self, name); |
| 2342 } |
| 2328 String name = getJSExportName(e) + suffix; | 2343 String name = getJSExportName(e) + suffix; |
| 2329 return new JS.PropertyAccess( | 2344 return new JS.PropertyAccess( |
| 2330 emitLibraryName(e.library), _propertyName(name)); | 2345 emitLibraryName(e.library), _propertyName(name)); |
| 2331 } | 2346 } |
| 2332 | 2347 |
| 2333 @override | 2348 @override |
| 2334 JS.Expression visitAssignmentExpression(AssignmentExpression node) { | 2349 JS.Expression visitAssignmentExpression(AssignmentExpression node) { |
| 2335 var left = node.leftHandSide; | 2350 var left = node.leftHandSide; |
| 2336 var right = node.rightHandSide; | 2351 var right = node.rightHandSide; |
| 2337 if (node.operator.type == TokenType.EQ) return _emitSet(left, right); | 2352 if (node.operator.type == TokenType.EQ) return _emitSet(left, right); |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2518 MethodInvocation node, | 2533 MethodInvocation node, |
| 2519 List<JS.Expression> args, | 2534 List<JS.Expression> args, |
| 2520 List<JS.Expression> typeArgs) { | 2535 List<JS.Expression> typeArgs) { |
| 2521 var type = getStaticType(target); | 2536 var type = getStaticType(target); |
| 2522 var name = node.methodName.name; | 2537 var name = node.methodName.name; |
| 2523 var element = node.methodName.staticElement; | 2538 var element = node.methodName.staticElement; |
| 2524 bool isStatic = element is ExecutableElement && element.isStatic; | 2539 bool isStatic = element is ExecutableElement && element.isStatic; |
| 2525 var memberName = _emitMemberName(name, type: type, isStatic: isStatic); | 2540 var memberName = _emitMemberName(name, type: type, isStatic: isStatic); |
| 2526 | 2541 |
| 2527 JS.Expression jsTarget = _visit(target); | 2542 JS.Expression jsTarget = _visit(target); |
| 2528 if (DynamicInvoke.get(target)) { | 2543 if (DynamicInvoke.get(target) || DynamicInvoke.get(node.methodName)) { |
| 2529 if (typeArgs != null) { | 2544 if (typeArgs != null) { |
| 2530 return js.call('dart.dgsend(#, #, #, #)', | 2545 return js.call('dart.dgsend(#, #, #, #)', |
| 2531 [jsTarget, new JS.ArrayInitializer(typeArgs), memberName, args]); | 2546 [jsTarget, new JS.ArrayInitializer(typeArgs), memberName, args]); |
| 2532 } else { | 2547 } else { |
| 2533 return js.call('dart.dsend(#, #, #)', [jsTarget, memberName, args]); | 2548 return js.call('dart.dsend(#, #, #)', [jsTarget, memberName, args]); |
| 2534 } | 2549 } |
| 2535 } | 2550 } |
| 2536 if (_isObjectMemberCall(target, name)) { | 2551 if (_isObjectMemberCall(target, name)) { |
| 2537 assert(typeArgs == null); // Object methods don't take type args. | 2552 assert(typeArgs == null); // Object methods don't take type args. |
| 2538 return js.call('dart.#(#, #)', [name, jsTarget, args]); | 2553 return js.call('dart.#(#, #)', [name, jsTarget, args]); |
| 2539 } | 2554 } |
| 2540 | 2555 |
| 2541 jsTarget = new JS.PropertyAccess(jsTarget, memberName); | 2556 jsTarget = new JS.PropertyAccess(jsTarget, memberName); |
| 2542 | |
| 2543 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs); | 2557 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs); |
| 2544 | 2558 |
| 2545 if (DynamicInvoke.get(node.methodName)) { | |
| 2546 // This is a dynamic call to a statically known target. For example: | |
| 2547 // class Foo { Function bar; } | |
| 2548 // new Foo().bar(); // dynamic call | |
| 2549 return js.call('dart.dcall(#, #)', [jsTarget, args]); | |
| 2550 } | |
| 2551 | |
| 2552 return new JS.Call(jsTarget, args); | 2559 return new JS.Call(jsTarget, args); |
| 2553 } | 2560 } |
| 2554 | 2561 |
| 2555 /// Emits a function call, to a top-level function, local function, or | 2562 /// Emits a function call, to a top-level function, local function, or |
| 2556 /// an expression. | 2563 /// an expression. |
| 2557 JS.Expression _emitFunctionCall(InvocationExpression node) { | 2564 JS.Expression _emitFunctionCall(InvocationExpression node) { |
| 2558 var fn = _visit(node.function); | 2565 var fn = _visit(node.function); |
| 2559 var args = _visit(node.argumentList); | 2566 var args = _visit(node.argumentList); |
| 2560 if (DynamicInvoke.get(node.function)) { | 2567 if (DynamicInvoke.get(node.function)) { |
| 2561 var typeArgs = _emitInvokeTypeArguments(node); | 2568 var typeArgs = _emitInvokeTypeArguments(node); |
| (...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3020 } | 3027 } |
| 3021 return null; | 3028 return null; |
| 3022 } | 3029 } |
| 3023 | 3030 |
| 3024 JS.Expression _emitConstructorName( | 3031 JS.Expression _emitConstructorName( |
| 3025 ConstructorElement element, DartType type, SimpleIdentifier name) { | 3032 ConstructorElement element, DartType type, SimpleIdentifier name) { |
| 3026 var classElem = element.enclosingElement; | 3033 var classElem = element.enclosingElement; |
| 3027 if (findAnnotation(classElem, isPublicJSAnnotation) != null) { | 3034 if (findAnnotation(classElem, isPublicJSAnnotation) != null) { |
| 3028 var annotationName = getAnnotationName(classElem, isPublicJSAnnotation); | 3035 var annotationName = getAnnotationName(classElem, isPublicJSAnnotation); |
| 3029 var typeName = js.string(annotationName ?? classElem.name); | 3036 var typeName = js.string(annotationName ?? classElem.name); |
| 3030 return new JS.PropertyAccess(new JS.Identifier('self'), typeName); | 3037 return new JS.PropertyAccess(_self, typeName); |
| 3031 } | 3038 } |
| 3032 var typeName = _emitType(type); | 3039 var typeName = _emitType(type); |
| 3033 if (name != null || element.isFactory) { | 3040 if (name != null || element.isFactory) { |
| 3034 var namedCtor = _constructorName(element); | 3041 var namedCtor = _constructorName(element); |
| 3035 return new JS.PropertyAccess(typeName, namedCtor); | 3042 return new JS.PropertyAccess(typeName, namedCtor); |
| 3036 } | 3043 } |
| 3037 return typeName; | 3044 return typeName; |
| 3038 } | 3045 } |
| 3039 | 3046 |
| 3040 @override | 3047 @override |
| (...skipping 1423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4464 } | 4471 } |
| 4465 | 4472 |
| 4466 bool isLibraryPrefix(Expression node) => | 4473 bool isLibraryPrefix(Expression node) => |
| 4467 node is SimpleIdentifier && node.staticElement is PrefixElement; | 4474 node is SimpleIdentifier && node.staticElement is PrefixElement; |
| 4468 | 4475 |
| 4469 LibraryElement _getLibrary(AnalysisContext c, String uri) => | 4476 LibraryElement _getLibrary(AnalysisContext c, String uri) => |
| 4470 c.computeLibraryElement(c.sourceFactory.forUri(uri)); | 4477 c.computeLibraryElement(c.sourceFactory.forUri(uri)); |
| 4471 | 4478 |
| 4472 bool _isDartRuntime(LibraryElement l) => | 4479 bool _isDartRuntime(LibraryElement l) => |
| 4473 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; | 4480 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; |
| OLD | NEW |