Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: lib/src/codegen/js_codegen.dart

Issue 1153003003: fixes #40, extension methods for primitive types (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 dev_compiler.src.codegen.js_codegen; 5 library dev_compiler.src.codegen.js_codegen;
6 6
7 import 'dart:collection' show HashSet, HashMap; 7 import 'dart:collection' show HashSet, HashMap;
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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 const DSETINDEX = 'dsetindex'; 48 const DSETINDEX = 'dsetindex';
49 const DCALL = 'dcall'; 49 const DCALL = 'dcall';
50 const DSEND = 'dsend'; 50 const DSEND = 'dsend';
51 51
52 class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { 52 class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
53 final AbstractCompiler compiler; 53 final AbstractCompiler compiler;
54 final CompilerOptions options; 54 final CompilerOptions options;
55 final TypeRules rules; 55 final TypeRules rules;
56 final LibraryInfo libraryInfo; 56 final LibraryInfo libraryInfo;
57 57
58 /// The global extension method table. 58 /// The global extension type table.
59 final HashMap<String, List<InterfaceType>> _extensionMethods; 59 final HashSet<ClassElement> _extensionTypes;
60 60
61 /// Information that is precomputed for this library, indicates which fields 61 /// Information that is precomputed for this library, indicates which fields
62 /// need storage slots. 62 /// need storage slots.
63 final HashSet<FieldElement> _fieldsNeedingStorage; 63 final HashSet<FieldElement> _fieldsNeedingStorage;
64 64
65 /// The variable for the target of the current `..` cascade expression. 65 /// The variable for the target of the current `..` cascade expression.
66 SimpleIdentifier _cascadeTarget; 66 SimpleIdentifier _cascadeTarget;
67 67
68 /// The variable for the current catch clause 68 /// The variable for the current catch clause
69 SimpleIdentifier _catchParameter; 69 SimpleIdentifier _catchParameter;
(...skipping 13 matching lines...) Expand all
83 /// The name for the library's exports inside itself. 83 /// The name for the library's exports inside itself.
84 /// `exports` was chosen as the most similar to ES module patterns. 84 /// `exports` was chosen as the most similar to ES module patterns.
85 final _exportsVar = new JS.TemporaryId('exports'); 85 final _exportsVar = new JS.TemporaryId('exports');
86 final _namedArgTemp = new JS.TemporaryId('opts'); 86 final _namedArgTemp = new JS.TemporaryId('opts');
87 87
88 ConstFieldVisitor _constField; 88 ConstFieldVisitor _constField;
89 89
90 ModuleItemLoadOrder _loader; 90 ModuleItemLoadOrder _loader;
91 91
92 JSCodegenVisitor(AbstractCompiler compiler, this.libraryInfo, 92 JSCodegenVisitor(AbstractCompiler compiler, this.libraryInfo,
93 this._extensionMethods, this._fieldsNeedingStorage) 93 this._extensionTypes, this._fieldsNeedingStorage)
94 : compiler = compiler, 94 : compiler = compiler,
95 options = compiler.options, 95 options = compiler.options,
96 rules = compiler.rules { 96 rules = compiler.rules {
97 _loader = new ModuleItemLoadOrder(_emitModuleItem); 97 _loader = new ModuleItemLoadOrder(_emitModuleItem);
98 } 98 }
99 99
100 LibraryElement get currentLibrary => libraryInfo.library; 100 LibraryElement get currentLibrary => libraryInfo.library;
101 TypeProvider get types => rules.provider; 101 TypeProvider get types => rules.provider;
102 102
103 JS.Program emitLibrary(LibraryUnit library) { 103 JS.Program emitLibrary(LibraryUnit library) {
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 ])); 552 ]));
553 } 553 }
554 554
555 // Interfaces 555 // Interfaces
556 if (classElem.interfaces.isNotEmpty) { 556 if (classElem.interfaces.isNotEmpty) {
557 body.add(js.statement('#[dart.implements] = () => #;', [ 557 body.add(js.statement('#[dart.implements] = () => #;', [
558 name, 558 name,
559 new JS.ArrayInitializer( 559 new JS.ArrayInitializer(
560 classElem.interfaces.map(_emitTypeName).toList()) 560 classElem.interfaces.map(_emitTypeName).toList())
561 ])); 561 ]));
562
563 // If a concrete class implements one of our extensions, we might need to
564 // add forwarders.
565 var extensions = _extensionsToImplement(classElem);
566 if (extensions.isNotEmpty) {
567 // Get the dynamic substitution of the extension interface, as we only
568 // care about what methods it has, not their implementation.
569 var jsTypes = extensions
570 .map((e) => _emitTypeName(fillDynamicTypeArgs(e.type, types)));
571 body.add(js.statement('dart.implementExtension(#, () => #);', [
572 name,
573 new JS.ArrayInitializer(jsTypes.toList(growable: false))
574 ]));
575 }
562 } 576 }
563 577
564 // Named constructors 578 // Named constructors
565 for (ConstructorDeclaration member in ctors) { 579 for (ConstructorDeclaration member in ctors) {
566 if (member.name != null && member.factoryKeyword == null) { 580 if (member.name != null && member.factoryKeyword == null) {
567 body.add(js.statement('dart.defineNamedConstructor(#, #);', [ 581 body.add(js.statement('dart.defineNamedConstructor(#, #);', [
568 name, 582 name,
569 _emitMemberName(member.name.name, isStatic: true) 583 _emitMemberName(member.name.name, isStatic: true)
570 ])); 584 ]));
571 } 585 }
(...skipping 18 matching lines...) Expand all
590 for (MethodDeclaration node in methods) { 604 for (MethodDeclaration node in methods) {
591 if (!(node.isSetter || node.isGetter || node.isAbstract)) { 605 if (!(node.isSetter || node.isGetter || node.isAbstract)) {
592 var name = node.name.name; 606 var name = node.name.name;
593 var element = node.element; 607 var element = node.element;
594 var inheritedElement = 608 var inheritedElement =
595 classElem.lookUpInheritedConcreteMethod(name, currentLibrary); 609 classElem.lookUpInheritedConcreteMethod(name, currentLibrary);
596 if (inheritedElement != null && 610 if (inheritedElement != null &&
597 inheritedElement.type == element.type) continue; 611 inheritedElement.type == element.type) continue;
598 var unary = node.parameters.parameters.isEmpty; 612 var unary = node.parameters.parameters.isEmpty;
599 var memberName = _emitMemberName(name, 613 var memberName = _emitMemberName(name,
600 type: cType, unary: unary, isStatic: node.isStatic); 614 type: cType,
615 unary: unary,
616 isStatic: node.isStatic,
617 declaration: true);
601 var parts = 618 var parts =
602 _emitFunctionTypeParts(element.type, dynamicIsBottom: false); 619 _emitFunctionTypeParts(element.type, dynamicIsBottom: false);
603 var property = 620 var property =
604 new JS.Property(memberName, new JS.ArrayInitializer(parts)); 621 new JS.Property(memberName, new JS.ArrayInitializer(parts));
605 if (node.isStatic) { 622 if (node.isStatic) {
606 tStatics.add(property); 623 tStatics.add(property);
607 sNames.add(memberName); 624 sNames.add(memberName);
608 } else tMethods.add(property); 625 } else tMethods.add(property);
609 } 626 }
610 } 627 }
(...skipping 27 matching lines...) Expand all
638 if (!sigFields.isEmpty) { 655 if (!sigFields.isEmpty) {
639 var sig = new JS.ObjectInitializer(sigFields); 656 var sig = new JS.ObjectInitializer(sigFields);
640 var classExpr = new JS.Identifier(name); 657 var classExpr = new JS.Identifier(name);
641 body.add(js.statement('dart.setSignature(#, #);', [classExpr, sig])); 658 body.add(js.statement('dart.setSignature(#, #);', [classExpr, sig]));
642 } 659 }
643 } 660 }
644 661
645 return _statement(body); 662 return _statement(body);
646 } 663 }
647 664
665 Set<ClassElement> _extensionsToImplement(ClassElement element) {
666 var extensions = new Set<ClassElement>();
667 if (_extensionTypes.contains(element)) return extensions;
668
669 // Collect all extension types we implement.
670 _collectExtensions(element.type, extensions);
671 if (extensions.isEmpty) return extensions;
672
673 // Filter out extensions implemented by our superclass or mixins.
674 var s = element.supertype.element;
675 if (!s.isAbstract) extensions.removeAll(_extensionsToImplement(s));
676 for (var mixin in element.mixins) {
677 var m = mixin.element;
678 if (!m.isAbstract) extensions.removeAll(_extensionsToImplement(m));
679 }
680 return extensions;
681 }
682
683 /// Collections the type and all supertypes, including interfaces, but
684 /// excluding [Object].
685 void _collectExtensions(InterfaceType type, Set<ClassElement> types) {
686 if (type.isObject) return;
687 var element = type.element;
688 if (_extensionTypes.contains(element)) types.add(element);
689 for (var m in type.mixins.reversed) {
690 _collectExtensions(m, types);
691 }
692 for (var i in type.interfaces) {
693 _collectExtensions(i, types);
694 }
695 _collectExtensions(type.superclass, types);
696 }
697
648 JS.Statement _overrideField(FieldElement e) { 698 JS.Statement _overrideField(FieldElement e) {
649 var cls = e.enclosingElement; 699 var cls = e.enclosingElement;
650 return js.statement('dart.virtualField(#, #)', [ 700 return js.statement('dart.virtualField(#, #)', [
651 cls.name, 701 cls.name,
652 _emitMemberName(e.name, type: cls.type) 702 _emitMemberName(e.name, type: cls.type)
653 ]); 703 ]);
654 } 704 }
655 705
656 /// Generates the implicit default constructor for class C of the form 706 /// Generates the implicit default constructor for class C of the form
657 /// `C() : super() {}`. 707 /// `C() : super() {}`.
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
987 1037
988 JS.Method _emitMethodDeclaration(DartType type, MethodDeclaration node) { 1038 JS.Method _emitMethodDeclaration(DartType type, MethodDeclaration node) {
989 if (node.isAbstract || _externalOrNative(node)) { 1039 if (node.isAbstract || _externalOrNative(node)) {
990 return null; 1040 return null;
991 } 1041 }
992 1042
993 var params = _visit(node.parameters); 1043 var params = _visit(node.parameters);
994 if (params == null) params = []; 1044 if (params == null) params = [];
995 1045
996 var memberName = _emitMemberName(node.name.name, 1046 var memberName = _emitMemberName(node.name.name,
997 type: type, unary: params.isEmpty, isStatic: node.isStatic); 1047 type: type,
1048 unary: params.isEmpty,
1049 isStatic: node.isStatic,
1050 declaration: true);
998 return new JS.Method(memberName, new JS.Fun(params, _visit(node.body)), 1051 return new JS.Method(memberName, new JS.Fun(params, _visit(node.body)),
999 isGetter: node.isGetter, 1052 isGetter: node.isGetter,
1000 isSetter: node.isSetter, 1053 isSetter: node.isSetter,
1001 isStatic: node.isStatic); 1054 isStatic: node.isStatic);
1002 } 1055 }
1003 1056
1004 @override 1057 @override
1005 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { 1058 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) {
1006 assert(node.parent is CompilationUnit); 1059 assert(node.parent is CompilationUnit);
1007 1060
(...skipping 651 matching lines...) Expand 10 before | Expand all | Expand 10 after
1659 body.add(js.statement('dart.copyProperties(#, { # });', [ 1712 body.add(js.statement('dart.copyProperties(#, { # });', [
1660 _exportsVar, 1713 _exportsVar,
1661 _properties.map(_emitTopLevelProperty) 1714 _properties.map(_emitTopLevelProperty)
1662 ])); 1715 ]));
1663 _properties.clear(); 1716 _properties.clear();
1664 } 1717 }
1665 1718
1666 @override 1719 @override
1667 visitConstructorName(ConstructorName node) { 1720 visitConstructorName(ConstructorName node) {
1668 var typeName = _visit(node.type); 1721 var typeName = _visit(node.type);
1669 if (node.name != null || node.staticElement.isFactory) { 1722 var element = node.staticElement;
1670 var namedCtor = _constructorName(node.staticElement); 1723 if (node.name != null || element.isFactory) {
1724 var namedCtor = _constructorName(element);
1671 return new JS.PropertyAccess(typeName, namedCtor); 1725 return new JS.PropertyAccess(typeName, namedCtor);
1672 } 1726 }
1673 return typeName; 1727 return typeName;
1674 } 1728 }
1675 1729
1676 @override 1730 @override
1677 visitInstanceCreationExpression(InstanceCreationExpression node) { 1731 visitInstanceCreationExpression(InstanceCreationExpression node) {
1678 emitNew() { 1732 emitNew() {
1679 var ctor = _visit(node.constructorName); 1733 JS.Expression ctor;
1734 bool isFactory = false;
1735 var element = node.staticElement;
1736 if (element == null) {
1737 // TODO(jmesserly): this only happens if we had a static error.
1738 // Should we generate a throw instead?
1739 ctor = _visit(node.constructorName.type);
1740 var ctorName = node.constructorName.name;
1741 if (ctorName != null) {
1742 ctor = new JS.PropertyAccess(ctor, _propertyName(ctorName.name));
1743 }
1744 } else {
1745 ctor = _visit(node.constructorName);
1746 isFactory = element.isFactory;
1747 }
1680 var args = _visit(node.argumentList); 1748 var args = _visit(node.argumentList);
1681 var isFactory = node.staticElement.isFactory;
1682 return isFactory ? new JS.Call(ctor, args) : new JS.New(ctor, args); 1749 return isFactory ? new JS.Call(ctor, args) : new JS.New(ctor, args);
1683 } 1750 }
1684 if (node.isConst) return _emitConst(node, emitNew); 1751 if (node.isConst) return _emitConst(node, emitNew);
1685 return emitNew(); 1752 return emitNew();
1686 } 1753 }
1687 1754
1688 /// True if this type is built-in to JS, and we use the values unwrapped. 1755 /// True if this type is built-in to JS, and we use the values unwrapped.
1689 /// For these types we generate a calling convention via static 1756 /// For these types we generate a calling convention via static
1690 /// "extension methods". This allows types to be extended without adding 1757 /// "extension methods". This allows types to be extended without adding
1691 /// extensions directly on the prototype. 1758 /// extensions directly on the prototype.
(...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after
2331 return new JS.New(_emitTypeName(types.symbolType), [name]); 2398 return new JS.New(_emitTypeName(types.symbolType), [name]);
2332 } 2399 }
2333 return _emitConst(node, emitSymbol); 2400 return _emitConst(node, emitSymbol);
2334 } 2401 }
2335 2402
2336 @override 2403 @override
2337 visitListLiteral(ListLiteral node) { 2404 visitListLiteral(ListLiteral node) {
2338 emitList() { 2405 emitList() {
2339 JS.Expression list = new JS.ArrayInitializer(_visitList(node.elements)); 2406 JS.Expression list = new JS.ArrayInitializer(_visitList(node.elements));
2340 ParameterizedType type = node.staticType; 2407 ParameterizedType type = node.staticType;
2341 if (type.typeArguments.any((a) => a != types.dynamicType)) { 2408 var elementType = type.typeArguments.single;
2342 list = js.call('dart.setType(#, #)', [list, _emitTypeName(type)]); 2409 if (elementType != types.dynamicType) {
2410 list = js.call('dart.list(#, #)', [list, _emitTypeName(elementType)]);
2343 } 2411 }
2344 return list; 2412 return list;
2345 } 2413 }
2346 if (node.constKeyword != null) return _emitConst(node, emitList); 2414 if (node.constKeyword != null) return _emitConst(node, emitList);
2347 return emitList(); 2415 return emitList();
2348 } 2416 }
2349 2417
2350 @override 2418 @override
2351 visitMapLiteral(MapLiteral node) { 2419 visitMapLiteral(MapLiteral node) {
2352 // TODO(jmesserly): we can likely make these faster. 2420 // TODO(jmesserly): we can likely make these faster.
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
2481 /// 2549 ///
2482 /// This follows the same pattern as EcmaScript 6 Map: 2550 /// This follows the same pattern as EcmaScript 6 Map:
2483 /// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_ Objects/Map> 2551 /// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_ Objects/Map>
2484 /// 2552 ///
2485 /// Unary minus looks like: `x['unary-']()`. Note that [unary] must be passed 2553 /// Unary minus looks like: `x['unary-']()`. Note that [unary] must be passed
2486 /// for this transformation to happen, otherwise binary minus is assumed. 2554 /// for this transformation to happen, otherwise binary minus is assumed.
2487 /// 2555 ///
2488 /// Equality is a bit special, it is generated via the Dart `equals` runtime 2556 /// Equality is a bit special, it is generated via the Dart `equals` runtime
2489 /// helper, that checks for null. The user defined method is called '=='. 2557 /// helper, that checks for null. The user defined method is called '=='.
2490 /// 2558 ///
2491 JS.Expression _emitMemberName(String name, 2559 JS.Expression _emitMemberName(String name, {DartType type, bool unary: false,
2492 {DartType type, bool unary: false, bool isStatic: false}) { 2560 bool isStatic: false, bool declaration: false}) {
2493 2561
2494 // Static members skip the rename steps. 2562 // Static members skip the rename steps.
2495 if (isStatic) return _propertyName(name); 2563 if (isStatic) return _propertyName(name);
2496 2564
2497 if (name.startsWith('_')) { 2565 if (name.startsWith('_')) {
2498 return _privateNames.putIfAbsent( 2566 return _privateNames.putIfAbsent(
2499 name, () => _initSymbol(new JS.TemporaryId(name))); 2567 name, () => _initSymbol(new JS.TemporaryId(name)));
2500 } 2568 }
2501 2569
2502 // Check for extension method:
2503 var extLibrary = _findExtensionLibrary(name, type);
2504
2505 if (name == '[]') { 2570 if (name == '[]') {
2506 name = 'get'; 2571 name = 'get';
2507 } else if (name == '[]=') { 2572 } else if (name == '[]=') {
2508 name = 'set'; 2573 name = 'set';
2509 } else if (name == '-' && unary) { 2574 } else if (name == '-' && unary) {
2510 name = 'unary-'; 2575 name = 'unary-';
2511 } 2576 }
2512 2577
2513 if (extLibrary != null) { 2578 // Dart "extension" methods. Used for JS Array, Boolean, Number, String.
2514 return _extensionMethodName(name, extLibrary); 2579 if (!declaration && _extensionTypes.contains(type.element)) {
2580 // Special case `length`. We can call it directly.
2581 if (name != 'length') return js.call('dartx.#', _propertyName(name));
2515 } 2582 }
2516 2583
2517 return _propertyName(name); 2584 return _propertyName(name);
2518 } 2585 }
2519 2586
2520 LibraryElement _findExtensionLibrary(String name, DartType type) {
2521 if (type is! InterfaceType) return null;
2522
2523 var extLibrary = null;
2524 var extensionTypes = _extensionMethods[name];
2525 if (extensionTypes != null) {
2526 // Normalize the type to ignore generics.
2527 type = fillDynamicTypeArgs(type, types);
2528 for (var t in extensionTypes) {
2529 if (rules.isSubTypeOf(type, t)) {
2530 assert(extLibrary == null || extLibrary == t.element.library);
2531 extLibrary = t.element.library;
2532 }
2533 }
2534 }
2535 return extLibrary;
2536 }
2537
2538 JS.Expression _extensionMethodName(String name, LibraryElement library) {
2539 var extName = '\$$name';
2540 if (library == currentLibrary) {
2541 // TODO(jacobr): need to do a better job ensuring that extension method
2542 // name symbols do not conflict with other symbols before we can let
2543 // user defined libraries define extension methods.
2544 if (_extensionMethodNames.add(extName)) {
2545 _initSymbol(new JS.Identifier(extName));
2546 _addExport(extName);
2547 }
2548 return new JS.Identifier(extName);
2549 }
2550 return js.call('#.#', [_libraryName(library), _propertyName(extName)]);
2551 }
2552
2553 bool _externalOrNative(node) => 2587 bool _externalOrNative(node) =>
2554 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; 2588 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody;
2555 2589
2556 FunctionBody _functionBody(node) => 2590 FunctionBody _functionBody(node) =>
2557 node is FunctionDeclaration ? node.functionExpression.body : node.body; 2591 node is FunctionDeclaration ? node.functionExpression.body : node.body;
2558 2592
2559 /// Choose a canonical name from the library element. 2593 /// Choose a canonical name from the library element.
2560 /// This never uses the library's name (the identifier in the `library` 2594 /// This never uses the library's name (the identifier in the `library`
2561 /// declaration) as it doesn't have any meaningful rules enforced. 2595 /// declaration) as it doesn't have any meaningful rules enforced.
2562 JS.Identifier _libraryName(LibraryElement library) { 2596 JS.Identifier _libraryName(LibraryElement library) {
2563 if (library == currentLibrary) return _exportsVar; 2597 if (library == currentLibrary) return _exportsVar;
2564 return _imports.putIfAbsent( 2598 return _imports.putIfAbsent(
2565 library, () => new JS.TemporaryId(jsLibraryName(library))); 2599 library, () => new JS.TemporaryId(jsLibraryName(library)));
2566 } 2600 }
2567 2601
2568 DartType getStaticType(Expression e) => rules.getStaticType(e); 2602 DartType getStaticType(Expression e) => rules.getStaticType(e);
2569 } 2603 }
2570 2604
2571 class JSGenerator extends CodeGenerator { 2605 class JSGenerator extends CodeGenerator {
2572 /// For fast lookup of extension methods, we first check the name, then do a 2606 final _extensionTypes = new HashSet<ClassElement>();
2573 /// (possibly expensive) subtype test to see if it matches one of the types
2574 /// that declares that method.
2575 final _extensionMethods = new HashMap<String, List<InterfaceType>>();
2576 2607
2577 JSGenerator(AbstractCompiler context) : super(context) { 2608 JSGenerator(AbstractCompiler compiler) : super(compiler) {
2578
2579 // TODO(jacobr): determine the the set of types with extension methods from 2609 // TODO(jacobr): determine the the set of types with extension methods from
2580 // the annotations rather than hard coding the list once the analyzer 2610 // the annotations rather than hard coding the list once the analyzer
2581 // supports summaries. 2611 // supports summaries.
2582 var extensionTypes = [types.listType, types.iterableType]; 2612 var context = compiler.context;
2583 for (var type in extensionTypes) { 2613 var src = context.sourceFactory.forUri('dart:_interceptors');
2584 type = fillDynamicTypeArgs(type, rules.provider); 2614 var interceptors = context.computeLibraryElement(src);
2585 var e = type.element; 2615 for (var t in ['JSArray', 'JSString', 'JSInt', 'JSDouble', 'JSBool']) {
2586 var names = new HashSet<String>() 2616 _addExtensionType(interceptors.getType(t).type);
2587 ..addAll(e.methods.map((m) => m.name))
2588 ..addAll(e.accessors.map((m) => m.name));
2589 for (var name in names) {
2590 _extensionMethods.putIfAbsent(name, () => []).add(type);
2591 }
2592 } 2617 }
2593 } 2618 }
2594 2619
2595 TypeProvider get types => rules.provider; 2620 void _addExtensionType(InterfaceType t) {
2621 if (t.isObject || !_extensionTypes.add(t.element)) return;
2622 t = fillDynamicTypeArgs(t, rules.provider);
2623 t.interfaces.forEach(_addExtensionType);
2624 t.mixins.forEach(_addExtensionType);
2625 _addExtensionType(t.superclass);
2626 }
2596 2627
2597 String generateLibrary(LibraryUnit unit, LibraryInfo info) { 2628 String generateLibrary(LibraryUnit unit, LibraryInfo info) {
2598 var fields = findFieldsNeedingStorage(unit); 2629 var fields = findFieldsNeedingStorage(unit);
2599 var codegen = 2630 var codegen = new JSCodegenVisitor(compiler, info, _extensionTypes, fields);
2600 new JSCodegenVisitor(compiler, info, _extensionMethods, fields);
2601 var module = codegen.emitLibrary(unit); 2631 var module = codegen.emitLibrary(unit);
2602 var dir = path.join(outDir, jsOutputPath(info, root)); 2632 var dir = path.join(outDir, jsOutputPath(info, root));
2603 return writeJsLibrary(module, dir, emitSourceMaps: options.emitSourceMaps); 2633 return writeJsLibrary(module, dir, emitSourceMaps: options.emitSourceMaps);
2604 } 2634 }
2605 } 2635 }
2606 2636
2607 /// Choose a canonical name from the library element. 2637 /// Choose a canonical name from the library element.
2608 /// This never uses the library's name (the identifier in the `library` 2638 /// This never uses the library's name (the identifier in the `library`
2609 /// declaration) as it doesn't have any meaningful rules enforced. 2639 /// declaration) as it doesn't have any meaningful rules enforced.
2610 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library); 2640 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2646 2676
2647 /// A special kind of element created by the compiler, signifying a temporary 2677 /// A special kind of element created by the compiler, signifying a temporary
2648 /// variable. These objects use instance equality, and should be shared 2678 /// variable. These objects use instance equality, and should be shared
2649 /// everywhere in the tree where they are treated as the same variable. 2679 /// everywhere in the tree where they are treated as the same variable.
2650 class TemporaryVariableElement extends LocalVariableElementImpl { 2680 class TemporaryVariableElement extends LocalVariableElementImpl {
2651 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 2681 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
2652 2682
2653 int get hashCode => identityHashCode(this); 2683 int get hashCode => identityHashCode(this);
2654 bool operator ==(Object other) => identical(this, other); 2684 bool operator ==(Object other) => identical(this, other);
2655 } 2685 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698