| 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 | |
| 87 final _privateNames = | 84 final _privateNames = |
| 88 new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>(); | 85 new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>(); |
| 89 final _initializingFormalTemps = | 86 final _initializingFormalTemps = |
| 90 new HashMap<ParameterElement, JS.TemporaryId>(); | 87 new HashMap<ParameterElement, JS.TemporaryId>(); |
| 91 | 88 |
| 92 final _dartxVar = new JS.Identifier('dartx'); | 89 final _dartxVar = new JS.Identifier('dartx'); |
| 93 final _runtimeLibVar = new JS.Identifier('dart'); | 90 final _runtimeLibVar = new JS.Identifier('dart'); |
| 94 final namedArgumentTemp = new JS.TemporaryId('opts'); | 91 final namedArgumentTemp = new JS.TemporaryId('opts'); |
| 95 | 92 |
| 96 final _hasDeferredSupertype = new HashSet<ClassElement>(); | 93 final _hasDeferredSupertype = new HashSet<ClassElement>(); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 _libraries[library] = libraryTemp; | 214 _libraries[library] = libraryTemp; |
| 218 items.add(new JS.ExportDeclaration( | 215 items.add(new JS.ExportDeclaration( |
| 219 js.call('const # = Object.create(null)', [libraryTemp]))); | 216 js.call('const # = Object.create(null)', [libraryTemp]))); |
| 220 | 217 |
| 221 // dart:_runtime has a magic module that holds extenstion method symbols. | 218 // dart:_runtime has a magic module that holds extenstion method symbols. |
| 222 // TODO(jmesserly): find a cleaner design for this. | 219 // TODO(jmesserly): find a cleaner design for this. |
| 223 if (_isDartRuntime(library)) { | 220 if (_isDartRuntime(library)) { |
| 224 items.add(new JS.ExportDeclaration( | 221 items.add(new JS.ExportDeclaration( |
| 225 js.call('const # = Object.create(null)', [_dartxVar]))); | 222 js.call('const # = Object.create(null)', [_dartxVar]))); |
| 226 } | 223 } |
| 227 | |
| 228 if (findAnnotation(library, isPublicJSAnnotation) != null) { | |
| 229 _self = new JS.TemporaryId('self'); | |
| 230 items.add(js.statement('const # = window;', [_self])); | |
| 231 } | |
| 232 } | 224 } |
| 233 | 225 |
| 234 // Collect all Element -> Node mappings, in case we need to forward declare | 226 // Collect all Element -> Node mappings, in case we need to forward declare |
| 235 // any nodes. | 227 // any nodes. |
| 236 var nodes = new HashMap<Element, AstNode>.identity(); | 228 var nodes = new HashMap<Element, AstNode>.identity(); |
| 237 var sdkBootstrappingFns = new List<FunctionElement>(); | 229 var sdkBootstrappingFns = new List<FunctionElement>(); |
| 238 for (var unit in compilationUnits) { | 230 for (var unit in compilationUnits) { |
| 239 if (_isDartRuntime(unit.element.library)) { | 231 if (_isDartRuntime(unit.element.library)) { |
| 240 sdkBootstrappingFns.addAll(unit.element.functions); | 232 sdkBootstrappingFns.addAll(unit.element.functions); |
| 241 } | 233 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 269 switch (options.moduleFormat) { | 261 switch (options.moduleFormat) { |
| 270 case ModuleFormat.legacy: | 262 case ModuleFormat.legacy: |
| 271 return new LegacyModuleBuilder().build(module); | 263 return new LegacyModuleBuilder().build(module); |
| 272 case ModuleFormat.node: | 264 case ModuleFormat.node: |
| 273 return new NodeModuleBuilder().build(module); | 265 return new NodeModuleBuilder().build(module); |
| 274 case ModuleFormat.es6: | 266 case ModuleFormat.es6: |
| 275 return module; | 267 return module; |
| 276 } | 268 } |
| 277 } | 269 } |
| 278 | 270 |
| 271 List<String> _getJSName(Element e) { |
| 272 if (findAnnotation(e.library, isPublicJSAnnotation) == null) { |
| 273 return null; |
| 274 } |
| 275 |
| 276 var libraryJSName = getAnnotationName(e.library, isPublicJSAnnotation); |
| 277 var libraryPrefix = []; |
| 278 if (libraryJSName != null && libraryJSName.isNotEmpty) { |
| 279 libraryPrefix.addAll(libraryJSName.split('.')); |
| 280 } |
| 281 |
| 282 var elementJSName; |
| 283 if (findAnnotation(e, isPublicJSAnnotation) != null) { |
| 284 elementJSName = getAnnotationName(e, isPublicJSAnnotation) ?? ''; |
| 285 } |
| 286 if (e is TopLevelVariableElement && |
| 287 e.getter != null && |
| 288 (e.getter.isExternal || |
| 289 findAnnotation(e.getter, isPublicJSAnnotation) != null)) { |
| 290 elementJSName = getAnnotationName(e.getter, isPublicJSAnnotation) ?? ''; |
| 291 } |
| 292 if (elementJSName == null) return null; |
| 293 |
| 294 var elementJSParts = []; |
| 295 if (elementJSName.isNotEmpty) { |
| 296 elementJSParts.addAll(elementJSName.split('.')); |
| 297 } else { |
| 298 elementJSParts.add(e.name); |
| 299 } |
| 300 |
| 301 return libraryPrefix..addAll(elementJSParts); |
| 302 } |
| 303 |
| 304 JS.Expression _emitJSInterop(Element e) { |
| 305 var jsName = _getJSName(e); |
| 306 if (jsName == null) return null; |
| 307 var fullName = ['global']..addAll(jsName); |
| 308 var access = _runtimeLibVar; |
| 309 for (var part in fullName) { |
| 310 access = new JS.PropertyAccess(access, js.string(part)); |
| 311 } |
| 312 return access; |
| 313 } |
| 314 |
| 279 /// Flattens blocks in [items] to a single list. | 315 /// Flattens blocks in [items] to a single list. |
| 280 /// | 316 /// |
| 281 /// This will not flatten blocks that are marked as being scopes. | 317 /// This will not flatten blocks that are marked as being scopes. |
| 282 void _copyAndFlattenBlocks( | 318 void _copyAndFlattenBlocks( |
| 283 List<JS.ModuleItem> result, Iterable<JS.ModuleItem> items) { | 319 List<JS.ModuleItem> result, Iterable<JS.ModuleItem> items) { |
| 284 for (var item in items) { | 320 for (var item in items) { |
| 285 if (item is JS.Block && !item.isScope) { | 321 if (item is JS.Block && !item.isScope) { |
| 286 _copyAndFlattenBlocks(result, item.statements); | 322 _copyAndFlattenBlocks(result, item.statements); |
| 287 } else { | 323 } else { |
| 288 result.add(item); | 324 result.add(item); |
| (...skipping 2045 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2334 if (jsArgs != null) { | 2370 if (jsArgs != null) { |
| 2335 var genericName = _emitTopLevelName(element, suffix: '\$'); | 2371 var genericName = _emitTopLevelName(element, suffix: '\$'); |
| 2336 return js.call('#(#)', [genericName, jsArgs]); | 2372 return js.call('#(#)', [genericName, jsArgs]); |
| 2337 } | 2373 } |
| 2338 } | 2374 } |
| 2339 | 2375 |
| 2340 return _emitTopLevelName(element); | 2376 return _emitTopLevelName(element); |
| 2341 } | 2377 } |
| 2342 | 2378 |
| 2343 JS.PropertyAccess _emitTopLevelName(Element e, {String suffix: ''}) { | 2379 JS.PropertyAccess _emitTopLevelName(Element e, {String suffix: ''}) { |
| 2344 if (e is TopLevelVariableElement && | 2380 var interop = _emitJSInterop(e); |
| 2345 e.getter != null && | 2381 if (interop != null) return interop; |
| 2346 findAnnotation(e.getter, isPublicJSAnnotation) != null) { | |
| 2347 var annotationName = getAnnotationName(e.getter, isPublicJSAnnotation); | |
| 2348 var name = annotationName ?? e.name; | |
| 2349 JS.PropertyAccess result = null; | |
| 2350 for (var segment in name.split('.')) { | |
| 2351 result = new JS.PropertyAccess(result ?? _self, js.string(segment)); | |
| 2352 } | |
| 2353 return result; | |
| 2354 } | |
| 2355 String name = getJSExportName(e) + suffix; | 2382 String name = getJSExportName(e) + suffix; |
| 2356 return new JS.PropertyAccess( | 2383 return new JS.PropertyAccess( |
| 2357 emitLibraryName(e.library), _propertyName(name)); | 2384 emitLibraryName(e.library), _propertyName(name)); |
| 2358 } | 2385 } |
| 2359 | 2386 |
| 2360 @override | 2387 @override |
| 2361 JS.Expression visitAssignmentExpression(AssignmentExpression node) { | 2388 JS.Expression visitAssignmentExpression(AssignmentExpression node) { |
| 2362 var left = node.leftHandSide; | 2389 var left = node.leftHandSide; |
| 2363 var right = node.rightHandSide; | 2390 var right = node.rightHandSide; |
| 2364 if (node.operator.type == TokenType.EQ) return _emitSet(left, right); | 2391 if (node.operator.type == TokenType.EQ) return _emitSet(left, right); |
| (...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3036 return getter | 3063 return getter |
| 3037 ? parent.getGetter(element.name) | 3064 ? parent.getGetter(element.name) |
| 3038 : parent.getSetter(element.name); | 3065 : parent.getSetter(element.name); |
| 3039 } | 3066 } |
| 3040 return null; | 3067 return null; |
| 3041 } | 3068 } |
| 3042 | 3069 |
| 3043 JS.Expression _emitConstructorName( | 3070 JS.Expression _emitConstructorName( |
| 3044 ConstructorElement element, DartType type, SimpleIdentifier name) { | 3071 ConstructorElement element, DartType type, SimpleIdentifier name) { |
| 3045 var classElem = element.enclosingElement; | 3072 var classElem = element.enclosingElement; |
| 3046 if (findAnnotation(classElem, isPublicJSAnnotation) != null) { | 3073 var interop = _emitJSInterop(classElem); |
| 3047 var annotationName = getAnnotationName(classElem, isPublicJSAnnotation); | 3074 if (interop != null) return interop; |
| 3048 var typeName = js.string(annotationName ?? classElem.name); | |
| 3049 return new JS.PropertyAccess(_self, typeName); | |
| 3050 } | |
| 3051 var typeName = _emitType(type); | 3075 var typeName = _emitType(type); |
| 3052 if (name != null || element.isFactory) { | 3076 if (name != null || element.isFactory) { |
| 3053 var namedCtor = _constructorName(element); | 3077 var namedCtor = _constructorName(element); |
| 3054 return new JS.PropertyAccess(typeName, namedCtor); | 3078 return new JS.PropertyAccess(typeName, namedCtor); |
| 3055 } | 3079 } |
| 3056 return typeName; | 3080 return typeName; |
| 3057 } | 3081 } |
| 3058 | 3082 |
| 3059 @override | 3083 @override |
| 3060 visitConstructorName(ConstructorName node) { | 3084 visitConstructorName(ConstructorName node) { |
| (...skipping 1432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4493 } | 4517 } |
| 4494 | 4518 |
| 4495 bool isLibraryPrefix(Expression node) => | 4519 bool isLibraryPrefix(Expression node) => |
| 4496 node is SimpleIdentifier && node.staticElement is PrefixElement; | 4520 node is SimpleIdentifier && node.staticElement is PrefixElement; |
| 4497 | 4521 |
| 4498 LibraryElement _getLibrary(AnalysisContext c, String uri) => | 4522 LibraryElement _getLibrary(AnalysisContext c, String uri) => |
| 4499 c.computeLibraryElement(c.sourceFactory.forUri(uri)); | 4523 c.computeLibraryElement(c.sourceFactory.forUri(uri)); |
| 4500 | 4524 |
| 4501 bool _isDartRuntime(LibraryElement l) => | 4525 bool _isDartRuntime(LibraryElement l) => |
| 4502 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; | 4526 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; |
| OLD | NEW |