| 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 library js_codegen; | |
| 6 | |
| 7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; | 5 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; |
| 8 | 6 |
| 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 7 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
| 10 import 'package:analyzer/dart/ast/token.dart'; | 8 import 'package:analyzer/dart/ast/token.dart'; |
| 11 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; |
| 12 import 'package:analyzer/src/generated/constant.dart'; | 10 import 'package:analyzer/src/generated/constant.dart'; |
| 13 import 'package:analyzer/src/generated/element.dart'; | 11 import 'package:analyzer/src/generated/element.dart'; |
| 14 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; | 12 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; |
| 15 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; | 13 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; |
| 16 import 'package:analyzer/src/dart/ast/token.dart' | 14 import 'package:analyzer/src/dart/ast/token.dart' |
| 17 show StringToken, Token, TokenType; | 15 show StringToken, Token, TokenType; |
| 18 import 'package:analyzer/src/generated/type_system.dart' | 16 import 'package:analyzer/src/generated/type_system.dart' |
| 19 show StrongTypeSystemImpl; | 17 show StrongTypeSystemImpl; |
| 20 import 'package:analyzer/src/task/dart.dart' show PublicNamespaceBuilder; | 18 import 'package:analyzer/src/task/dart.dart' show PublicNamespaceBuilder; |
| 21 | 19 |
| 22 import 'ast_builder.dart' show AstBuilder; | 20 import 'ast_builder.dart' show AstBuilder; |
| 23 import 'reify_coercions.dart' show CoercionReifier, Tuple2; | 21 import 'reify_coercions.dart' show CoercionReifier, Tuple2; |
| 24 | 22 |
| 25 // TODO(jmesserly): import from its own package | |
| 26 import '../js/js_ast.dart' as JS; | 23 import '../js/js_ast.dart' as JS; |
| 27 import '../js/js_ast.dart' show js; | 24 import '../js/js_ast.dart' show js; |
| 28 | 25 |
| 29 import '../closure/closure_annotator.dart' show ClosureAnnotator; | 26 import '../closure/closure_annotator.dart' show ClosureAnnotator; |
| 30 import '../compiler.dart' | 27 import '../compiler.dart' |
| 31 show AbstractCompiler, corelibOrder, getCorelibModuleName; | 28 show AbstractCompiler, corelibOrder, getCorelibModuleName; |
| 32 import '../info.dart'; | 29 import '../info.dart'; |
| 33 import '../options.dart' show CodegenOptions; | 30 import '../options.dart' show CodegenOptions; |
| 34 import '../utils.dart'; | 31 import '../utils.dart'; |
| 35 | 32 |
| 36 import 'code_generator.dart'; | 33 import 'code_generator.dart'; |
| 37 import 'js_field_storage.dart'; | 34 import 'js_field_storage.dart'; |
| 38 import 'js_interop.dart'; | 35 import 'js_interop.dart'; |
| 39 import 'js_names.dart' as JS; | 36 import 'js_names.dart' as JS; |
| 40 import 'js_metalet.dart' as JS; | 37 import 'js_metalet.dart' as JS; |
| 41 import 'js_module_item_order.dart'; | 38 import 'js_module_item_order.dart'; |
| 42 import 'js_names.dart'; | 39 import 'js_names.dart'; |
| 43 import 'js_printer.dart' show writeJsLibrary; | 40 import 'js_printer.dart' show writeJsLibrary; |
| 41 import 'js_typeref_codegen.dart'; |
| 44 import 'module_builder.dart'; | 42 import 'module_builder.dart'; |
| 45 import 'nullability_inferrer.dart'; | 43 import 'nullability_inferrer.dart'; |
| 46 import 'side_effect_analysis.dart'; | 44 import 'side_effect_analysis.dart'; |
| 47 | 45 |
| 48 part 'js_typeref_codegen.dart'; | |
| 49 | |
| 50 // Various dynamic helpers we call. | 46 // Various dynamic helpers we call. |
| 51 // If renaming these, make sure to check other places like the | 47 // If renaming these, make sure to check other places like the |
| 52 // _runtime.js file and comments. | 48 // _runtime.js file and comments. |
| 53 // TODO(jmesserly): ideally we'd have a "dynamic call" dart library we can | 49 // TODO(jmesserly): ideally we'd have a "dynamic call" dart library we can |
| 54 // import and generate calls to, rather than dart_runtime.js | 50 // import and generate calls to, rather than dart_runtime.js |
| 55 const DPUT = 'dput'; | 51 const DPUT = 'dput'; |
| 56 const DLOAD = 'dload'; | 52 const DLOAD = 'dload'; |
| 57 const DINDEX = 'dindex'; | 53 const DINDEX = 'dindex'; |
| 58 const DSETINDEX = 'dsetindex'; | 54 const DSETINDEX = 'dsetindex'; |
| 59 const DCALL = 'dcall'; | 55 const DCALL = 'dcall'; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 final _privateNames = new HashMap<String, JS.TemporaryId>(); | 88 final _privateNames = new HashMap<String, JS.TemporaryId>(); |
| 93 final _moduleItems = <JS.Statement>[]; | 89 final _moduleItems = <JS.Statement>[]; |
| 94 final _temps = new HashMap<Element, JS.TemporaryId>(); | 90 final _temps = new HashMap<Element, JS.TemporaryId>(); |
| 95 final _qualifiedIds = new List<Tuple2<Element, JS.MaybeQualifiedId>>(); | 91 final _qualifiedIds = new List<Tuple2<Element, JS.MaybeQualifiedId>>(); |
| 96 | 92 |
| 97 /// The name for the library's exports inside itself. | 93 /// The name for the library's exports inside itself. |
| 98 /// `exports` was chosen as the most similar to ES module patterns. | 94 /// `exports` was chosen as the most similar to ES module patterns. |
| 99 final _dartxVar = new JS.Identifier('dartx'); | 95 final _dartxVar = new JS.Identifier('dartx'); |
| 100 final _exportsVar = new JS.TemporaryId('exports'); | 96 final _exportsVar = new JS.TemporaryId('exports'); |
| 101 final _runtimeLibVar = new JS.Identifier('dart'); | 97 final _runtimeLibVar = new JS.Identifier('dart'); |
| 102 final _namedArgTemp = new JS.TemporaryId('opts'); | 98 final namedArgumentTemp = new JS.TemporaryId('opts'); |
| 103 | 99 |
| 104 final TypeProvider _types; | 100 final TypeProvider _types; |
| 105 | 101 |
| 106 ConstFieldVisitor _constField; | 102 ConstFieldVisitor _constField; |
| 107 | 103 |
| 108 ModuleItemLoadOrder _loader; | 104 ModuleItemLoadOrder _loader; |
| 109 | 105 |
| 110 /// _interceptors.JSArray<E>, used for List literals. | 106 /// _interceptors.JSArray<E>, used for List literals. |
| 111 ClassElement _jsArray; | 107 ClassElement _jsArray; |
| 112 | 108 |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 _jsModuleValue = | 235 _jsModuleValue = |
| 240 getConstantField(jsName, 'name', types.stringType)?.toStringValue(); | 236 getConstantField(jsName, 'name', types.stringType)?.toStringValue(); |
| 241 } | 237 } |
| 242 | 238 |
| 243 @override | 239 @override |
| 244 void visitImportDirective(ImportDirective node) { | 240 void visitImportDirective(ImportDirective node) { |
| 245 // Nothing to do yet, but we'll want to convert this to an ES6 import once | 241 // Nothing to do yet, but we'll want to convert this to an ES6 import once |
| 246 // we have support for modules. | 242 // we have support for modules. |
| 247 } | 243 } |
| 248 | 244 |
| 249 @override void visitPartDirective(PartDirective node) {} | 245 @override |
| 250 @override void visitPartOfDirective(PartOfDirective node) {} | 246 void visitPartDirective(PartDirective node) {} |
| 247 @override |
| 248 void visitPartOfDirective(PartOfDirective node) {} |
| 251 | 249 |
| 252 @override | 250 @override |
| 253 void visitExportDirective(ExportDirective node) { | 251 void visitExportDirective(ExportDirective node) { |
| 254 var exportName = _libraryName(node.uriElement); | 252 var exportName = emitLibraryName(node.uriElement); |
| 255 | 253 |
| 256 var currentLibNames = currentLibrary.publicNamespace.definedNames; | 254 var currentLibNames = currentLibrary.publicNamespace.definedNames; |
| 257 | 255 |
| 258 var args = [_exportsVar, exportName]; | 256 var args = [_exportsVar, exportName]; |
| 259 if (node.combinators.isNotEmpty) { | 257 if (node.combinators.isNotEmpty) { |
| 260 var shownNames = <JS.Expression>[]; | 258 var shownNames = <JS.Expression>[]; |
| 261 var hiddenNames = <JS.Expression>[]; | 259 var hiddenNames = <JS.Expression>[]; |
| 262 | 260 |
| 263 var show = node.combinators.firstWhere((c) => c is ShowCombinator, | 261 var show = node.combinators.firstWhere((c) => c is ShowCombinator, |
| 264 orElse: () => null) as ShowCombinator; | 262 orElse: () => null) as ShowCombinator; |
| (...skipping 1068 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1333 | 1331 |
| 1334 if (param.kind == ParameterKind.NAMED) { | 1332 if (param.kind == ParameterKind.NAMED) { |
| 1335 if (!options.destructureNamedParams) { | 1333 if (!options.destructureNamedParams) { |
| 1336 // Parameters will be passed using their real names, not the (possibly | 1334 // Parameters will be passed using their real names, not the (possibly |
| 1337 // renamed) local variable. | 1335 // renamed) local variable. |
| 1338 var paramName = js.string(param.identifier.name, "'"); | 1336 var paramName = js.string(param.identifier.name, "'"); |
| 1339 | 1337 |
| 1340 // TODO(ochafik): Fix `'prop' in obj` to please Closure's renaming. | 1338 // TODO(ochafik): Fix `'prop' in obj` to please Closure's renaming. |
| 1341 body.add(js.statement('let # = # && # in # ? #.# : #;', [ | 1339 body.add(js.statement('let # = # && # in # ? #.# : #;', [ |
| 1342 jsParam, | 1340 jsParam, |
| 1343 _namedArgTemp, | 1341 namedArgumentTemp, |
| 1344 paramName, | 1342 paramName, |
| 1345 _namedArgTemp, | 1343 namedArgumentTemp, |
| 1346 _namedArgTemp, | 1344 namedArgumentTemp, |
| 1347 paramName, | 1345 paramName, |
| 1348 _defaultParamValue(param), | 1346 _defaultParamValue(param), |
| 1349 ])); | 1347 ])); |
| 1350 } | 1348 } |
| 1351 } else if (param.kind == ParameterKind.POSITIONAL && | 1349 } else if (param.kind == ParameterKind.POSITIONAL && |
| 1352 !options.destructureNamedParams) { | 1350 !options.destructureNamedParams) { |
| 1353 body.add(js.statement('if (# === void 0) # = #;', | 1351 body.add(js.statement('if (# === void 0) # = #;', |
| 1354 [jsParam, jsParam, _defaultParamValue(param)])); | 1352 [jsParam, jsParam, _defaultParamValue(param)])); |
| 1355 } | 1353 } |
| 1356 | 1354 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1447 | 1445 |
| 1448 return annotate( | 1446 return annotate( |
| 1449 new JS.Method(_elementMemberName(node.element), fn, | 1447 new JS.Method(_elementMemberName(node.element), fn, |
| 1450 isGetter: node.isGetter, | 1448 isGetter: node.isGetter, |
| 1451 isSetter: node.isSetter, | 1449 isSetter: node.isSetter, |
| 1452 isStatic: node.isStatic), | 1450 isStatic: node.isStatic), |
| 1453 node, | 1451 node, |
| 1454 node.element); | 1452 node.element); |
| 1455 } | 1453 } |
| 1456 | 1454 |
| 1457 /// Returns the name value of the `JSExportName` annotation (when compiling | |
| 1458 /// the SDK), or `null` if there's none. This is used to control the name | |
| 1459 /// under which functions are compiled and exported. | |
| 1460 String _getJSExportName(Element e) { | |
| 1461 if (!e.source.isInSystemLibrary) { | |
| 1462 return null; | |
| 1463 } | |
| 1464 var jsName = findAnnotation(e, isJSExportNameAnnotation); | |
| 1465 return getConstantField(jsName, 'name', types.stringType)?.toStringValue(); | |
| 1466 } | |
| 1467 | |
| 1468 @override | 1455 @override |
| 1469 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { | 1456 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { |
| 1470 assert(node.parent is CompilationUnit); | 1457 assert(node.parent is CompilationUnit); |
| 1471 | 1458 |
| 1472 if (_externalOrNative(node)) return null; | 1459 if (_externalOrNative(node)) return null; |
| 1473 | 1460 |
| 1474 if (node.isGetter || node.isSetter) { | 1461 if (node.isGetter || node.isSetter) { |
| 1475 // Add these later so we can use getter/setter syntax. | 1462 // Add these later so we can use getter/setter syntax. |
| 1476 _properties.add(node); | 1463 _properties.add(node); |
| 1477 return null; | 1464 return null; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1490 } | 1477 } |
| 1491 | 1478 |
| 1492 var id = new JS.Identifier(name); | 1479 var id = new JS.Identifier(name); |
| 1493 body.add(annotate(new JS.FunctionDeclaration(id, fn), node, node.element)); | 1480 body.add(annotate(new JS.FunctionDeclaration(id, fn), node, node.element)); |
| 1494 if (!_isDartRuntime) { | 1481 if (!_isDartRuntime) { |
| 1495 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true) | 1482 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true) |
| 1496 .toStatement()); | 1483 .toStatement()); |
| 1497 } | 1484 } |
| 1498 | 1485 |
| 1499 if (isPublic(name)) { | 1486 if (isPublic(name)) { |
| 1500 _addExport(name, _getJSExportName(node.element) ?? name); | 1487 _addExport(name, getJSExportName(node.element, types) ?? name); |
| 1501 } | 1488 } |
| 1502 return _statement(body); | 1489 return _statement(body); |
| 1503 } | 1490 } |
| 1504 | 1491 |
| 1505 bool _isInlineJSFunction(FunctionExpression functionExpression) { | 1492 bool _isInlineJSFunction(FunctionExpression functionExpression) { |
| 1506 var body = functionExpression.body; | 1493 var body = functionExpression.body; |
| 1507 if (body is ExpressionFunctionBody) { | 1494 if (body is ExpressionFunctionBody) { |
| 1508 return _isJSInvocation(body.expression); | 1495 return _isJSInvocation(body.expression); |
| 1509 } else if (body is BlockFunctionBody) { | 1496 } else if (body is BlockFunctionBody) { |
| 1510 if (body.block.statements.length == 1) { | 1497 if (body.block.statements.length == 1) { |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1955 if (jsArgs != null) { | 1942 if (jsArgs != null) { |
| 1956 var genericName = _emitTopLevelName(element, suffix: '\$'); | 1943 var genericName = _emitTopLevelName(element, suffix: '\$'); |
| 1957 return js.call('#(#)', [genericName, jsArgs]); | 1944 return js.call('#(#)', [genericName, jsArgs]); |
| 1958 } | 1945 } |
| 1959 } | 1946 } |
| 1960 | 1947 |
| 1961 return _emitTopLevelName(element); | 1948 return _emitTopLevelName(element); |
| 1962 } | 1949 } |
| 1963 | 1950 |
| 1964 JS.Expression _emitTopLevelName(Element e, {String suffix: ''}) { | 1951 JS.Expression _emitTopLevelName(Element e, {String suffix: ''}) { |
| 1965 var libName = _libraryName(e.library); | 1952 var libName = emitLibraryName(e.library); |
| 1966 | 1953 |
| 1967 // Always qualify: | 1954 // Always qualify: |
| 1968 // * mutable top-level fields | 1955 // * mutable top-level fields |
| 1969 // * elements from other libraries | 1956 // * elements from other libraries |
| 1970 bool mutableTopLevel = e is TopLevelVariableElement && | 1957 bool mutableTopLevel = e is TopLevelVariableElement && |
| 1971 !e.isConst && | 1958 !e.isConst && |
| 1972 !_isFinalJSDecl(e.computeNode()); | 1959 !_isFinalJSDecl(e.computeNode()); |
| 1973 bool fromAnotherLibrary = e.library != currentLibrary; | 1960 bool fromAnotherLibrary = e.library != currentLibrary; |
| 1974 var nameExpr; | 1961 var nameExpr; |
| 1975 if (fromAnotherLibrary) { | 1962 if (fromAnotherLibrary) { |
| 1976 nameExpr = _propertyName((_getJSExportName(e) ?? e.name) + suffix); | 1963 nameExpr = _propertyName((getJSExportName(e, types) ?? e.name) + suffix); |
| 1977 } else { | 1964 } else { |
| 1978 nameExpr = _propertyName(e.name + suffix); | 1965 nameExpr = _propertyName(e.name + suffix); |
| 1979 } | 1966 } |
| 1980 if (mutableTopLevel || fromAnotherLibrary) { | 1967 if (mutableTopLevel || fromAnotherLibrary) { |
| 1981 return new JS.PropertyAccess(libName, nameExpr); | 1968 return new JS.PropertyAccess(libName, nameExpr); |
| 1982 } | 1969 } |
| 1983 | 1970 |
| 1984 var id = new JS.MaybeQualifiedId(libName, nameExpr); | 1971 var id = new JS.MaybeQualifiedId(libName, nameExpr); |
| 1985 _qualifiedIds.add(new Tuple2(e, id)); | 1972 _qualifiedIds.add(new Tuple2(e, id)); |
| 1986 return id; | 1973 return id; |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2274 } else { | 2261 } else { |
| 2275 var jsParam = _visit(param); | 2262 var jsParam = _visit(param); |
| 2276 result.add(param is DefaultFormalParameter && destructure | 2263 result.add(param is DefaultFormalParameter && destructure |
| 2277 ? new JS.DestructuredVariable( | 2264 ? new JS.DestructuredVariable( |
| 2278 name: jsParam, defaultValue: _defaultParamValue(param)) | 2265 name: jsParam, defaultValue: _defaultParamValue(param)) |
| 2279 : jsParam); | 2266 : jsParam); |
| 2280 } | 2267 } |
| 2281 } | 2268 } |
| 2282 | 2269 |
| 2283 if (needsOpts) { | 2270 if (needsOpts) { |
| 2284 result.add(_namedArgTemp); | 2271 result.add(namedArgumentTemp); |
| 2285 } else if (namedVars.isNotEmpty) { | 2272 } else if (namedVars.isNotEmpty) { |
| 2286 // Note: `var {valueOf} = {}` extracts `Object.prototype.valueOf`, so | 2273 // Note: `var {valueOf} = {}` extracts `Object.prototype.valueOf`, so |
| 2287 // in case there are conflicting names we create an object without | 2274 // in case there are conflicting names we create an object without |
| 2288 // any prototype. | 2275 // any prototype. |
| 2289 var defaultOpts = hasNamedArgsConflictingWithObjectProperties | 2276 var defaultOpts = hasNamedArgsConflictingWithObjectProperties |
| 2290 ? js.call('Object.create(null)') | 2277 ? js.call('Object.create(null)') |
| 2291 : js.call('{}'); | 2278 : js.call('{}'); |
| 2292 result.add(new JS.DestructuredVariable( | 2279 result.add(new JS.DestructuredVariable( |
| 2293 structure: new JS.ObjectBindingPattern(namedVars), | 2280 structure: new JS.ObjectBindingPattern(namedVars), |
| 2294 type: emitNamedParamsArgType(node.parameterElements), | 2281 type: emitNamedParamsArgType(node.parameterElements), |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2497 } | 2484 } |
| 2498 | 2485 |
| 2499 // Treat `final x = JS('', '...')` as a const (non-lazy) to help compile | 2486 // Treat `final x = JS('', '...')` as a const (non-lazy) to help compile |
| 2500 // runtime helpers. | 2487 // runtime helpers. |
| 2501 var isJSTopLevel = field.isFinal && _isFinalJSDecl(field); | 2488 var isJSTopLevel = field.isFinal && _isFinalJSDecl(field); |
| 2502 if (isJSTopLevel) eagerInit = true; | 2489 if (isJSTopLevel) eagerInit = true; |
| 2503 | 2490 |
| 2504 var fieldName = field.name.name; | 2491 var fieldName = field.name.name; |
| 2505 var exportName = fieldName; | 2492 var exportName = fieldName; |
| 2506 if (element is TopLevelVariableElement) { | 2493 if (element is TopLevelVariableElement) { |
| 2507 exportName = _getJSExportName(element) ?? fieldName; | 2494 exportName = getJSExportName(element, types) ?? fieldName; |
| 2508 } | 2495 } |
| 2509 if ((field.isConst && eagerInit && element is TopLevelVariableElement) || | 2496 if ((field.isConst && eagerInit && element is TopLevelVariableElement) || |
| 2510 isJSTopLevel) { | 2497 isJSTopLevel) { |
| 2511 // constant fields don't change, so we can generate them as `let` | 2498 // constant fields don't change, so we can generate them as `let` |
| 2512 // but add them to the module's exports. However, make sure we generate | 2499 // but add them to the module's exports. However, make sure we generate |
| 2513 // anything they depend on first. | 2500 // anything they depend on first. |
| 2514 | 2501 |
| 2515 if (isPublic(fieldName)) _addExport(fieldName, exportName); | 2502 if (isPublic(fieldName)) _addExport(fieldName, exportName); |
| 2516 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let'; | 2503 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let'; |
| 2517 if (isJSTopLevel && jsInit is JS.ClassExpression) { | 2504 if (isJSTopLevel && jsInit is JS.ClassExpression) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2568 isSetter: true), | 2555 isSetter: true), |
| 2569 node, | 2556 node, |
| 2570 _findAccessor(element, getter: false))); | 2557 _findAccessor(element, getter: false))); |
| 2571 } | 2558 } |
| 2572 } | 2559 } |
| 2573 | 2560 |
| 2574 JS.Expression objExpr; | 2561 JS.Expression objExpr; |
| 2575 if (target is ClassElement) { | 2562 if (target is ClassElement) { |
| 2576 objExpr = new JS.Identifier(target.type.name); | 2563 objExpr = new JS.Identifier(target.type.name); |
| 2577 } else { | 2564 } else { |
| 2578 objExpr = _libraryName(target); | 2565 objExpr = emitLibraryName(target); |
| 2579 } | 2566 } |
| 2580 | 2567 |
| 2581 return js | 2568 return js |
| 2582 .statement('dart.defineLazyProperties(#, { # });', [objExpr, methods]); | 2569 .statement('dart.defineLazyProperties(#, { # });', [objExpr, methods]); |
| 2583 } | 2570 } |
| 2584 | 2571 |
| 2585 PropertyAccessorElement _findAccessor(VariableElement element, | 2572 PropertyAccessorElement _findAccessor(VariableElement element, |
| 2586 {bool getter}) { | 2573 {bool getter}) { |
| 2587 var parent = element.enclosingElement; | 2574 var parent = element.enclosingElement; |
| 2588 if (parent is ClassElement) { | 2575 if (parent is ClassElement) { |
| (...skipping 930 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3519 | 3506 |
| 3520 _visit(AstNode node) { | 3507 _visit(AstNode node) { |
| 3521 if (node == null) return null; | 3508 if (node == null) return null; |
| 3522 var result = node.accept(this); | 3509 var result = node.accept(this); |
| 3523 if (result is JS.Node) result = annotate(result, node); | 3510 if (result is JS.Node) result = annotate(result, node); |
| 3524 return result; | 3511 return result; |
| 3525 } | 3512 } |
| 3526 | 3513 |
| 3527 // TODO(jmesserly): this will need to be a generic method, if we ever want to | 3514 // TODO(jmesserly): this will need to be a generic method, if we ever want to |
| 3528 // self-host strong mode. | 3515 // self-host strong mode. |
| 3529 List /*<T>*/ _visitList /*<T>*/ (Iterable<AstNode> nodes) { | 3516 List/*<T>*/ _visitList/*<T>*/(Iterable<AstNode> nodes) { |
| 3530 if (nodes == null) return null; | 3517 if (nodes == null) return null; |
| 3531 var result = /*<T>*/ []; | 3518 var result = /*<T>*/ []; |
| 3532 for (var node in nodes) result.add(_visit(node)); | 3519 for (var node in nodes) result.add(_visit(node)); |
| 3533 return result; | 3520 return result; |
| 3534 } | 3521 } |
| 3535 | 3522 |
| 3536 /// Visits a list of expressions, creating a comma expression if needed in JS. | 3523 /// Visits a list of expressions, creating a comma expression if needed in JS. |
| 3537 JS.Expression _visitListToBinary(List<Expression> nodes, String operator) { | 3524 JS.Expression _visitListToBinary(List<Expression> nodes, String operator) { |
| 3538 if (nodes == null || nodes.isEmpty) return null; | 3525 if (nodes == null || nodes.isEmpty) return null; |
| 3539 return new JS.Expression.binary( | 3526 return new JS.Expression.binary( |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3647 | 3634 |
| 3648 bool _externalOrNative(node) => | 3635 bool _externalOrNative(node) => |
| 3649 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; | 3636 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; |
| 3650 | 3637 |
| 3651 FunctionBody _functionBody(node) => | 3638 FunctionBody _functionBody(node) => |
| 3652 node is FunctionDeclaration ? node.functionExpression.body : node.body; | 3639 node is FunctionDeclaration ? node.functionExpression.body : node.body; |
| 3653 | 3640 |
| 3654 /// Choose a canonical name from the library element. | 3641 /// Choose a canonical name from the library element. |
| 3655 /// This never uses the library's name (the identifier in the `library` | 3642 /// This never uses the library's name (the identifier in the `library` |
| 3656 /// declaration) as it doesn't have any meaningful rules enforced. | 3643 /// declaration) as it doesn't have any meaningful rules enforced. |
| 3657 JS.Identifier _libraryName(LibraryElement library) { | 3644 JS.Identifier emitLibraryName(LibraryElement library) { |
| 3658 if (library == currentLibrary) return _exportsVar; | 3645 if (library == currentLibrary) return _exportsVar; |
| 3659 if (library.name == 'dart._runtime') return _runtimeLibVar; | 3646 if (library.name == 'dart._runtime') return _runtimeLibVar; |
| 3660 return _imports.putIfAbsent( | 3647 return _imports.putIfAbsent( |
| 3661 library, () => new JS.TemporaryId(jsLibraryName(library))); | 3648 library, () => new JS.TemporaryId(jsLibraryName(library))); |
| 3662 } | 3649 } |
| 3663 | 3650 |
| 3664 DartType getStaticType(Expression e) => | 3651 DartType getStaticType(Expression e) => |
| 3665 e.staticType ?? DynamicTypeImpl.instance; | 3652 e.staticType ?? DynamicTypeImpl.instance; |
| 3666 | 3653 |
| 3667 JS.Node annotate(JS.Node node, AstNode original, [Element element]) { | 3654 JS.Node annotate(JS.Node node, AstNode original, [Element element]) { |
| 3668 if (options.closure && element != null) { | 3655 if (options.closure && element != null) { |
| 3669 node = node.withClosureAnnotation( | 3656 node = node.withClosureAnnotation(closureAnnotationFor( |
| 3670 closureAnnotationFor(node, original, element, _namedArgTemp.name)); | 3657 node, original, element, namedArgumentTemp.name)); |
| 3671 } | 3658 } |
| 3672 return node..sourceInformation = original; | 3659 return node..sourceInformation = original; |
| 3673 } | 3660 } |
| 3674 | 3661 |
| 3675 /// Returns true if this is any kind of object represented by `Number` in JS. | 3662 /// Returns true if this is any kind of object represented by `Number` in JS. |
| 3676 /// | 3663 /// |
| 3677 /// In practice, this is 4 types: num, int, double, and JSNumber. | 3664 /// In practice, this is 4 types: num, int, double, and JSNumber. |
| 3678 /// | 3665 /// |
| 3679 /// JSNumber is the type that actually "implements" all numbers, hence it's | 3666 /// JSNumber is the type that actually "implements" all numbers, hence it's |
| 3680 /// a subtype of int and double (and num). It's in our "dart:_interceptors". | 3667 /// a subtype of int and double (and num). It's in our "dart:_interceptors". |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3836 | 3823 |
| 3837 /// A special kind of element created by the compiler, signifying a temporary | 3824 /// A special kind of element created by the compiler, signifying a temporary |
| 3838 /// variable. These objects use instance equality, and should be shared | 3825 /// variable. These objects use instance equality, and should be shared |
| 3839 /// everywhere in the tree where they are treated as the same variable. | 3826 /// everywhere in the tree where they are treated as the same variable. |
| 3840 class TemporaryVariableElement extends LocalVariableElementImpl { | 3827 class TemporaryVariableElement extends LocalVariableElementImpl { |
| 3841 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 3828 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
| 3842 | 3829 |
| 3843 int get hashCode => identityHashCode(this); | 3830 int get hashCode => identityHashCode(this); |
| 3844 bool operator ==(Object other) => identical(this, other); | 3831 bool operator ==(Object other) => identical(this, other); |
| 3845 } | 3832 } |
| OLD | NEW |