Index: lib/src/codegen/js_codegen.dart |
diff --git a/lib/src/codegen/js_codegen.dart b/lib/src/codegen/js_codegen.dart |
index 81166e316a183f91531a59a2153e2b305fa155f5..86cd2385d00afcf638c11f96820532f371176ea5 100644 |
--- a/lib/src/codegen/js_codegen.dart |
+++ b/lib/src/codegen/js_codegen.dart |
@@ -30,7 +30,6 @@ const String _jsNamedParameterName = r'opt$'; |
class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
final LibraryInfo libraryInfo; |
final TypeRules rules; |
- final String _libraryName; |
/// The variable for the target of the current `..` cascade expression. |
SimpleIdentifier _cascadeTarget; |
@@ -44,8 +43,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
JSCodegenVisitor(LibraryInfo libraryInfo, TypeRules rules) |
: libraryInfo = libraryInfo, |
- rules = rules, |
- _libraryName = jsLibraryName(libraryInfo.library); |
+ rules = rules; |
Element get currentLibrary => libraryInfo.library; |
@@ -67,18 +65,18 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
// TODO(jmesserly): make these immutable in JS? |
for (var name in _exports) { |
- body.add(js.statement('#.# = #;', [_libraryName, name, name])); |
+ body.add(js.statement('$_EXPORTS.# = #;', [name, name])); |
} |
- var name = _libraryName; |
+ var name = jsLibraryName(libraryInfo.library); |
return new JS.Block([ |
js.statement('var #;', name), |
js.statement(''' |
- (function (#) { |
+ (function ($_EXPORTS) { |
'use strict'; |
#; |
})(# || (# = {})); |
- ''', [name, body, name, name]) |
+ ''', [body, name, name]) |
]); |
} |
@@ -638,7 +636,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
var name = node.name; |
if (e.enclosingElement is CompilationUnitElement && |
(e.library != libraryInfo.library || _needsModuleGetter(e))) { |
- return js.call('#.#', [jsLibraryName(e.library), name]); |
+ return js.call('#.#', [_libraryName(e.library), name]); |
} else if (currentClass != null && _needsImplicitThis(e)) { |
return js.call('this.#', name); |
} |
@@ -668,7 +666,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
JS.Expression result; |
if (lib != currentLibrary && lib != null) { |
- result = js.call('#.#', [jsLibraryName(lib), name]); |
+ result = js.call('#.#', [_libraryName(lib), name]); |
} else { |
result = new JS.VariableUse(name); |
} |
@@ -958,7 +956,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
} |
void _flushLazyFields(List<JS.Statement> body) { |
- var code = _emitLazyFields(_libraryName, _lazyFields); |
+ var code = _emitLazyFields(_EXPORTS, _lazyFields); |
if (code != null) body.add(code); |
_lazyFields.clear(); |
} |
@@ -988,8 +986,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
void _flushLibraryProperties(List<JS.Statement> body) { |
if (_properties.isEmpty) return; |
- body.add(js.statement('dart.copyProperties(#, { # });', [ |
- _libraryName, |
+ body.add(js.statement('dart.copyProperties($_EXPORTS, { # });', [ |
_properties.map(_emitTopLevelProperty) |
])); |
_properties.clear(); |
@@ -1630,6 +1627,14 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
FunctionBody _functionBody(node) => |
node is FunctionDeclaration ? node.functionExpression.body : node.body; |
+ /// Choose a canonical name from the library element. |
+ /// This never uses the library's name (the identifier in the `library` |
+ /// declaration) as it doesn't have any meaningful rules enforced. |
+ String _libraryName(LibraryElement library) { |
+ if (library == libraryInfo.library) return _EXPORTS; |
+ return jsLibraryName(library); |
+ } |
+ |
String _maybeBindThis(node) { |
if (currentClass == null) return ''; |
var visitor = _BindThisVisitor._instance; |
@@ -1638,6 +1643,12 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
return visitor._bindThis ? '.bind(this)' : ''; |
} |
+ /// The name for the library's exports inside itself. |
+ /// This much be a constant because we interpolate it into template strings, |
+ /// and otherwise it would break caching for them. |
+ /// `exports` was chosen as the most similar to ES module patterns. |
+ static const String _EXPORTS = 'exports'; |
+ |
static bool _needsImplicitThis(Element e) => |
e is PropertyAccessorElement && !e.variable.isStatic || |
e is ClassMemberElement && !e.isStatic && e is! ConstructorElement; |