| 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; | 5 library js_codegen; |
| 6 | 6 |
| 7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; | 7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; |
| 8 | 8 |
| 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
| 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; | 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 459 // want to support construction of instances with generic types other | 459 // want to support construction of instances with generic types other |
| 460 // than dynamic. See issue #154 for Array and List<E> related bug. | 460 // than dynamic. See issue #154 for Array and List<E> related bug. |
| 461 var copyMembers = js.statement( | 461 var copyMembers = js.statement( |
| 462 'dart.registerExtension(dart.global.#, #);', | 462 'dart.registerExtension(dart.global.#, #);', |
| 463 [_propertyName(jsPeerName), classElem.name]); | 463 [_propertyName(jsPeerName), classElem.name]); |
| 464 return _statement([result, copyMembers]); | 464 return _statement([result, copyMembers]); |
| 465 } | 465 } |
| 466 return result; | 466 return result; |
| 467 } | 467 } |
| 468 | 468 |
| 469 Iterable<JS.Identifier> _emitTypeParams(TypeParameterizedElement e) sync* { | 469 Iterable<JS.TypeParameter> _emitTypeParams(TypeParameterizedElement e) sync* { |
| 470 if (!options.closure) return; | 470 if (!options.closure) return; |
| 471 for (var typeParam in e.typeParameters) { | 471 for (var typeParam in e.typeParameters) { |
| 472 yield new JS.Identifier(typeParam.name); | 472 yield new JS.TypeParameter( |
| 473 new JS.Identifier(typeParam.name), |
| 474 bound: emitTypeRef(typeParam.bound)); |
| 473 } | 475 } |
| 474 } | 476 } |
| 475 | 477 |
| 476 /// Emit field declarations for TypeScript & Closure's ES6_TYPED | 478 /// Emit field declarations for TypeScript & Closure's ES6_TYPED |
| 477 /// (e.g. `class Foo { i: string; }`) | 479 /// (e.g. `class Foo { i: string; }`) |
| 478 Iterable<JS.VariableDeclarationList> _emitFieldDeclarations( | 480 Iterable<JS.VariableDeclarationList> _emitFieldDeclarations( |
| 479 ClassElement classElem, | 481 ClassElement classElem, |
| 480 List<FieldDeclaration> fields, | 482 List<FieldDeclaration> fields, |
| 481 List<FieldDeclaration> staticFields) sync* { | 483 List<FieldDeclaration> staticFields) sync* { |
| 482 if (!options.closure) return; | 484 if (!options.closure) return; |
| 483 | 485 |
| 484 makeInitialization(VariableDeclaration decl) => | 486 makeInitialization(VariableDeclaration decl) => |
| 485 new JS.VariableInitialization( | 487 new JS.VariableInitialization( |
| 486 new JS.Identifier( | 488 // TODO(ochafik): use a refactored _emitMemberName instead. |
| 487 // TODO(ochafik): use a refactored _emitMemberName instead. | 489 new JS.Identifier(decl.name.name), |
| 488 decl.name.name, | 490 null, |
| 489 type: emitTypeRef(decl.element.type)), | 491 type: emitTypeRef(decl.element.type)); |
| 490 null); | |
| 491 | 492 |
| 492 for (var field in fields) { | 493 for (var field in fields) { |
| 493 yield new JS.VariableDeclarationList( | 494 yield new JS.VariableDeclarationList( |
| 494 null, field.fields.variables.map(makeInitialization).toList()); | 495 null, field.fields.variables.map(makeInitialization).toList()); |
| 495 } | 496 } |
| 496 for (var field in staticFields) { | 497 for (var field in staticFields) { |
| 497 yield new JS.VariableDeclarationList( | 498 yield new JS.VariableDeclarationList( |
| 498 'static', field.fields.variables.map(makeInitialization).toList()); | 499 'static', field.fields.variables.map(makeInitialization).toList()); |
| 499 } | 500 } |
| 500 } | 501 } |
| (...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1204 fields[element as FieldElement] = _visitInitializer(fieldNode); | 1205 fields[element as FieldElement] = _visitInitializer(fieldNode); |
| 1205 } | 1206 } |
| 1206 } | 1207 } |
| 1207 } | 1208 } |
| 1208 | 1209 |
| 1209 // Initialize fields from `this.fieldName` parameters. | 1210 // Initialize fields from `this.fieldName` parameters. |
| 1210 if (ctor != null) { | 1211 if (ctor != null) { |
| 1211 for (var p in ctor.parameters.parameters) { | 1212 for (var p in ctor.parameters.parameters) { |
| 1212 var element = p.element; | 1213 var element = p.element; |
| 1213 if (element is FieldFormalParameterElement) { | 1214 if (element is FieldFormalParameterElement) { |
| 1214 fields[element.field] = _emitFormalParameter(p, allowType: false); | 1215 fields[element.field] = _visit(p.identifier); |
| 1215 } | 1216 } |
| 1216 } | 1217 } |
| 1217 | 1218 |
| 1218 // Run constructor field initializers such as `: foo = bar.baz` | 1219 // Run constructor field initializers such as `: foo = bar.baz` |
| 1219 for (var init in ctor.initializers) { | 1220 for (var init in ctor.initializers) { |
| 1220 if (init is ConstructorFieldInitializer) { | 1221 if (init is ConstructorFieldInitializer) { |
| 1221 fields[init.fieldName.staticElement as FieldElement] = | 1222 fields[init.fieldName.staticElement as FieldElement] = |
| 1222 _visit(init.expression); | 1223 _visit(init.expression); |
| 1223 } | 1224 } |
| 1224 } | 1225 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1262 JS.Statement _emitArgumentInitializers(node, {bool constructor: false}) { | 1263 JS.Statement _emitArgumentInitializers(node, {bool constructor: false}) { |
| 1263 // Constructor argument initializers are emitted earlier in the code, rather | 1264 // Constructor argument initializers are emitted earlier in the code, rather |
| 1264 // than always when we visit the function body, so we control it explicitly. | 1265 // than always when we visit the function body, so we control it explicitly. |
| 1265 if (node is ConstructorDeclaration != constructor) return null; | 1266 if (node is ConstructorDeclaration != constructor) return null; |
| 1266 | 1267 |
| 1267 var parameters = _parametersOf(node); | 1268 var parameters = _parametersOf(node); |
| 1268 if (parameters == null) return null; | 1269 if (parameters == null) return null; |
| 1269 | 1270 |
| 1270 var body = <JS.Statement>[]; | 1271 var body = <JS.Statement>[]; |
| 1271 for (var param in parameters.parameters) { | 1272 for (var param in parameters.parameters) { |
| 1272 var jsParam = _emitSimpleIdentifier(param.identifier, allowType: false); | 1273 var jsParam = _visit(param.identifier); |
| 1273 | 1274 |
| 1274 if (param.kind == ParameterKind.NAMED) { | 1275 if (param.kind == ParameterKind.NAMED) { |
| 1275 if (!options.destructureNamedParams) { | 1276 if (!options.destructureNamedParams) { |
| 1276 // Parameters will be passed using their real names, not the (possibly | 1277 // Parameters will be passed using their real names, not the (possibly |
| 1277 // renamed) local variable. | 1278 // renamed) local variable. |
| 1278 var paramName = js.string(param.identifier.name, "'"); | 1279 var paramName = js.string(param.identifier.name, "'"); |
| 1279 | 1280 |
| 1280 // TODO(ochafik): Fix `'prop' in obj` to please Closure's renaming. | 1281 // TODO(ochafik): Fix `'prop' in obj` to please Closure's renaming. |
| 1281 body.add(js.statement('let # = # && # in # ? #.# : #;', [ | 1282 body.add(js.statement('let # = # && # in # ? #.# : #;', [ |
| 1282 jsParam, | 1283 jsParam, |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1329 if (params == null) params = <JS.Parameter>[]; | 1330 if (params == null) params = <JS.Parameter>[]; |
| 1330 | 1331 |
| 1331 var typeParams = _emitTypeParams(node.element).toList(); | 1332 var typeParams = _emitTypeParams(node.element).toList(); |
| 1332 var returnType = emitTypeRef(node.element.returnType); | 1333 var returnType = emitTypeRef(node.element.returnType); |
| 1333 JS.Fun fn = _emitFunctionBody(params, node.body, typeParams, returnType); | 1334 JS.Fun fn = _emitFunctionBody(params, node.body, typeParams, returnType); |
| 1334 if (node.operatorKeyword != null && | 1335 if (node.operatorKeyword != null && |
| 1335 node.name.name == '[]=' && | 1336 node.name.name == '[]=' && |
| 1336 params.isNotEmpty) { | 1337 params.isNotEmpty) { |
| 1337 // []= methods need to return the value. We could also address this at | 1338 // []= methods need to return the value. We could also address this at |
| 1338 // call sites, but it's cleaner to instead transform the operator method. | 1339 // call sites, but it's cleaner to instead transform the operator method. |
| 1339 var returnValue = new JS.Return(params.last); | 1340 // TODO(ochafik): How do we ensure this is an expression and not a destruc
ting pattern? |
| 1341 var returnValue = new JS.Return(params.last.binding as JS.Expression); |
| 1340 var body = fn.body; | 1342 var body = fn.body; |
| 1341 if (JS.Return.foundIn(fn)) { | 1343 if (JS.Return.foundIn(fn)) { |
| 1342 // If a return is inside body, transform `(params) { body }` to | 1344 // If a return is inside body, transform `(params) { body }` to |
| 1343 // `(params) { (() => { body })(); return value; }`. | 1345 // `(params) { (() => { body })(); return value; }`. |
| 1344 // TODO(jmesserly): we could instead generate the return differently, | 1346 // TODO(jmesserly): we could instead generate the return differently, |
| 1345 // and avoid the immediately invoked function. | 1347 // and avoid the immediately invoked function. |
| 1346 body = new JS.Call(new JS.ArrowFun([], fn.body), []).toStatement(); | 1348 body = new JS.Call(new JS.ArrowFun([], fn.body), []).toStatement(); |
| 1347 } | 1349 } |
| 1348 // Rewrite the function to include the return. | 1350 // Rewrite the function to include the return. |
| 1349 fn = new JS.Fun(fn.params, new JS.Block([body, returnValue]), | 1351 fn = new JS.Fun(fn.params, new JS.Block([body, returnValue]), |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1536 if (!inStmt) { | 1538 if (!inStmt) { |
| 1537 var type = getStaticType(node); | 1539 var type = getStaticType(node); |
| 1538 return _emitFunctionTagged(clos, type, | 1540 return _emitFunctionTagged(clos, type, |
| 1539 topLevel: _executesAtTopLevel(node)); | 1541 topLevel: _executesAtTopLevel(node)); |
| 1540 } | 1542 } |
| 1541 return clos; | 1543 return clos; |
| 1542 } | 1544 } |
| 1543 } | 1545 } |
| 1544 | 1546 |
| 1545 JS.Fun _emitFunctionBody(List<JS.Parameter> params, FunctionBody body, | 1547 JS.Fun _emitFunctionBody(List<JS.Parameter> params, FunctionBody body, |
| 1546 List<JS.Identifier> typeParams, JS.TypeRef returnType) { | 1548 List<JS.TypeParameter> typeParams, JS.TypeRef returnType) { |
| 1547 // sync*, async, async* | 1549 // sync*, async, async* |
| 1548 if (body.isAsynchronous || body.isGenerator) { | 1550 if (body.isAsynchronous || body.isGenerator) { |
| 1549 return new JS.Fun( | 1551 return new JS.Fun( |
| 1550 params, | 1552 params, |
| 1551 js.statement('{ return #; }', | 1553 js.statement('{ return #; }', |
| 1552 [_emitGeneratorFunctionBody(params, body, returnType)]), | 1554 [_emitGeneratorFunctionBody(params, body, returnType)]), |
| 1553 returnType: returnType); | 1555 returnType: returnType); |
| 1554 } | 1556 } |
| 1555 // normal function (sync) | 1557 // normal function (sync) |
| 1556 return new JS.Fun(params, _visit(body), | 1558 return new JS.Fun(params, _visit(body), |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1634 declareFn = new JS.FunctionDeclaration(name, fn); | 1636 declareFn = new JS.FunctionDeclaration(name, fn); |
| 1635 } | 1637 } |
| 1636 declareFn = annotate(declareFn, node, node.functionDeclaration.element); | 1638 declareFn = annotate(declareFn, node, node.functionDeclaration.element); |
| 1637 | 1639 |
| 1638 return new JS.Block([ | 1640 return new JS.Block([ |
| 1639 declareFn, | 1641 declareFn, |
| 1640 _emitFunctionTagged(name, func.element.type).toStatement() | 1642 _emitFunctionTagged(name, func.element.type).toStatement() |
| 1641 ]); | 1643 ]); |
| 1642 } | 1644 } |
| 1643 | 1645 |
| 1644 @override | |
| 1645 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) => | |
| 1646 _emitSimpleIdentifier(node); | |
| 1647 | |
| 1648 /// Writes a simple identifier. This can handle implicit `this` as well as | 1646 /// Writes a simple identifier. This can handle implicit `this` as well as |
| 1649 /// going through the qualified library name if necessary. | 1647 /// going through the qualified library name if necessary. |
| 1650 JS.Expression _emitSimpleIdentifier(SimpleIdentifier node, | 1648 @override |
| 1651 {bool allowType: false}) { | 1649 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { |
| 1652 var accessor = node.staticElement; | 1650 var accessor = node.staticElement; |
| 1653 if (accessor == null) { | 1651 if (accessor == null) { |
| 1654 return js.commentExpression( | 1652 return js.commentExpression( |
| 1655 'Unimplemented unknown name', new JS.Identifier(node.name)); | 1653 'Unimplemented unknown name', new JS.Identifier(node.name)); |
| 1656 } | 1654 } |
| 1657 | 1655 |
| 1658 // Get the original declaring element. If we had a property accessor, this | 1656 // Get the original declaring element. If we had a property accessor, this |
| 1659 // indirects back to a (possibly synthetic) field. | 1657 // indirects back to a (possibly synthetic) field. |
| 1660 var element = accessor; | 1658 var element = accessor; |
| 1661 if (accessor is PropertyAccessorElement) element = accessor.variable; | 1659 if (accessor is PropertyAccessorElement) element = accessor.variable; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1710 } | 1708 } |
| 1711 | 1709 |
| 1712 if (element is TemporaryVariableElement) { | 1710 if (element is TemporaryVariableElement) { |
| 1713 if (name[0] == '#') { | 1711 if (name[0] == '#') { |
| 1714 return new JS.InterpolatedExpression(name.substring(1)); | 1712 return new JS.InterpolatedExpression(name.substring(1)); |
| 1715 } else { | 1713 } else { |
| 1716 return _getTemp(element, name); | 1714 return _getTemp(element, name); |
| 1717 } | 1715 } |
| 1718 } | 1716 } |
| 1719 | 1717 |
| 1720 return annotate( | 1718 return annotate(new JS.Identifier(name), node); |
| 1721 new JS.Identifier(name, | |
| 1722 type: allowType ? emitTypeRef(node.bestType) : null), | |
| 1723 node); | |
| 1724 } | 1719 } |
| 1725 | 1720 |
| 1726 JS.TemporaryId _getTemp(Element key, String name) => | 1721 JS.TemporaryId _getTemp(Element key, String name) => |
| 1727 _temps.putIfAbsent(key, () => new JS.TemporaryId(name)); | 1722 _temps.putIfAbsent(key, () => new JS.TemporaryId(name)); |
| 1728 | 1723 |
| 1729 List<Annotation> _parameterMetadata(FormalParameter p) => | 1724 List<Annotation> _parameterMetadata(FormalParameter p) => |
| 1730 (p is NormalFormalParameter) | 1725 (p is NormalFormalParameter) |
| 1731 ? p.metadata | 1726 ? p.metadata |
| 1732 : (p as DefaultFormalParameter).parameter.metadata; | 1727 : (p as DefaultFormalParameter).parameter.metadata; |
| 1733 | 1728 |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2088 code = '#(#)'; | 2083 code = '#(#)'; |
| 2089 } | 2084 } |
| 2090 return js.call(code, [_visit(node.function), _visit(node.argumentList)]); | 2085 return js.call(code, [_visit(node.function), _visit(node.argumentList)]); |
| 2091 } | 2086 } |
| 2092 | 2087 |
| 2093 @override | 2088 @override |
| 2094 List<JS.Expression> visitArgumentList(ArgumentList node) { | 2089 List<JS.Expression> visitArgumentList(ArgumentList node) { |
| 2095 var args = <JS.Expression>[]; | 2090 var args = <JS.Expression>[]; |
| 2096 var named = <JS.Property>[]; | 2091 var named = <JS.Property>[]; |
| 2097 for (var arg in node.arguments) { | 2092 for (var arg in node.arguments) { |
| 2093 var jsArg = _visit(arg); |
| 2098 if (arg is NamedExpression) { | 2094 if (arg is NamedExpression) { |
| 2099 named.add(_visit(arg)); | 2095 named.add(jsArg); |
| 2100 } else if (arg is MethodInvocation && isJsSpreadInvocation(arg)) { | 2096 } else if (arg is MethodInvocation && isJsSpreadInvocation(arg)) { |
| 2101 args.add( | 2097 args.add(new JS.Spread(jsArg)); |
| 2102 new JS.RestParameter(_visit(arg.argumentList.arguments.single))); | |
| 2103 } else { | 2098 } else { |
| 2104 args.add(_visit(arg)); | 2099 args.add(jsArg); |
| 2105 } | 2100 } |
| 2106 } | 2101 } |
| 2107 if (named.isNotEmpty) { | 2102 if (named.isNotEmpty) { |
| 2108 args.add(new JS.ObjectInitializer(named)); | 2103 args.add(new JS.ObjectInitializer(named)); |
| 2109 } | 2104 } |
| 2110 return args; | 2105 return args; |
| 2111 } | 2106 } |
| 2112 | 2107 |
| 2113 @override | 2108 @override |
| 2114 JS.Property visitNamedExpression(NamedExpression node) { | 2109 JS.Property visitNamedExpression(NamedExpression node) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2149 name = _visit(param.identifier); | 2144 name = _visit(param.identifier); |
| 2150 } | 2145 } |
| 2151 namedVars.add(new JS.DestructuredVariable( | 2146 namedVars.add(new JS.DestructuredVariable( |
| 2152 name: name, | 2147 name: name, |
| 2153 structure: structure, | 2148 structure: structure, |
| 2154 defaultValue: _defaultParamValue(param))); | 2149 defaultValue: _defaultParamValue(param))); |
| 2155 } else { | 2150 } else { |
| 2156 needsOpts = true; | 2151 needsOpts = true; |
| 2157 } | 2152 } |
| 2158 } else { | 2153 } else { |
| 2159 var jsParam = _visit(param); | 2154 result.add(_visit(param)); |
| 2160 result.add( | |
| 2161 param is DefaultFormalParameter && options.destructureNamedParams | |
| 2162 ? new JS.DestructuredVariable( | |
| 2163 name: jsParam, defaultValue: _defaultParamValue(param)) | |
| 2164 : jsParam); | |
| 2165 } | 2155 } |
| 2166 } | 2156 } |
| 2167 | 2157 |
| 2168 if (needsOpts) { | 2158 if (needsOpts) { |
| 2169 result.add(_namedArgTemp); | 2159 result.add(new JS.Parameter(_namedArgTemp)); |
| 2170 } else if (namedVars.isNotEmpty) { | 2160 } else if (namedVars.isNotEmpty) { |
| 2171 // Note: `var {valueOf} = {}` extracts `Object.prototype.valueOf`, so | 2161 // Note: `var {valueOf} = {}` extracts `Object.prototype.valueOf`, so |
| 2172 // in case there are conflicting names we create an object without | 2162 // in case there are conflicting names we create an object without |
| 2173 // any prototype. | 2163 // any prototype. |
| 2174 var defaultOpts = hasNamedArgsConflictingWithObjectProperties | 2164 var defaultOpts = hasNamedArgsConflictingWithObjectProperties |
| 2175 ? js.call('Object.create(null)') | 2165 ? js.call('Object.create(null)') |
| 2176 : js.call('{}'); | 2166 : js.call('{}'); |
| 2177 result.add(new JS.DestructuredVariable( | 2167 result.add(new JS.Parameter( |
| 2178 structure: new JS.ObjectBindingPattern(namedVars), | 2168 new JS.ObjectBindingPattern(namedVars), |
| 2179 type: emitNamedParamsArgType(node.parameterElements), | 2169 type: emitNamedParamsArgType(node.parameterElements), |
| 2180 defaultValue: defaultOpts)); | 2170 defaultValue: defaultOpts)); |
| 2181 } | 2171 } |
| 2182 return result; | 2172 return result; |
| 2183 } | 2173 } |
| 2184 | 2174 |
| 2185 /// See ES6 spec (and `Object.getOwnPropertyNames(Object.prototype)`): | 2175 /// See ES6 spec (and `Object.getOwnPropertyNames(Object.prototype)`): |
| 2186 /// http://www.ecma-international.org/ecma-262/6.0/#sec-properties-of-the-obje
ct-prototype-object | 2176 /// http://www.ecma-international.org/ecma-262/6.0/#sec-properties-of-the-obje
ct-prototype-object |
| 2187 /// http://www.ecma-international.org/ecma-262/6.0/#sec-additional-properties-
of-the-object.prototype-object | 2177 /// http://www.ecma-international.org/ecma-262/6.0/#sec-additional-properties-
of-the-object.prototype-object |
| 2188 static final Set<String> _jsObjectProperties = new Set<String>() | 2178 static final Set<String> _jsObjectProperties = new Set<String>() |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2301 } | 2291 } |
| 2302 | 2292 |
| 2303 @override | 2293 @override |
| 2304 visitVariableDeclaration(VariableDeclaration node) { | 2294 visitVariableDeclaration(VariableDeclaration node) { |
| 2305 if (node.element is PropertyInducingElement) { | 2295 if (node.element is PropertyInducingElement) { |
| 2306 // Static and instance fields are handled elsewhere. | 2296 // Static and instance fields are handled elsewhere. |
| 2307 assert(node.element is TopLevelVariableElement); | 2297 assert(node.element is TopLevelVariableElement); |
| 2308 return _emitTopLevelField(node); | 2298 return _emitTopLevelField(node); |
| 2309 } | 2299 } |
| 2310 | 2300 |
| 2311 var name = | 2301 var name = new JS.Identifier(node.name.name); |
| 2312 new JS.Identifier(node.name.name, type: emitTypeRef(node.element.type)); | 2302 return new JS.VariableInitialization(name, _visitInitializer(node), |
| 2313 return new JS.VariableInitialization(name, _visitInitializer(node)); | 2303 type: emitTypeRef(node.element.type)); |
| 2314 } | 2304 } |
| 2315 | 2305 |
| 2316 bool _isFinalJSDecl(AstNode field) => | 2306 bool _isFinalJSDecl(AstNode field) => |
| 2317 field is VariableDeclaration && | 2307 field is VariableDeclaration && |
| 2318 field.isFinal && | 2308 field.isFinal && |
| 2319 _isJSInvocation(field.initializer); | 2309 _isJSInvocation(field.initializer); |
| 2320 | 2310 |
| 2321 /// Try to emit a constant static field. | 2311 /// Try to emit a constant static field. |
| 2322 /// | 2312 /// |
| 2323 /// If the field's initializer does not cause side effects, and if all of | 2313 /// If the field's initializer does not cause side effects, and if all of |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2396 // constant fields don't change, so we can generate them as `let` | 2386 // constant fields don't change, so we can generate them as `let` |
| 2397 // but add them to the module's exports. However, make sure we generate | 2387 // but add them to the module's exports. However, make sure we generate |
| 2398 // anything they depend on first. | 2388 // anything they depend on first. |
| 2399 | 2389 |
| 2400 if (isPublic(fieldName)) _addExport(fieldName, exportName); | 2390 if (isPublic(fieldName)) _addExport(fieldName, exportName); |
| 2401 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let'; | 2391 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let'; |
| 2402 return js.statement('#;', [ | 2392 return js.statement('#;', [ |
| 2403 annotate( | 2393 annotate( |
| 2404 new JS.VariableDeclarationList(declKeyword, [ | 2394 new JS.VariableDeclarationList(declKeyword, [ |
| 2405 new JS.VariableInitialization( | 2395 new JS.VariableInitialization( |
| 2406 new JS.Identifier(fieldName, | 2396 new JS.Identifier(fieldName), |
| 2407 type: emitTypeRef(field.element.type)), | 2397 jsInit, |
| 2408 jsInit) | 2398 type: emitTypeRef(field.element.type)) |
| 2409 ]), | 2399 ]), |
| 2410 field, | 2400 field, |
| 2411 field.element) | 2401 field.element) |
| 2412 ]); | 2402 ]); |
| 2413 } | 2403 } |
| 2414 | 2404 |
| 2415 if (eagerInit && !JS.invalidStaticFieldName(fieldName)) { | 2405 if (eagerInit && !JS.invalidStaticFieldName(fieldName)) { |
| 2416 return annotate(js.statement('# = #;', [_visit(field.name), jsInit]), | 2406 return annotate(js.statement('# = #;', [_visit(field.name), jsInit]), |
| 2417 field, field.element); | 2407 field, field.element); |
| 2418 } | 2408 } |
| (...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2830 _cascadeTarget = savedCascadeTemp; | 2820 _cascadeTarget = savedCascadeTemp; |
| 2831 return result; | 2821 return result; |
| 2832 } | 2822 } |
| 2833 | 2823 |
| 2834 @override | 2824 @override |
| 2835 visitParenthesizedExpression(ParenthesizedExpression node) => | 2825 visitParenthesizedExpression(ParenthesizedExpression node) => |
| 2836 // The printer handles precedence so we don't need to. | 2826 // The printer handles precedence so we don't need to. |
| 2837 _visit(node.expression); | 2827 _visit(node.expression); |
| 2838 | 2828 |
| 2839 @override | 2829 @override |
| 2840 visitFormalParameter(FormalParameter node) => _emitFormalParameter(node); | 2830 visitFormalParameter(FormalParameter node) { |
| 2841 | 2831 var defaultValue = |
| 2842 _emitFormalParameter(FormalParameter node, {bool allowType: true}) { | 2832 node is DefaultFormalParameter && options.destructureNamedParams |
| 2843 var id = _emitSimpleIdentifier(node.identifier, allowType: allowType); | 2833 ? _defaultParamValue(node) : null; |
| 2844 | 2834 return new JS.Parameter( |
| 2845 var isRestArg = findAnnotation(node.element, isJsRestAnnotation) != null; | 2835 _visit(node.identifier), |
| 2846 return isRestArg ? new JS.RestParameter(id) : id; | 2836 type: emitTypeRef(node.element.type), |
| 2837 defaultValue: defaultValue, |
| 2838 isRest: findAnnotation(node.element, isJsRestAnnotation) != null); |
| 2847 } | 2839 } |
| 2848 | 2840 |
| 2849 @override | 2841 @override |
| 2850 JS.This visitThisExpression(ThisExpression node) => new JS.This(); | 2842 JS.This visitThisExpression(ThisExpression node) => new JS.This(); |
| 2851 | 2843 |
| 2852 @override | 2844 @override |
| 2853 JS.Super visitSuperExpression(SuperExpression node) => new JS.Super(); | 2845 JS.Super visitSuperExpression(SuperExpression node) => new JS.Super(); |
| 2854 | 2846 |
| 2855 @override | 2847 @override |
| 2856 visitPrefixedIdentifier(PrefixedIdentifier node) { | 2848 visitPrefixedIdentifier(PrefixedIdentifier node) { |
| (...skipping 832 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3689 | 3681 |
| 3690 /// A special kind of element created by the compiler, signifying a temporary | 3682 /// A special kind of element created by the compiler, signifying a temporary |
| 3691 /// variable. These objects use instance equality, and should be shared | 3683 /// variable. These objects use instance equality, and should be shared |
| 3692 /// everywhere in the tree where they are treated as the same variable. | 3684 /// everywhere in the tree where they are treated as the same variable. |
| 3693 class TemporaryVariableElement extends LocalVariableElementImpl { | 3685 class TemporaryVariableElement extends LocalVariableElementImpl { |
| 3694 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 3686 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
| 3695 | 3687 |
| 3696 int get hashCode => identityHashCode(this); | 3688 int get hashCode => identityHashCode(this); |
| 3697 bool operator ==(Object other) => identical(this, other); | 3689 bool operator ==(Object other) => identical(this, other); |
| 3698 } | 3690 } |
| OLD | NEW |