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

Unified Diff: lib/src/codegen/js_codegen.dart

Issue 1530563003: Generate all runtime files from dart. (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years 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/typed_data.js ('k') | lib/src/codegen/js_interop.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 0ff3baadbffb8904081d3144b30bb3d788b64e54..ffd51b990e2be43035873b6a9fa0a90638c22925 100644
--- a/lib/src/codegen/js_codegen.dart
+++ b/lib/src/codegen/js_codegen.dart
@@ -94,6 +94,9 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
final _dartxVar = new JS.Identifier('dartx');
final _exportsVar = new JS.TemporaryId('exports');
final _runtimeLibVar = new JS.Identifier('dart');
+ final _utilsLibVar = new JS.TemporaryId('utils');
+ final _classesLibVar = new JS.TemporaryId('classes');
+ final _rttiLibVar = new JS.TemporaryId('rtti');
final _namedArgTemp = new JS.TemporaryId('opts');
final TypeProvider _types;
@@ -108,7 +111,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
/// The default value of the module object. See [visitLibraryDirective].
String _jsModuleValue;
- bool _isDartUtils;
+ bool _isDartRuntime;
Map<String, DartType> _objectMembers;
@@ -123,10 +126,24 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
var src = context.sourceFactory.forUri('dart:_interceptors');
var interceptors = context.computeLibraryElement(src);
_jsArray = interceptors.getType('JSArray');
- _isDartUtils = currentLibrary.source.uri.toString() == 'dart:_utils';
+
+ _isDartRuntime = _runtimeLibUris.contains(_getLibUri(currentLibrary));
_objectMembers = getObjectMemberMap(types);
}
+ String _getLibUri(LibraryElement lib) => lib.source.uri.toString();
+
+ static final _runtimeLibUris = new Set<String>.from([
+ 'dart:_utils',
+ 'dart:_runtime',
+ 'dart:_operations',
+ 'dart:_errors',
+ 'dart:_classes',
+ 'dart:_generators',
+ 'dart:_operations',
+ 'dart:_types',
+ 'dart:_rtti'
+ ]);
TypeProvider get types => rules.provider;
@@ -196,39 +213,51 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
// TODO(jmesserly): it would be great to run the renamer on the body,
// then figure out if we really need each of these parameters.
// See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34
- var params = [_exportsVar, _runtimeLibVar];
- var processImport =
- (LibraryElement library, JS.TemporaryId temp, List list) {
- params.add(temp);
- list.add(js.string(compiler.getModuleName(library.source.uri), "'"));
- };
+ var params = [_exportsVar];
+ var lazyParams = [];
- var needsDartRuntime = !_isDartUtils;
+ var libUri = _getLibUri(currentLibrary);
var imports = <JS.Expression>[];
+ var lazyImports = <JS.Expression>[];
var moduleStatements = <JS.Statement>[];
- if (needsDartRuntime) {
- imports.add(js.string('dart/_runtime'));
+
+ addImport(String name, JS.Expression libVar, {bool eager: true}) {
+ (eager ? imports : lazyImports).add(js.string(name, "'"));
+ (eager ? params : lazyParams).add(libVar);
+ }
+
+ if (!_isDartRuntime) {
+ addImport('dart/_runtime', _runtimeLibVar);
var dartxImport =
js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]);
moduleStatements.add(dartxImport);
+ } else {
+ if (libUri == 'dart:_generators') {
+ addImport('dart/_classes', _classesLibVar);
+ }
}
moduleStatements.addAll(_moduleItems);
- _imports.forEach((library, temp) {
- if (_loader.libraryIsLoaded(library)) {
- processImport(library, temp, imports);
- }
- });
+ bool shouldImportEagerly(lib) {
+ var otherLibUri = _getLibUri(lib);
+ if (otherLibUri == 'dart:_utils') return true;
+ if (libUri == 'dart:_types' && otherLibUri == 'dart:_rtti') return true;
+ if (libUri == 'dart:_runtime') return otherLibUri != 'dart:_js_helper';
+ return !_isDartRuntime && _loader.libraryIsLoaded(lib);
+ }
- var lazyImports = <JS.Expression>[];
- _imports.forEach((library, temp) {
- if (!_loader.libraryIsLoaded(library)) {
- processImport(library, temp, lazyImports);
- }
+ var importsEagerness = new Map<LibraryElement, bool>.fromIterable(
+ _imports.keys, value: shouldImportEagerly);
+
+ _imports.forEach((LibraryElement lib, JS.TemporaryId temp) {
+ bool eager = importsEagerness[lib];
+ addImport(compiler.getModuleName(lib.source.uri), temp, eager: eager);
});
+ params.addAll(lazyParams);
+
var module =
js.call("function(#) { 'use strict'; #; }", [params, moduleStatements]);
@@ -264,9 +293,12 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
void visitLibraryDirective(LibraryDirective node) {
assert(_jsModuleValue == null);
- var jsName = findAnnotation(node.element, isJSAnnotation);
- _jsModuleValue =
- getConstantField(jsName, 'name', types.stringType)?.toStringValue();
+ _jsModuleValue = _getJsName(node.element);
+ }
+
+ String _getJsName(Element e) {
+ var jsName = findAnnotation(e, isJSAnnotation);
+ return getConstantField(jsName, 'name', types.stringType)?.toStringValue();
}
@override
@@ -294,8 +326,12 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
var hide = node.combinators.firstWhere((c) => c is HideCombinator,
orElse: () => null) as HideCombinator;
if (show != null) {
+ var singleName = _getJsName(node.element);
+ if (singleName != null && show.shownNames.length != 1) {
+ throw new StateError('Cannot set js name on more than one name');
+ }
shownNames.addAll(show.shownNames
- .map((i) => i.name)
+ .map((i) => singleName ?? i.name)
.where((s) => !currentLibNames.containsKey(s))
.map((s) => js.string(s, "'")));
}
@@ -305,7 +341,10 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
args.add(new JS.ArrayInitializer(shownNames));
args.add(new JS.ArrayInitializer(hiddenNames));
}
- _moduleItems.add(js.statement('dart.export_(#);', [args]));
+
+ // When we compile _runtime.js, we need to source export_ from _utils.js:
+ _moduleItems.add(js.statement('#.export(#);',
+ [_isDartRuntime ? _utilsLibVar : _runtimeLibVar, args]));
}
JS.Identifier _initSymbol(JS.Identifier id) {
@@ -579,10 +618,14 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
var genericName = '$name\$';
var typeParams = type.typeParameters.map((p) => p.name);
if (isPublic(name)) _exports.add(genericName);
- return js.statement('const # = dart.generic(function(#) { #; return #; });',
- [genericName, typeParams, body, name]);
+
+ return js.statement('const # = #(function(#) { #; return #; });',
+ [genericName, _dartGeneric, typeParams, body, name]);
}
+ get _dartGeneric =>
+ js.call('#.generic', [_isDartRuntime ? _classesLibVar : _runtimeLibVar]);
+
final _hasDeferredSupertype = new HashSet<ClassElement>();
bool _deferIfNeeded(DartType type, ClassElement current) {
@@ -832,7 +875,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
if (!sigFields.isEmpty || extensions.isNotEmpty) {
var sig = new JS.ObjectInitializer(sigFields);
var classExpr = new JS.Identifier(name);
- body.add(js.statement('dart.setSignature(#, #);', [classExpr, sig]));
+ body.add(js.statement('#(#, #);', [_dartSetSignature, classExpr, sig]));
}
}
@@ -862,6 +905,9 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
return _statement(body);
}
+ get _dartSetSignature =>
+ js.call('#.setSignature', [_isDartRuntime ? _classesLibVar : _runtimeLibVar]);
+
List<ExecutableElement> _extensionsToImplement(ClassElement element) {
var members = <ExecutableElement>[];
if (_extensionTypes.contains(element)) return members;
@@ -1302,15 +1348,14 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
var body = <JS.Statement>[];
_flushLibraryProperties(body);
- var name = node.name.name;
+ var name = _getJsName(node.element) ?? node.name.name;
var fn = _visit(node.functionExpression);
- bool needsTagging = true;
+ bool needsTagging = !_isDartRuntime;
if (currentLibrary.source.isInSystemLibrary &&
_isInlineJSFunction(node.functionExpression)) {
fn = _simplifyPassThroughArrowFunCallBody(fn);
- needsTagging = !_isDartUtils;
}
var id = new JS.Identifier(name);
@@ -1406,16 +1451,18 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
type.optionalParameterTypes.isEmpty &&
type.namedParameterTypes.isEmpty &&
type.normalParameterTypes.every((t) => t.isDynamic)) {
- return js.call('dart.fn(#)', [clos]);
+ return js.call('#(#)', [_dartFn, clos]);
}
if (lazy) {
- return js.call('dart.fn(#, () => #)', [clos, _emitFunctionRTTI(type)]);
+ return js.call('#(#, () => #)', [_dartFn, clos, _emitFunctionRTTI(type)]);
}
- return js.call('dart.fn(#, #)', [clos, _emitFunctionTypeParts(type)]);
+ return js.call('#(#, #)', [_dartFn, clos, _emitFunctionTypeParts(type)]);
}
throw 'Function has non function type: $type';
}
+ get _dartFn => js.call('#.fn', _isDartRuntime ? _rttiLibVar : _runtimeLibVar);
+
@override
JS.Expression visitFunctionExpression(FunctionExpression node) {
var params = _visit(node.parameters) as List<JS.Parameter>;
@@ -1566,7 +1613,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
_loader.declareBeforeUse(element);
- var name = element.name;
+ var name = _getJsName(element) ?? element.name;
// type literal
if (element is ClassElement ||
@@ -1578,7 +1625,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
// library member
if (element.enclosingElement is CompilationUnitElement) {
- return _maybeQualifiedName(element);
+ return _maybeQualifiedName(element, name);
}
// Unqualified class member. This could mean implicit-this, or implicit
@@ -1881,11 +1928,30 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
new JS.Block(_visitList(node.statements) as List<JS.Statement>,
isScope: true);
+ /// Return the type constructor `_foolib.Bar$` given `Bar` from lib `_foolib`.
+ JS.Expression _emitGenericTypeConstructor(Expression typeExpression) {
+ var ref = _visit(typeExpression);
+ if (ref is JS.PropertyAccess) {
+ var name = (ref.selector as JS.LiteralString).valueWithoutQuotes;
+ return new JS.PropertyAccess(
+ ref.receiver, new JS.LiteralString("'$name\$'"));
+ } else if (ref is JS.MaybeQualifiedId) {
+ var name = (ref.name as JS.Identifier).name;
+ return new JS.PropertyAccess(
+ ref.qualifier, new JS.Identifier('$name\$'));
+ } else {
+ throw new ArgumentError('Invalid type ref: $ref (${ref?.runtimeType})');
+ }
+ }
+
@override
visitMethodInvocation(MethodInvocation node) {
if (node.operator != null && node.operator.lexeme == '?.') {
return _emitNullSafe(node);
}
+ if (isGenericTypeConstructorInvocation(node)) {
+ return _emitGenericTypeConstructor(node.argumentList.arguments.single);
+ }
var target = _getTarget(node);
var result = _emitForeignJS(node);
@@ -2211,7 +2277,8 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
var isJSTopLevel = field.isFinal && _isFinalJSDecl(field);
if (isJSTopLevel) eagerInit = true;
- var fieldName = field.name.name;
+ var fieldName = _getJsName(element) ?? field.name.name;
+
if ((field.isConst && eagerInit && element is TopLevelVariableElement) ||
isJSTopLevel) {
// constant fields don't change, so we can generate them as `let`
@@ -2847,7 +2914,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
} else if (_requiresStaticDispatch(target, memberId.name)) {
var type = member.type;
var clos = js.call('dart.#.bind(#)', [name, _visit(target)]);
- return js.call('dart.fn(#, #)', [clos, _emitFunctionTypeParts(type)]);
+ return js.call('#(#, #)', [_dartFn, clos, _emitFunctionTypeParts(type)]);
}
code = 'dart.bind(#, #)';
} else if (_requiresStaticDispatch(target, memberId.name)) {
@@ -3416,8 +3483,13 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
/// declaration) as it doesn't have any meaningful rules enforced.
JS.Identifier _libraryName(LibraryElement library) {
if (library == currentLibrary) return _exportsVar;
- return _imports.putIfAbsent(
- library, () => new JS.TemporaryId(jsLibraryName(library)));
+ return _imports.putIfAbsent(library, () {
+ var name = library.name;
+ if (name == 'dart._utils') return _utilsLibVar;
+ else if (name == 'dart._classes') return _classesLibVar;
+ else if (name == 'dart._rtti') return _rttiLibVar;
+ else return new JS.TemporaryId(jsLibraryName(library));
+ });
}
DartType getStaticType(Expression e) => rules.getStaticType(e);
« no previous file with comments | « lib/runtime/dart/typed_data.js ('k') | lib/src/codegen/js_interop.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698