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

Unified 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, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/runtime/dart_runtime.js ('k') | lib/src/utils.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/src/codegen/js_codegen.dart
diff --git a/lib/src/codegen/js_codegen.dart b/lib/src/codegen/js_codegen.dart
index 6c1ba46e5897bfc3447955762756f777dbff9bb3..890261396987604c44dafa47bc00c62b42a0d9f0 100644
--- a/lib/src/codegen/js_codegen.dart
+++ b/lib/src/codegen/js_codegen.dart
@@ -573,32 +573,64 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
jsMethods.add(_emitImplicitConstructor(node, name, fields));
}
- for (var member in node.members) {
- if (member is ConstructorDeclaration) {
- jsMethods.add(_emitConstructor(member, name, fields, isObject));
- } else if (member is MethodDeclaration) {
- jsMethods.add(_emitMethodDeclaration(type, member));
+ bool hasJsPeer = getAnnotationValue(node, _isJsPeerInterface) != null;
+
+ bool hasIterator = false;
+ for (var m in node.members) {
+ if (m is ConstructorDeclaration) {
+ jsMethods.add(_emitConstructor(m, name, fields, isObject));
+ } else if (m is MethodDeclaration) {
+ jsMethods.add(_emitMethodDeclaration(type, m));
+
+ if (!hasJsPeer && m.isGetter && m.name.name == 'iterator') {
+ hasIterator = true;
+ 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
+ }
}
}
- // Support for adapting dart:core Iterator/Iterable to ES6 versions.
- // This lets them use for-of loops transparently.
- // https://github.com/lukehoban/es6features#iterators--forof
- if (element.library.isDartCore && element.name == 'Iterable') {
- JS.Fun body = js.call('''function() {
- var iterator = this.iterator;
- return {
- next() {
- var done = iterator.moveNext();
- return { done: done, current: done ? void 0 : iterator.current };
- }
- };
- }''');
- jsMethods.add(new JS.Method(js.call('$_SYMBOL.iterator'), body));
+ // If the type doesn't have an `iterator`, but claims to implement Iterable,
+ // we inject the adaptor method here, as it's less code size to put the
+ // helper on a parent class. This pattern is common in the core libraries
+ // (e.g. IterableMixin<E> and IterableBase<E>).
+ //
+ // (We could do this same optimization for any interface with an `iterator`
+ // method, but that's more expensive to check for, so it doesn't seem worth
+ // it. The above case for an explicit `iterator` method will catch those.)
+ if (!hasJsPeer && !hasIterator && _implementsIterable(type)) {
+ jsMethods.add(_emitIterable(type));
}
+
return jsMethods.where((m) => m != null).toList(growable: false);
}
+ bool _implementsIterable(InterfaceType t) =>
+ t.interfaces.any((i) => i.element.type == types.iterableType);
+
+ /// Support for adapting dart:core Iterable to ES6 versions.
+ ///
+ /// This lets them use for-of loops transparently:
+ /// <https://github.com/lukehoban/es6features#iterators--forof>
+ ///
+ /// This will return `null` if the adapter was already added on a super type,
+ /// otherwise it returns the adapter code.
+ // TODO(jmesserly): should we adapt `Iterator` too?
+ JS.Method _emitIterable(InterfaceType t) {
+ // If a parent had an `iterator` (concrete or abstract) or implements
+ // Iterable, we know the adapter is already there, so we can skip it as a
+ // simple code size optimization.
+ var parent = t.lookUpGetterInSuperclass('iterator', t.element.library);
+ if (parent != null) return null;
+ parent = findSupertype(t, _implementsIterable);
+ if (parent != null) return null;
+
+ // Otherwise, emit the adapter method, which wraps the Dart iterator in
+ // an ES6 iterator.
+ return new JS.Method(js.call('$_SYMBOL.iterator'), js.call(
+ 'function() { return new dart.JsIterator(this.#); }',
+ [_emitMemberName('iterator', type: t)]));
+ }
+
/// Emit class members that need to come after the class declaration, such
/// as static fields. See [_emitClassMethods] for things that are emitted
/// inside the ES6 `class { ... }` node.
« 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