Chromium Code Reviews| 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 651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 662 for (var m in node.members) { | 662 for (var m in node.members) { |
| 663 if (m is ConstructorDeclaration) { | 663 if (m is ConstructorDeclaration) { |
| 664 jsMethods.add(_emitConstructor(m, type, fields, isObject)); | 664 jsMethods.add(_emitConstructor(m, type, fields, isObject)); |
| 665 } else if (m is MethodDeclaration) { | 665 } else if (m is MethodDeclaration) { |
| 666 jsMethods.add(_emitMethodDeclaration(type, m)); | 666 jsMethods.add(_emitMethodDeclaration(type, m)); |
| 667 | 667 |
| 668 if (!hasJsPeer && m.isGetter && m.name.name == 'iterator') { | 668 if (!hasJsPeer && m.isGetter && m.name.name == 'iterator') { |
| 669 hasIterator = true; | 669 hasIterator = true; |
| 670 jsMethods.add(_emitIterable(type)); | 670 jsMethods.add(_emitIterable(type)); |
| 671 } | 671 } |
| 672 } else if (m is FieldDeclaration) { | |
| 673 // TODO(vsm): Refactor common logic out. | |
|
Jennifer Messerly
2016/02/16 17:46:38
yeah if this was in a method like _emitRenamedNati
vsm
2016/02/18 01:13:09
Refactored and added a TODO to look into metaprogr
| |
| 674 if (!m.isStatic && _extensionTypes.contains(element)) { | |
| 675 for (var decl in m.fields.variables) { | |
| 676 FieldElement field = decl.element; | |
|
Jacob
2016/02/16 17:47:35
nit: change these to variables to var?
vsm
2016/02/18 01:13:09
Done.
| |
| 677 String name = decl.name.name; | |
| 678 var annotation = findAnnotation(field, isJsName); | |
| 679 if (annotation != null) { | |
| 680 name = getConstantField(annotation, 'name', types.stringType) | |
| 681 ?.toStringValue(); | |
| 682 } | |
| 683 // Generate getter | |
| 684 var fn = new JS.Fun([], js.statement('{ return this.#; }', [name])); | |
| 685 var method = new JS.Method(_elementMemberName(field.getter), fn, | |
| 686 isGetter: true); | |
| 687 jsMethods.add(method); | |
| 688 | |
| 689 // Generate setter | |
| 690 if (!decl.isFinal) { | |
| 691 var value = new JS.TemporaryId('value'); | |
| 692 fn = new JS.Fun( | |
| 693 [value], js.statement('{ this.# = #; }', [name, value])); | |
| 694 method = new JS.Method(_elementMemberName(field.setter), fn, | |
| 695 isSetter: true); | |
| 696 jsMethods.add(method); | |
| 697 } | |
| 698 } | |
| 699 } | |
| 672 } | 700 } |
| 673 } | 701 } |
| 674 | 702 |
| 675 // If the type doesn't have an `iterator`, but claims to implement Iterable, | 703 // If the type doesn't have an `iterator`, but claims to implement Iterable, |
| 676 // we inject the adaptor method here, as it's less code size to put the | 704 // we inject the adaptor method here, as it's less code size to put the |
| 677 // helper on a parent class. This pattern is common in the core libraries | 705 // helper on a parent class. This pattern is common in the core libraries |
| 678 // (e.g. IterableMixin<E> and IterableBase<E>). | 706 // (e.g. IterableMixin<E> and IterableBase<E>). |
| 679 // | 707 // |
| 680 // (We could do this same optimization for any interface with an `iterator` | 708 // (We could do this same optimization for any interface with an `iterator` |
| 681 // method, but that's more expensive to check for, so it doesn't seem worth | 709 // method, but that's more expensive to check for, so it doesn't seem worth |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 762 var name = classElem.name; | 790 var name = classElem.name; |
| 763 var body = <JS.Statement>[]; | 791 var body = <JS.Statement>[]; |
| 764 | 792 |
| 765 if (_extensionTypes.contains(classElem)) { | 793 if (_extensionTypes.contains(classElem)) { |
| 766 var dartxNames = <JS.Expression>[]; | 794 var dartxNames = <JS.Expression>[]; |
| 767 for (var m in methods) { | 795 for (var m in methods) { |
| 768 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { | 796 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { |
| 769 dartxNames.add(_elementMemberName(m.element, allowExtensions: false)); | 797 dartxNames.add(_elementMemberName(m.element, allowExtensions: false)); |
| 770 } | 798 } |
| 771 } | 799 } |
| 800 for (var f in fields) { | |
| 801 if (!f.isStatic) { | |
| 802 for (var d in f.fields.variables) { | |
| 803 if (d.element.isPublic) { | |
| 804 dartxNames.add( | |
| 805 _elementMemberName(d.element.getter, allowExtensions: false)); | |
| 806 } | |
| 807 } | |
| 808 } | |
| 809 } | |
| 772 if (dartxNames.isNotEmpty) { | 810 if (dartxNames.isNotEmpty) { |
| 773 body.add(js.statement('dart.defineExtensionNames(#)', | 811 body.add(js.statement('dart.defineExtensionNames(#)', |
| 774 [new JS.ArrayInitializer(dartxNames, multiline: true)])); | 812 [new JS.ArrayInitializer(dartxNames, multiline: true)])); |
| 775 } | 813 } |
| 776 } | 814 } |
| 777 | 815 |
| 778 body.add(_emitClassHeritageWorkaround(cls)); | 816 body.add(_emitClassHeritageWorkaround(cls)); |
| 779 | 817 |
| 780 // TODO(jmesserly): we should really just extend native Array. | 818 // TODO(jmesserly): we should really just extend native Array. |
| 781 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) { | 819 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) { |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 958 _collectExtensions(m, types); | 996 _collectExtensions(m, types); |
| 959 } | 997 } |
| 960 for (var i in type.interfaces) { | 998 for (var i in type.interfaces) { |
| 961 _collectExtensions(i, types); | 999 _collectExtensions(i, types); |
| 962 } | 1000 } |
| 963 _collectExtensions(type.superclass, types); | 1001 _collectExtensions(type.superclass, types); |
| 964 } | 1002 } |
| 965 | 1003 |
| 966 JS.Statement _overrideField(FieldElement e) { | 1004 JS.Statement _overrideField(FieldElement e) { |
| 967 var cls = e.enclosingElement; | 1005 var cls = e.enclosingElement; |
| 968 return js.statement('dart.virtualField(#, #)', | 1006 var name; |
| 969 [cls.name, _emitMemberName(e.name, type: cls.type)]); | 1007 if (_extensionTypes.contains(cls)) { |
|
Jennifer Messerly
2016/02/16 17:46:38
eeep. This is a little bit sketchy :). We try and
vsm
2016/02/18 01:13:09
Hmm, seems to work now if I revert. I had probabl
| |
| 1008 name = js.call('dart.getExtensionSymbol(#)', js.string(e.name)); | |
| 1009 } else { | |
| 1010 name = _emitMemberName(e.name, type: cls.type); | |
| 1011 } | |
|
Jacob
2016/02/16 17:47:35
nit: consider
var name = _extensionTypes.contain
vsm
2016/02/18 01:13:09
Removed change altogether.
| |
| 1012 return js.statement('dart.virtualField(#, #)', [cls.name, name]); | |
| 970 } | 1013 } |
| 971 | 1014 |
| 972 /// Generates the implicit default constructor for class C of the form | 1015 /// Generates the implicit default constructor for class C of the form |
| 973 /// `C() : super() {}`. | 1016 /// `C() : super() {}`. |
| 974 JS.Method _emitImplicitConstructor( | 1017 JS.Method _emitImplicitConstructor( |
| 975 ClassDeclaration node, List<FieldDeclaration> fields) { | 1018 ClassDeclaration node, List<FieldDeclaration> fields) { |
| 976 assert(_hasUnnamedConstructor(node.element) == fields.isNotEmpty); | 1019 assert(_hasUnnamedConstructor(node.element) == fields.isNotEmpty); |
| 977 | 1020 |
| 978 // If we don't have a method body, skip this. | 1021 // If we don't have a method body, skip this. |
| 979 var superCall = _superConstructorCall(node.element); | 1022 var superCall = _superConstructorCall(node.element); |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1321 t is ParameterizedType && t.typeArguments.any(_hasUnsoundTypeParameter); | 1364 t is ParameterizedType && t.typeArguments.any(_hasUnsoundTypeParameter); |
| 1322 | 1365 |
| 1323 JS.Expression _defaultParamValue(FormalParameter param) { | 1366 JS.Expression _defaultParamValue(FormalParameter param) { |
| 1324 if (param is DefaultFormalParameter && param.defaultValue != null) { | 1367 if (param is DefaultFormalParameter && param.defaultValue != null) { |
| 1325 return _visit(param.defaultValue); | 1368 return _visit(param.defaultValue); |
| 1326 } else { | 1369 } else { |
| 1327 return new JS.LiteralNull(); | 1370 return new JS.LiteralNull(); |
| 1328 } | 1371 } |
| 1329 } | 1372 } |
| 1330 | 1373 |
| 1331 JS.Fun _emitNativeFunctionBody( | 1374 JS.Fun _emitNativeFunctionBody(List<JS.Parameter> params, |
| 1332 List<JS.Parameter> params, List<JS.Expression> paramRefs, | 1375 List<JS.Expression> paramRefs, MethodDeclaration node) { |
| 1333 MethodDeclaration node) { | |
| 1334 if (node.isStatic) { | 1376 if (node.isStatic) { |
| 1335 // TODO(vsm): Do we need to handle this case? | 1377 // TODO(vsm): Do we need to handle this case? |
| 1336 return null; | 1378 return null; |
| 1337 } | 1379 } |
| 1338 | 1380 |
| 1339 String name = node.name.name; | 1381 String name = node.name.name; |
| 1340 var annotation = findAnnotation(node.element, isJsName); | 1382 var annotation = findAnnotation(node.element, isJsName); |
| 1341 if (annotation != null) { | 1383 if (annotation != null) { |
| 1342 name = getConstantField(annotation, 'name', types.stringType) | 1384 name = getConstantField(annotation, 'name', types.stringType) |
| 1343 ?.toStringValue(); | 1385 ?.toStringValue(); |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1558 // arrow functions yet (e.g. `({a} = {}) => 1`) but happily accepts them | 1600 // arrow functions yet (e.g. `({a} = {}) => 1`) but happily accepts them |
| 1559 // with regular functions (e.g. `function({a} = {}) { return 1 }`). | 1601 // with regular functions (e.g. `function({a} = {}) { return 1 }`). |
| 1560 // Note that Firefox accepts both syntaxes just fine. | 1602 // Note that Firefox accepts both syntaxes just fine. |
| 1561 // TODO(ochafik): Simplify this code when Chrome Canary catches up. | 1603 // TODO(ochafik): Simplify this code when Chrome Canary catches up. |
| 1562 var canUseArrowFun = !node.parameters.parameters.any(_isNamedParam); | 1604 var canUseArrowFun = !node.parameters.parameters.any(_isNamedParam); |
| 1563 | 1605 |
| 1564 JS.Node jsBody; | 1606 JS.Node jsBody; |
| 1565 var body = node.body; | 1607 var body = node.body; |
| 1566 if (body.isGenerator || body.isAsynchronous) { | 1608 if (body.isGenerator || body.isAsynchronous) { |
| 1567 var paramRefs = _emitParameterReferences(node.parameters); | 1609 var paramRefs = _emitParameterReferences(node.parameters); |
| 1568 jsBody = _emitGeneratorFunctionBody( | 1610 jsBody = |
| 1569 params, paramRefs, body, returnType); | 1611 _emitGeneratorFunctionBody(params, paramRefs, body, returnType); |
| 1570 } else if (body is ExpressionFunctionBody) { | 1612 } else if (body is ExpressionFunctionBody) { |
| 1571 jsBody = _visit(body.expression); | 1613 jsBody = _visit(body.expression); |
| 1572 } else { | 1614 } else { |
| 1573 jsBody = _visit(body); | 1615 jsBody = _visit(body); |
| 1574 } | 1616 } |
| 1575 if (jsBody is JS.Expression && !canUseArrowFun) { | 1617 if (jsBody is JS.Expression && !canUseArrowFun) { |
| 1576 jsBody = js.statement("{ return #; }", [jsBody]); | 1618 jsBody = js.statement("{ return #; }", [jsBody]); |
| 1577 } | 1619 } |
| 1578 var clos = canUseArrowFun | 1620 var clos = canUseArrowFun |
| 1579 ? new JS.ArrowFun(params, jsBody, | 1621 ? new JS.ArrowFun(params, jsBody, |
| 1580 typeParams: typeParams, returnType: returnType) | 1622 typeParams: typeParams, returnType: returnType) |
| 1581 : new JS.Fun(params, jsBody, | 1623 : new JS.Fun(params, jsBody, |
| 1582 typeParams: typeParams, returnType: returnType); | 1624 typeParams: typeParams, returnType: returnType); |
| 1583 if (!inStmt) { | 1625 if (!inStmt) { |
| 1584 var type = getStaticType(node); | 1626 var type = getStaticType(node); |
| 1585 return _emitFunctionTagged(clos, type, | 1627 return _emitFunctionTagged(clos, type, |
| 1586 topLevel: _executesAtTopLevel(node)); | 1628 topLevel: _executesAtTopLevel(node)); |
| 1587 } | 1629 } |
| 1588 return clos; | 1630 return clos; |
| 1589 } | 1631 } |
| 1590 } | 1632 } |
| 1591 | 1633 |
| 1592 JS.Fun _emitFunctionBody(List<JS.Parameter> params, | 1634 JS.Fun _emitFunctionBody( |
| 1593 List<JS.Expression> paramRefs, FunctionBody body, | 1635 List<JS.Parameter> params, |
| 1594 List<JS.Identifier> typeParams, JS.TypeRef returnType) { | 1636 List<JS.Expression> paramRefs, |
| 1637 FunctionBody body, | |
| 1638 List<JS.Identifier> typeParams, | |
| 1639 JS.TypeRef returnType) { | |
| 1595 // sync*, async, async* | 1640 // sync*, async, async* |
| 1596 if (body.isAsynchronous || body.isGenerator) { | 1641 if (body.isAsynchronous || body.isGenerator) { |
| 1597 // TODO(ochafik): Refine params: we don't need default values in the | 1642 // TODO(ochafik): Refine params: we don't need default values in the |
| 1598 // nested function, so we'd need to generate a custom, simpler params | 1643 // nested function, so we'd need to generate a custom, simpler params |
| 1599 // list here. | 1644 // list here. |
| 1600 return new JS.Fun( | 1645 return new JS.Fun( |
| 1601 params, | 1646 params, |
| 1602 js.statement('{ return #; }', [ | 1647 js.statement('{ return #; }', [ |
| 1603 _emitGeneratorFunctionBody(params, paramRefs, body, returnType) | 1648 _emitGeneratorFunctionBody(params, paramRefs, body, returnType) |
| 1604 ]), | 1649 ]), |
| 1605 returnType: returnType); | 1650 returnType: returnType); |
| 1606 } | 1651 } |
| 1607 // normal function (sync) | 1652 // normal function (sync) |
| 1608 return new JS.Fun(params, _visit(body), | 1653 return new JS.Fun(params, _visit(body), |
| 1609 typeParams: typeParams, returnType: returnType); | 1654 typeParams: typeParams, returnType: returnType); |
| 1610 } | 1655 } |
| 1611 | 1656 |
| 1612 JS.Expression _emitGeneratorFunctionBody( | 1657 JS.Expression _emitGeneratorFunctionBody(List<JS.Parameter> params, |
| 1613 List<JS.Parameter> params, List<JS.Expression> paramRefs, | 1658 List<JS.Expression> paramRefs, FunctionBody body, JS.TypeRef returnType) { |
| 1614 FunctionBody body, JS.TypeRef returnType) { | |
| 1615 var kind = body.isSynchronous ? 'sync' : 'async'; | 1659 var kind = body.isSynchronous ? 'sync' : 'async'; |
| 1616 if (body.isGenerator) kind += 'Star'; | 1660 if (body.isGenerator) kind += 'Star'; |
| 1617 | 1661 |
| 1618 // Transforms `sync*` `async` and `async*` function bodies | 1662 // Transforms `sync*` `async` and `async*` function bodies |
| 1619 // using ES6 generators. | 1663 // using ES6 generators. |
| 1620 // | 1664 // |
| 1621 // `sync*` wraps a generator in a Dart Iterable<T>: | 1665 // `sync*` wraps a generator in a Dart Iterable<T>: |
| 1622 // | 1666 // |
| 1623 // function name(<args>) { | 1667 // function name(<args>) { |
| 1624 // return dart.syncStar(function*(<args>) { | 1668 // return dart.syncStar(function*(<args>) { |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2173 bool _isNamedParam(FormalParameter param) => | 2217 bool _isNamedParam(FormalParameter param) => |
| 2174 param.kind == ParameterKind.NAMED; | 2218 param.kind == ParameterKind.NAMED; |
| 2175 | 2219 |
| 2176 @override | 2220 @override |
| 2177 List<JS.Parameter> visitFormalParameterList(FormalParameterList node) => | 2221 List<JS.Parameter> visitFormalParameterList(FormalParameterList node) => |
| 2178 _emitFormalParameterList(node); | 2222 _emitFormalParameterList(node); |
| 2179 | 2223 |
| 2180 // TODO(ochafik): Decouple Parameter from Identifier. | 2224 // TODO(ochafik): Decouple Parameter from Identifier. |
| 2181 List<JS.Expression> _emitParameterReferences(FormalParameterList node) => | 2225 List<JS.Expression> _emitParameterReferences(FormalParameterList node) => |
| 2182 node == null | 2226 node == null |
| 2183 ? <JS.Expression>[] | 2227 ? <JS.Expression>[] |
| 2184 : _emitFormalParameterList(node, allowDestructuring: false) | 2228 : _emitFormalParameterList(node, allowDestructuring: false) |
| 2185 .map((JS.Parameter p) { | 2229 .map((JS.Parameter p) { |
| 2186 if (p is JS.RestParameter) return new JS.Spread(p.parameter); | 2230 if (p is JS.RestParameter) return new JS.Spread(p.parameter); |
| 2187 return p as JS.Identifier; | 2231 return p as JS.Identifier; |
| 2188 }) | 2232 }).toList(); |
| 2189 .toList(); | |
| 2190 | 2233 |
| 2191 List<JS.Parameter> _emitFormalParameterList(FormalParameterList node, | 2234 List<JS.Parameter> _emitFormalParameterList(FormalParameterList node, |
| 2192 {bool allowDestructuring: true}) { | 2235 {bool allowDestructuring: true}) { |
| 2193 var result = <JS.Parameter>[]; | 2236 var result = <JS.Parameter>[]; |
| 2194 | 2237 |
| 2195 var namedVars = <JS.DestructuredVariable>[]; | 2238 var namedVars = <JS.DestructuredVariable>[]; |
| 2196 var destructure = allowDestructuring && options.destructureNamedParams; | 2239 var destructure = allowDestructuring && options.destructureNamedParams; |
| 2197 var hasNamedArgsConflictingWithObjectProperties = false; | 2240 var hasNamedArgsConflictingWithObjectProperties = false; |
| 2198 var needsOpts = false; | 2241 var needsOpts = false; |
| 2199 | 2242 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 2214 } | 2257 } |
| 2215 namedVars.add(new JS.DestructuredVariable( | 2258 namedVars.add(new JS.DestructuredVariable( |
| 2216 name: name, | 2259 name: name, |
| 2217 structure: structure, | 2260 structure: structure, |
| 2218 defaultValue: _defaultParamValue(param))); | 2261 defaultValue: _defaultParamValue(param))); |
| 2219 } else { | 2262 } else { |
| 2220 needsOpts = true; | 2263 needsOpts = true; |
| 2221 } | 2264 } |
| 2222 } else { | 2265 } else { |
| 2223 var jsParam = _visit(param); | 2266 var jsParam = _visit(param); |
| 2224 result.add( | 2267 result.add(param is DefaultFormalParameter && destructure |
| 2225 param is DefaultFormalParameter && destructure | 2268 ? new JS.DestructuredVariable( |
| 2226 ? new JS.DestructuredVariable( | 2269 name: jsParam, defaultValue: _defaultParamValue(param)) |
| 2227 name: jsParam, defaultValue: _defaultParamValue(param)) | 2270 : jsParam); |
| 2228 : jsParam); | |
| 2229 } | 2271 } |
| 2230 } | 2272 } |
| 2231 | 2273 |
| 2232 if (needsOpts) { | 2274 if (needsOpts) { |
| 2233 result.add(_namedArgTemp); | 2275 result.add(_namedArgTemp); |
| 2234 } else if (namedVars.isNotEmpty) { | 2276 } else if (namedVars.isNotEmpty) { |
| 2235 // Note: `var {valueOf} = {}` extracts `Object.prototype.valueOf`, so | 2277 // Note: `var {valueOf} = {}` extracts `Object.prototype.valueOf`, so |
| 2236 // in case there are conflicting names we create an object without | 2278 // in case there are conflicting names we create an object without |
| 2237 // any prototype. | 2279 // any prototype. |
| 2238 var defaultOpts = hasNamedArgsConflictingWithObjectProperties | 2280 var defaultOpts = hasNamedArgsConflictingWithObjectProperties |
| (...skipping 744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2983 return AstBuilder.propertyAccess(newTarget, node.propertyName); | 3025 return AstBuilder.propertyAccess(newTarget, node.propertyName); |
| 2984 } else { | 3026 } else { |
| 2985 var invoke = node as MethodInvocation; | 3027 var invoke = node as MethodInvocation; |
| 2986 return AstBuilder.methodInvoke( | 3028 return AstBuilder.methodInvoke( |
| 2987 newTarget, invoke.methodName, invoke.argumentList.arguments); | 3029 newTarget, invoke.methodName, invoke.argumentList.arguments); |
| 2988 } | 3030 } |
| 2989 } | 3031 } |
| 2990 | 3032 |
| 2991 bool _requiresStaticDispatch(Expression target, String memberName) { | 3033 bool _requiresStaticDispatch(Expression target, String memberName) { |
| 2992 var type = getStaticType(target); | 3034 var type = getStaticType(target); |
| 2993 if (!_isObjectProperty(memberName)) { | 3035 if (!_isObjectProperty(memberName) || target is SuperExpression) { |
|
Jennifer Messerly
2016/02/16 17:46:38
nice fix.
Jacob
2016/02/16 17:47:35
Why does target is SuperExpression require static
Jennifer Messerly
2016/02/16 18:22:00
Yup, that's what the CL is fixing, if I understand
| |
| 2994 return false; | 3036 return false; |
| 2995 } | 3037 } |
| 2996 if (!type.isObject && | 3038 if (!type.isObject && |
|
Jennifer Messerly
2016/02/16 18:22:01
wow, this code is confusing. Can we rewrite it lik
vsm
2016/02/18 01:13:09
Excellent point - cleaned up code! The explicit s
vsm
2016/02/18 15:23:55
Ugh, had to back off this a little bit. We don't
| |
| 2997 !_isJSBuiltinType(type) && | 3039 !_isJSBuiltinType(type) && |
| 2998 !_extensionTypes.contains(type.element) && | 3040 !_extensionTypes.contains(type.element) && |
| 2999 !_isNullable(target)) { | 3041 !_isNullable(target)) { |
| 3000 return false; | 3042 return false; |
| 3001 } | 3043 } |
| 3002 return true; | 3044 return true; |
| 3003 } | 3045 } |
| 3004 | 3046 |
| 3005 /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. | 3047 /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. |
| 3006 JS.Expression _emitGet(Expression target, SimpleIdentifier memberId) { | 3048 JS.Expression _emitGet(Expression target, SimpleIdentifier memberId) { |
| (...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3579 // conflict. We could use practically any character for this. | 3621 // conflict. We could use practically any character for this. |
| 3580 name = '+$name'; | 3622 name = '+$name'; |
| 3581 } | 3623 } |
| 3582 | 3624 |
| 3583 // Dart "extension" methods. Used for JS Array, Boolean, Number, String. | 3625 // Dart "extension" methods. Used for JS Array, Boolean, Number, String. |
| 3584 var baseType = type; | 3626 var baseType = type; |
| 3585 while (baseType is TypeParameterType) { | 3627 while (baseType is TypeParameterType) { |
| 3586 baseType = baseType.element.bound; | 3628 baseType = baseType.element.bound; |
| 3587 } | 3629 } |
| 3588 if (allowExtensions && | 3630 if (allowExtensions && |
| 3631 baseType != null && | |
| 3589 _extensionTypes.contains(baseType.element) && | 3632 _extensionTypes.contains(baseType.element) && |
| 3590 !_isObjectProperty(name)) { | 3633 !_isObjectProperty(name)) { |
| 3591 return js.call('dartx.#', _propertyName(name)); | 3634 return js.call('dartx.#', _propertyName(name)); |
| 3592 } | 3635 } |
| 3593 | 3636 |
| 3594 return _propertyName(name); | 3637 return _propertyName(name); |
| 3595 } | 3638 } |
| 3596 | 3639 |
| 3597 bool _externalOrNative(node) => | 3640 bool _externalOrNative(node) => |
| 3598 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; | 3641 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3725 | 3768 |
| 3726 JSGenerator(AbstractCompiler compiler) | 3769 JSGenerator(AbstractCompiler compiler) |
| 3727 : _types = compiler.context.typeProvider, | 3770 : _types = compiler.context.typeProvider, |
| 3728 super(compiler) { | 3771 super(compiler) { |
| 3729 // TODO(vsm): Eventually, we want to make this extensible - i.e., find | 3772 // TODO(vsm): Eventually, we want to make this extensible - i.e., find |
| 3730 // annotations in user code as well. It would need to be summarized in | 3773 // annotations in user code as well. It would need to be summarized in |
| 3731 // the element model - not searched this way on every compile. | 3774 // the element model - not searched this way on every compile. |
| 3732 var finder = new _ExtensionFinder(context, _extensionTypes, _types); | 3775 var finder = new _ExtensionFinder(context, _extensionTypes, _types); |
| 3733 finder._addExtensionTypes('dart:_interceptors'); | 3776 finder._addExtensionTypes('dart:_interceptors'); |
| 3734 finder._addExtensionTypes('dart:_native_typed_data'); | 3777 finder._addExtensionTypes('dart:_native_typed_data'); |
| 3778 finder._addExtensionTypes('dart:html'); | |
| 3779 finder._addExtensionTypes('dart:indexed_db'); | |
| 3780 finder._addExtensionTypes('dart:svg'); | |
| 3781 finder._addExtensionTypes('dart:web_audio'); | |
| 3782 finder._addExtensionTypes('dart:web_gl'); | |
| 3783 finder._addExtensionTypes('dart:web_sql'); | |
| 3735 | 3784 |
| 3736 // TODO(vsm): If we're analyzing against the main SDK, those | 3785 // TODO(vsm): If we're analyzing against the main SDK, those |
| 3737 // types are not explicitly annotated. | 3786 // types are not explicitly annotated. |
| 3738 finder._addExtensionType(_types.intType); | 3787 finder._addExtensionType(_types.intType); |
| 3739 finder._addExtensionType(_types.doubleType); | 3788 finder._addExtensionType(_types.doubleType); |
| 3740 finder._addExtensionType(_types.boolType); | 3789 finder._addExtensionType(_types.boolType); |
| 3741 finder._addExtensionType(_types.stringType); | 3790 finder._addExtensionType(_types.stringType); |
| 3742 } | 3791 } |
| 3743 | 3792 |
| 3744 String generateLibrary(LibraryUnit unit) { | 3793 String generateLibrary(LibraryUnit unit) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3779 | 3828 |
| 3780 /// A special kind of element created by the compiler, signifying a temporary | 3829 /// A special kind of element created by the compiler, signifying a temporary |
| 3781 /// variable. These objects use instance equality, and should be shared | 3830 /// variable. These objects use instance equality, and should be shared |
| 3782 /// everywhere in the tree where they are treated as the same variable. | 3831 /// everywhere in the tree where they are treated as the same variable. |
| 3783 class TemporaryVariableElement extends LocalVariableElementImpl { | 3832 class TemporaryVariableElement extends LocalVariableElementImpl { |
| 3784 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 3833 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
| 3785 | 3834 |
| 3786 int get hashCode => identityHashCode(this); | 3835 int get hashCode => identityHashCode(this); |
| 3787 bool operator ==(Object other) => identical(this, other); | 3836 bool operator ==(Object other) => identical(this, other); |
| 3788 } | 3837 } |
| OLD | NEW |