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

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

Issue 1126713002: fixes #130, accept anything with `iterator` in for loops (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: fix iterator Created 5 years, 7 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
« no previous file with comments | « lib/runtime/dart_runtime.js ('k') | lib/src/utils.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 555 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 var isObject = type.isObject; 566 var isObject = type.isObject;
567 var name = node.name.name; 567 var name = node.name.name;
568 568
569 // Iff no constructor is specified for a class C, it implicitly has a 569 // Iff no constructor is specified for a class C, it implicitly has a
570 // default constructor `C() : super() {}`, unless C is class Object. 570 // default constructor `C() : super() {}`, unless C is class Object.
571 var jsMethods = <JS.Method>[]; 571 var jsMethods = <JS.Method>[];
572 if (ctors.isEmpty && !isObject) { 572 if (ctors.isEmpty && !isObject) {
573 jsMethods.add(_emitImplicitConstructor(node, name, fields)); 573 jsMethods.add(_emitImplicitConstructor(node, name, fields));
574 } 574 }
575 575
576 for (var member in node.members) { 576 bool hasJsPeer = getAnnotationValue(node, _isJsPeerInterface) != null;
577 if (member is ConstructorDeclaration) { 577
578 jsMethods.add(_emitConstructor(member, name, fields, isObject)); 578 bool hasIterator = false;
579 } else if (member is MethodDeclaration) { 579 for (var m in node.members) {
580 jsMethods.add(_emitMethodDeclaration(type, member)); 580 if (m is ConstructorDeclaration) {
581 jsMethods.add(_emitConstructor(m, name, fields, isObject));
582 } else if (m is MethodDeclaration) {
583 jsMethods.add(_emitMethodDeclaration(type, m));
584
585 if (!hasJsPeer && m.isGetter && m.name.name == 'iterator') {
586 hasIterator = true;
587 jsMethods.add(_emitIterable(type));
vsm 2015/05/05 14:19:28 Should we check the return type of iterator here?
Jennifer Messerly 2015/05/05 15:38:25 First off, just confirming: most of this is the jo
588 }
581 } 589 }
582 } 590 }
583 591
584 // Support for adapting dart:core Iterator/Iterable to ES6 versions. 592 // If the type doesn't have an `iterator`, but claims to implement Iterable,
585 // This lets them use for-of loops transparently. 593 // we inject the adaptor method here, as it's less code size to put the
586 // https://github.com/lukehoban/es6features#iterators--forof 594 // helper on a parent class. This pattern is common in the core libraries
587 if (element.library.isDartCore && element.name == 'Iterable') { 595 // (e.g. IterableMixin<E> and IterableBase<E>).
588 JS.Fun body = js.call('''function() { 596 //
589 var iterator = this.iterator; 597 // (We could do this same optimization for any interface with an `iterator`
590 return { 598 // method, but that's more expensive to check for, so it doesn't seem worth
591 next() { 599 // it. The above case for an explicit `iterator` method will catch those.)
592 var done = iterator.moveNext(); 600 if (!hasJsPeer && !hasIterator && _implementsIterable(type)) {
593 return { done: done, current: done ? void 0 : iterator.current }; 601 jsMethods.add(_emitIterable(type));
594 }
595 };
596 }''');
597 jsMethods.add(new JS.Method(js.call('$_SYMBOL.iterator'), body));
598 } 602 }
603
599 return jsMethods.where((m) => m != null).toList(growable: false); 604 return jsMethods.where((m) => m != null).toList(growable: false);
600 } 605 }
601 606
607 bool _implementsIterable(InterfaceType t) =>
608 t.interfaces.any((i) => i.element.type == types.iterableType);
609
610 /// Support for adapting dart:core Iterable to ES6 versions.
611 ///
612 /// This lets them use for-of loops transparently:
613 /// <https://github.com/lukehoban/es6features#iterators--forof>
614 ///
615 /// This will return `null` if the adapter was already added on a super type,
616 /// otherwise it returns the adapter code.
617 // TODO(jmesserly): should we adapt `Iterator` too?
618 JS.Method _emitIterable(InterfaceType t) {
619 // If a parent had an `iterator` (concrete or abstract) or implements
620 // Iterable, we know the adapter is already there, so we can skip it as a
621 // simple code size optimization.
622 var parent = t.lookUpGetterInSuperclass('iterator', t.element.library);
623 if (parent != null) return null;
624 parent = findSupertype(t, _implementsIterable);
625 if (parent != null) return null;
626
627 // Otherwise, emit the adapter method, which wraps the Dart iterator in
628 // an ES6 iterator.
629 return new JS.Method(js.call('$_SYMBOL.iterator'), js.call(
630 'function() { return new dart.JsIterator(this.#); }',
631 [_emitMemberName('iterator', type: t)]));
632 }
633
602 /// Emit class members that need to come after the class declaration, such 634 /// Emit class members that need to come after the class declaration, such
603 /// as static fields. See [_emitClassMethods] for things that are emitted 635 /// as static fields. See [_emitClassMethods] for things that are emitted
604 /// inside the ES6 `class { ... }` node. 636 /// inside the ES6 `class { ... }` node.
605 JS.Statement _finishClassMembers(ClassElement classElem, 637 JS.Statement _finishClassMembers(ClassElement classElem,
606 JS.ClassExpression cls, List<ConstructorDeclaration> ctors, 638 JS.ClassExpression cls, List<ConstructorDeclaration> ctors,
607 List<FieldDeclaration> fields, List<FieldDeclaration> staticFields, 639 List<FieldDeclaration> fields, List<FieldDeclaration> staticFields,
608 String jsPeerName) { 640 String jsPeerName) {
609 var name = classElem.name; 641 var name = classElem.name;
610 var body = <JS.Statement>[]; 642 var body = <JS.Statement>[];
611 body.add(new JS.ClassDeclaration(cls)); 643 body.add(new JS.ClassDeclaration(cls));
(...skipping 1926 matching lines...) Expand 10 before | Expand all | Expand 10 after
2538 // TODO(jmesserly): validate the library. See issue #135. 2570 // TODO(jmesserly): validate the library. See issue #135.
2539 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName'; 2571 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName';
2540 2572
2541 bool _isJsPeerInterface(DartObjectImpl value) => 2573 bool _isJsPeerInterface(DartObjectImpl value) =>
2542 value.type.name == 'JsPeerInterface'; 2574 value.type.name == 'JsPeerInterface';
2543 2575
2544 // TODO(jacobr): we would like to do something like the following 2576 // TODO(jacobr): we would like to do something like the following
2545 // but we don't have summary support yet. 2577 // but we don't have summary support yet.
2546 // bool _supportJsExtensionMethod(AnnotatedNode node) => 2578 // bool _supportJsExtensionMethod(AnnotatedNode node) =>
2547 // _getAnnotation(node, "SupportJsExtensionMethod") != null; 2579 // _getAnnotation(node, "SupportJsExtensionMethod") != null;
OLDNEW
« no previous file with comments | « lib/runtime/dart_runtime.js ('k') | lib/src/utils.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698