manually merge static-length
diff --git a/lib/src/codegen/js_codegen.dart b/lib/src/codegen/js_codegen.dart index 98631ae..65c8fe4 100644 --- a/lib/src/codegen/js_codegen.dart +++ b/lib/src/codegen/js_codegen.dart
@@ -87,6 +87,7 @@ final _moduleItems = <JS.Statement>[]; final _temps = new HashMap<Element, JS.TemporaryId>(); final _qualifiedIds = new List<Tuple2<Element, JS.MaybeQualifiedId>>(); + final _topLevelExtensionNames = new Set<String>(); /// The name for the library's exports inside itself. /// `exports` was chosen as the most similar to ES module patterns. @@ -170,6 +171,10 @@ // Flush any unwritten fields/properties. _flushLazyFields(_moduleItems); _flushLibraryProperties(_moduleItems); + if (_topLevelExtensionNames.isNotEmpty) { + _moduleItems.add(_emitExtensionNamesDeclaration( + _topLevelExtensionNames.map(js.string).toList())); + } // Mark all qualified names as qualified or not, depending on if they need // to be loaded lazily or not. @@ -210,8 +215,10 @@ // var jsBin = compiler.options.runnerOptions.v8Binary; // String scriptTag = null; // if (library.library.scriptTag != null) scriptTag = '/usr/bin/env $jsBin'; + var jsName = compiler.getModuleName(currentLibrary.source.uri); + items.insert(0, js.statement("console.log('Loading ' + #)", [js.string(jsName)])); return moduleBuilder.build( - compiler.getModuleName(currentLibrary.source.uri), + jsName, _jsModuleValue, _exportsVar, items); @@ -694,6 +701,13 @@ return _statement(body); } + JS.Statement _emitExtensionNamesDeclaration(List<JS.Expression> names) => + js.statement('dart.defineExtensionNames(#)', + [new JS.ArrayInitializer(names.toList(), multiline: true)]); + + JS.Expression _emitExtensionName(String name) => + js.call('dartx.#', _propertyName(name)); + /// 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. @@ -716,8 +730,7 @@ } } if (dartxNames.isNotEmpty) { - body.add(js.statement('dart.defineExtensionNames(#)', - [new JS.ArrayInitializer(dartxNames, multiline: true)])); + body.add(_emitExtensionNamesDeclaration(dartxNames)); } } @@ -1515,7 +1528,7 @@ jsParams = params; } JS.Expression gen = new JS.Fun(jsParams, _visit(body), isGenerator: true); - if (JS.This.foundIn(gen)) { + if (JS.This.foundIn(gen) && options.arrowFnBindThisWorkaround) { gen = js.call('#.bind(this)', gen); } _asyncStarController = savedController; @@ -3424,8 +3437,14 @@ bool allowExtensions: true}) { // Static members skip the rename steps, except for Function properties. if (isStatic) { - if (name == 'length' || name == 'name') { - return js.call('dartx.#', _propertyName(name)); + if (options.closure) { + // Avoid colliding with Function properties, which might be desirable + // in general but is critical to work around a Closure ES6->ES5 bug + // (https://github.com/google/closure-compiler/issues/1460). + if (invalidStaticFieldName(name, closureCompiler: true)) { + _topLevelExtensionNames.add(name); + return _emitExtensionName(name); + } } return _propertyName(name); } @@ -3455,7 +3474,7 @@ if (allowExtensions && _extensionTypes.contains(baseType.element) && !_isObjectProperty(name)) { - return js.call('dartx.#', _propertyName(name)); + return _emitExtensionName(name); } return _propertyName(name);
diff --git a/lib/src/codegen/js_names.dart b/lib/src/codegen/js_names.dart index a07b1f7..19310da 100644 --- a/lib/src/codegen/js_names.dart +++ b/lib/src/codegen/js_names.dart
@@ -293,12 +293,20 @@ /// Returns true for invalid static field names in strict mode. /// In particular, "caller" "callee" and "arguments" cannot be used. -bool invalidStaticFieldName(String name) { +/// +/// [closureCompiler] marks some names as invalid for the purpose of ES6->ES5 +/// lowering with the Closure Compiler. +bool invalidStaticFieldName(String name, {bool closureCompiler : false}) { switch (name) { case "arguments": case "caller": case "callee": return true; + // Workarounds for Closure: + // (see https://github.com/google/closure-compiler/issues/1460) + case "name": + case "length": + return closureCompiler; } return false; }