mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 08:24:39 +00:00
fix #27644, allow "dart" and "dartx" to be renamed if needed
R=vsm@google.com Review URL: https://codereview.chromium.org/2435223002 .
This commit is contained in:
parent
982f9f46ed
commit
ce76fc1fe5
|
@ -74,7 +74,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
final _moduleItems = <JS.ModuleItem>[];
|
||||
|
||||
/// Table of named and possibly hoisted types.
|
||||
final _typeTable = new TypeTable();
|
||||
TypeTable _typeTable;
|
||||
|
||||
/// The global extension type table.
|
||||
final ExtensionTypeSet _extensionTypes;
|
||||
|
@ -97,8 +97,8 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
final _initializingFormalTemps =
|
||||
new HashMap<ParameterElement, JS.TemporaryId>();
|
||||
|
||||
final _dartxVar = new JS.Identifier('dartx');
|
||||
final _runtimeLibVar = new JS.Identifier('dart');
|
||||
JS.Identifier _extensionSymbolsModule;
|
||||
JS.Identifier _runtimeModule;
|
||||
final namedArgumentTemp = new JS.TemporaryId('opts');
|
||||
|
||||
final _hasDeferredSupertype = new HashSet<ClassElement>();
|
||||
|
@ -231,6 +231,18 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
// Transform the AST to make coercions explicit.
|
||||
compilationUnits = CoercionReifier.reify(compilationUnits);
|
||||
|
||||
if (compilationUnits.any((u) => _isDartRuntime(u.element.library))) {
|
||||
// Don't allow these to be renamed when we're building the SDK.
|
||||
// There is JS code in dart:* that depends on their names.
|
||||
_runtimeModule = new JS.Identifier('dart');
|
||||
_extensionSymbolsModule = new JS.Identifier('dartx');
|
||||
} else {
|
||||
// Otherwise allow these to be renamed so users can write them.
|
||||
_runtimeModule = new JS.TemporaryId('dart');
|
||||
_extensionSymbolsModule = new JS.TemporaryId('dartx');
|
||||
}
|
||||
_typeTable = new TypeTable(_runtimeModule);
|
||||
|
||||
// Initialize our library variables.
|
||||
var items = <JS.ModuleItem>[];
|
||||
for (var unit in compilationUnits) {
|
||||
|
@ -238,7 +250,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
if (unit.element != library.definingCompilationUnit) continue;
|
||||
|
||||
var libraryTemp = _isDartRuntime(library)
|
||||
? _runtimeLibVar
|
||||
? _runtimeModule
|
||||
: new JS.TemporaryId(jsLibraryName(_libraryRoot, library));
|
||||
_libraries[library] = libraryTemp;
|
||||
items.add(new JS.ExportDeclaration(
|
||||
|
@ -247,8 +259,8 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
// dart:_runtime has a magic module that holds extension method symbols.
|
||||
// TODO(jmesserly): find a cleaner design for this.
|
||||
if (_isDartRuntime(library)) {
|
||||
items.add(new JS.ExportDeclaration(
|
||||
js.call('const # = Object.create(null)', [_dartxVar])));
|
||||
items.add(new JS.ExportDeclaration(js
|
||||
.call('const # = Object.create(null)', [_extensionSymbolsModule])));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,7 +344,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
var jsName = _getJSName(e);
|
||||
if (jsName == null) return null;
|
||||
var fullName = ['global']..addAll(jsName);
|
||||
JS.Expression access = _runtimeLibVar;
|
||||
JS.Expression access = _runtimeModule;
|
||||
for (var part in fullName) {
|
||||
access = new JS.PropertyAccess(access, js.string(part));
|
||||
}
|
||||
|
@ -391,8 +403,8 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
var imports =
|
||||
libraries.map((l) => new JS.NameSpecifier(_imports[l])).toList();
|
||||
if (module == coreModuleName) {
|
||||
imports.add(new JS.NameSpecifier(_runtimeLibVar));
|
||||
imports.add(new JS.NameSpecifier(_dartxVar));
|
||||
imports.add(new JS.NameSpecifier(_runtimeModule));
|
||||
imports.add(new JS.NameSpecifier(_extensionSymbolsModule));
|
||||
}
|
||||
items.add(new JS.ImportDeclaration(
|
||||
namedImports: imports, from: js.string(module, "'")));
|
||||
|
@ -508,8 +520,8 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
} else {
|
||||
// top-level fields, getters, setters need to copy the property
|
||||
// descriptor.
|
||||
_moduleItems.add(js.statement('dart.export(#, #, #);',
|
||||
[libraryName, name.receiver, name.selector]));
|
||||
_moduleItems.add(_callHelperStatement(
|
||||
'export(#, #, #);', [libraryName, name.receiver, name.selector]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -553,7 +565,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
// Make sure to check when converting to int.
|
||||
if (from != types.intType && to == types.intType) {
|
||||
// TODO(jmesserly): fuse this with notNull check.
|
||||
return js.call('dart.asInt(#)', jsFrom);
|
||||
return _callHelper('asInt(#)', jsFrom);
|
||||
}
|
||||
|
||||
// A no-op in JavaScript.
|
||||
|
@ -607,7 +619,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
FunctionTypeAliasElement element = node.element;
|
||||
|
||||
JS.Expression body = annotate(
|
||||
js.call('dart.typedef(#, () => #)', [
|
||||
_callHelper('typedef(#, () => #)', [
|
||||
js.string(element.name, "'"),
|
||||
_emitType(element.type, nameType: false, lowerTypedef: true)
|
||||
]),
|
||||
|
@ -629,7 +641,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
// TODO(jmesserly): if the type fails to resolve, should we generate code
|
||||
// that throws instead?
|
||||
assert(options.unsafeForceCompile || options.replCompile);
|
||||
return js.call('dart.dynamic');
|
||||
return _callHelper('dynamic');
|
||||
}
|
||||
return _emitType(node.type);
|
||||
}
|
||||
|
@ -794,7 +806,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
classExpr.name, _emitCallableClassConstructor(unnamedCtor));
|
||||
|
||||
// Name the constructor function the same as the class.
|
||||
return js.call('dart.callableClass(#, #)', [ctor, classExpr]);
|
||||
return _callHelper('callableClass(#, #)', [ctor, classExpr]);
|
||||
}
|
||||
|
||||
/// Emits a constructor that ensures instances of this class are callable as
|
||||
|
@ -825,21 +837,21 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
body.add(js.statement(
|
||||
'#.is = function is_Object(o) {'
|
||||
' if (o instanceof this) return true;'
|
||||
' return dart.is(o, this);'
|
||||
' return #.is(o, this);'
|
||||
'}',
|
||||
className));
|
||||
[className, _runtimeModule]));
|
||||
body.add(js.statement(
|
||||
'#.as = function as_Object(o) {'
|
||||
' if (o == null || o instanceof this) return o;'
|
||||
' return dart.as(o, this);'
|
||||
' return #.as(o, this);'
|
||||
'}',
|
||||
className));
|
||||
[className, _runtimeModule]));
|
||||
body.add(js.statement(
|
||||
'#._check = function check_Object(o) {'
|
||||
' if (o == null || o instanceof this) return o;'
|
||||
' return dart.check(o, this);'
|
||||
' return #.check(o, this);'
|
||||
'}',
|
||||
className));
|
||||
[className, _runtimeModule]));
|
||||
return;
|
||||
}
|
||||
if (classElem == stringClass) {
|
||||
|
@ -849,15 +861,15 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
body.add(js.statement(
|
||||
'#.as = function as_String(o) {'
|
||||
' if (typeof o == "string" || o == null) return o;'
|
||||
' return dart.as(o, #);'
|
||||
' return #.as(o, #);'
|
||||
'}',
|
||||
[className, className]));
|
||||
[className, _runtimeModule, className]));
|
||||
body.add(js.statement(
|
||||
'#._check = function check_String(o) {'
|
||||
' if (typeof o == "string" || o == null) return o;'
|
||||
' return dart.check(o, #);'
|
||||
' return #.check(o, #);'
|
||||
'}',
|
||||
[className, className]));
|
||||
[className, _runtimeModule, className]));
|
||||
return;
|
||||
}
|
||||
if (classElem == intClass) {
|
||||
|
@ -870,16 +882,16 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
'#.as = function as_int(o) {'
|
||||
' if ((typeof o == "number" && Math.floor(o) == o) || o == null)'
|
||||
' return o;'
|
||||
' return dart.as(o, #);'
|
||||
' return #.as(o, #);'
|
||||
'}',
|
||||
[className, className]));
|
||||
[className, _runtimeModule, className]));
|
||||
body.add(js.statement(
|
||||
'#._check = function check_int(o) {'
|
||||
' if ((typeof o == "number" && Math.floor(o) == o) || o == null)'
|
||||
' return o;'
|
||||
' return dart.check(o, #);'
|
||||
' return #.check(o, #);'
|
||||
'}',
|
||||
[className, className]));
|
||||
[className, _runtimeModule, className]));
|
||||
return;
|
||||
}
|
||||
if (classElem == nullClass) {
|
||||
|
@ -888,15 +900,15 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
body.add(js.statement(
|
||||
'#.as = function as_Null(o) {'
|
||||
' if (o == null) return o;'
|
||||
' return dart.as(o, #);'
|
||||
' return #.as(o, #);'
|
||||
'}',
|
||||
[className, className]));
|
||||
[className, _runtimeModule, className]));
|
||||
body.add(js.statement(
|
||||
'#._check = function check_Null(o) {'
|
||||
' if (o == null) return o;'
|
||||
' return dart.check(o, #);'
|
||||
' return #.check(o, #);'
|
||||
'}',
|
||||
[className, className]));
|
||||
[className, _runtimeModule, className]));
|
||||
return;
|
||||
}
|
||||
if (classElem == numClass) {
|
||||
|
@ -906,15 +918,15 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
body.add(js.statement(
|
||||
'#.as = function as_num(o) {'
|
||||
' if (typeof o == "number" || o == null) return o;'
|
||||
' return dart.as(o, #);'
|
||||
' return #.as(o, #);'
|
||||
'}',
|
||||
[className, className]));
|
||||
[className, _runtimeModule, className]));
|
||||
body.add(js.statement(
|
||||
'#._check = function check_num(o) {'
|
||||
' if (typeof o == "number" || o == null) return o;'
|
||||
' return dart.check(o, #);'
|
||||
' return #.check(o, #);'
|
||||
'}',
|
||||
[className, className]));
|
||||
[className, _runtimeModule, className]));
|
||||
return;
|
||||
}
|
||||
if (classElem == boolClass) {
|
||||
|
@ -924,15 +936,15 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
body.add(js.statement(
|
||||
'#.as = function as_bool(o) {'
|
||||
' if (o === true || o === false || o == null) return o;'
|
||||
' return dart.as(o, #);'
|
||||
' return #.as(o, #);'
|
||||
'}',
|
||||
[className, className]));
|
||||
[className, _runtimeModule, className]));
|
||||
body.add(js.statement(
|
||||
'#._check = function check_bool(o) {'
|
||||
' if (o === true || o === false || o == null) return o;'
|
||||
' return dart.check(o, #);'
|
||||
' return #.check(o, #);'
|
||||
'}',
|
||||
[className, className]));
|
||||
[className, _runtimeModule, className]));
|
||||
return;
|
||||
}
|
||||
// TODO(sra): Add special cases for hot tests like `x is html.Element`.
|
||||
|
@ -945,7 +957,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
// Place non-instanceof version of checks on Interceptor. All
|
||||
// interceptor classes will inherit the methods via ES6 class static
|
||||
// inheritance.
|
||||
body.add(js.statement('dart.addTypeTests(#);', className));
|
||||
body.add(_callHelperStatement('addTypeTests(#);', className));
|
||||
|
||||
// TODO(sra): We could place on the extension type a pointer to the
|
||||
// peer constructor and use that for the `instanceof` check, e.g.
|
||||
|
@ -983,9 +995,9 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
if (thisIsSimple == superIsSimple) return;
|
||||
|
||||
if (thisIsSimple) {
|
||||
body.add(js.statement('dart.addSimpleTypeTests(#);', className));
|
||||
body.add(_callHelperStatement('addSimpleTypeTests(#);', className));
|
||||
} else {
|
||||
body.add(js.statement('dart.addTypeTests(#);', className));
|
||||
body.add(_callHelperStatement('addTypeTests(#);', className));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1103,8 +1115,8 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
|
||||
// Create static fields for each enum value
|
||||
for (var i = 0; i < fields.length; ++i) {
|
||||
result.add(js.statement('#.# = dart.const(new #(#));',
|
||||
[id, fields[i].name, id, js.number(i)]));
|
||||
result.add(js.statement('#.# = #.const(new #(#));',
|
||||
[id, fields[i].name, _runtimeModule, id, js.number(i)]));
|
||||
}
|
||||
|
||||
// Create static values list
|
||||
|
@ -1114,8 +1126,8 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
// dart.constList helper internally depends on _interceptors.JSArray.
|
||||
_declareBeforeUse(_jsArray);
|
||||
|
||||
result.add(js.statement(
|
||||
'#.values = dart.constList(#, #);', [id, values, _emitType(type)]));
|
||||
result.add(js.statement('#.values = #.constList(#, #);',
|
||||
[id, _runtimeModule, values, _emitType(type)]));
|
||||
|
||||
return _statement(result);
|
||||
}
|
||||
|
@ -1124,7 +1136,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
JS.Statement _defineClassTypeArguments(TypeDefiningElement element,
|
||||
List<TypeParameterElement> formals, JS.Statement body) {
|
||||
assert(formals.isNotEmpty);
|
||||
var genericCall = js.call('dart.generic((#) => { #; #; return #; })', [
|
||||
var genericCall = _callHelper('generic((#) => { #; #; return #; })', [
|
||||
_emitTypeFormals(formals),
|
||||
_typeTable.discharge(formals),
|
||||
body,
|
||||
|
@ -1132,7 +1144,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
]);
|
||||
if (element.library.isDartAsync &&
|
||||
(element.name == "Future" || element.name == "_Future")) {
|
||||
genericCall = js.call('dart.flattenFutures(#)', [genericCall]);
|
||||
genericCall = _callHelper('flattenFutures(#)', [genericCall]);
|
||||
}
|
||||
var genericDef = js.statement(
|
||||
'# = #;', [_emitTopLevelName(element, suffix: r'$'), genericCall]);
|
||||
|
@ -1190,7 +1202,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
var mixins =
|
||||
type.mixins.map((t) => _emitType(t, nameType: false)).toList();
|
||||
mixins.insert(0, heritage);
|
||||
heritage = js.call('dart.mixin(#)', [mixins]);
|
||||
heritage = _callHelper('mixin(#)', [mixins]);
|
||||
}
|
||||
|
||||
_loader.finishTopLevel(element);
|
||||
|
@ -1410,8 +1422,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
JS.Expression positionalArgs;
|
||||
|
||||
if (method.type.namedParameterTypes.isNotEmpty) {
|
||||
addProperty(
|
||||
'namedArguments', js.call('dart.extractNamedArgs(#)', [args]));
|
||||
addProperty('namedArguments', _callHelper('extractNamedArgs(#)', [args]));
|
||||
}
|
||||
|
||||
if (method is MethodElement) {
|
||||
|
@ -1433,8 +1444,8 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
}
|
||||
}
|
||||
|
||||
var fnBody =
|
||||
js.call('this.noSuchMethod(new dart.InvocationImpl(#, #, #))', [
|
||||
var fnBody = js.call('this.noSuchMethod(new #.InvocationImpl(#, #, #))', [
|
||||
_runtimeModule,
|
||||
_declareMemberName(method),
|
||||
positionalArgs,
|
||||
new JS.ObjectInitializer(invocationProps)
|
||||
|
@ -1552,8 +1563,8 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
// an ES6 iterator.
|
||||
return new JS.Method(
|
||||
js.call('Symbol.iterator'),
|
||||
js.call('function() { return new dart.JsIterator(this.#); }',
|
||||
[_emitMemberName('iterator', type: t)]) as JS.Fun);
|
||||
js.call('function() { return new #.JsIterator(this.#); }',
|
||||
[_runtimeModule, _emitMemberName('iterator', type: t)]) as JS.Fun);
|
||||
}
|
||||
|
||||
JS.Expression _instantiateAnnotation(Annotation node) {
|
||||
|
@ -1590,8 +1601,11 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
void _registerExtensionType(
|
||||
ClassElement classElem, String jsPeerName, List<JS.Statement> body) {
|
||||
if (jsPeerName != null) {
|
||||
body.add(js.statement('dart.registerExtension(dart.global.#, #);',
|
||||
[_propertyName(jsPeerName), _emitTopLevelName(classElem)]));
|
||||
body.add(_callHelperStatement('registerExtension(#.global.#, #);', [
|
||||
_runtimeModule,
|
||||
_propertyName(jsPeerName),
|
||||
_emitTopLevelName(classElem)
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1600,23 +1614,23 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
if (jsPeerNames.isNotEmpty && classElem.typeParameters.isNotEmpty) {
|
||||
for (var peer in jsPeerNames) {
|
||||
// TODO(jmesserly): we should just extend Array in the first place
|
||||
var newBaseClass = js.call('dart.global.#', [peer]);
|
||||
body.add(js.statement(
|
||||
'dart.setExtensionBaseClass(#, #);', [className, newBaseClass]));
|
||||
var newBaseClass = _callHelper('global.#', [peer]);
|
||||
body.add(_callHelperStatement(
|
||||
'setExtensionBaseClass(#, #);', [className, newBaseClass]));
|
||||
}
|
||||
} else if (_hasDeferredSupertype.contains(classElem)) {
|
||||
var newBaseClass = _emitType(classElem.type.superclass,
|
||||
nameType: false, subClass: classElem, className: className);
|
||||
body.add(
|
||||
js.statement('dart.setBaseClass(#, #);', [className, newBaseClass]));
|
||||
body.add(_callHelperStatement(
|
||||
'setBaseClass(#, #);', [className, newBaseClass]));
|
||||
}
|
||||
}
|
||||
|
||||
void _defineNamedConstructors(List<ConstructorDeclaration> ctors,
|
||||
List<JS.Statement> body, JS.Expression className, bool isCallable) {
|
||||
var code = isCallable
|
||||
? 'dart.defineNamedConstructorCallable(#, #, #);'
|
||||
: 'dart.defineNamedConstructor(#, #)';
|
||||
? 'defineNamedConstructorCallable(#, #, #);'
|
||||
: 'defineNamedConstructor(#, #)';
|
||||
|
||||
for (ConstructorDeclaration member in ctors) {
|
||||
if (member.name != null && member.factoryKeyword == null) {
|
||||
|
@ -1625,7 +1639,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
args.add(_emitCallableClassConstructor(member.element));
|
||||
}
|
||||
|
||||
body.add(js.statement(code, args));
|
||||
body.add(_callHelperStatement(code, args));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1658,8 +1672,9 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
List<JS.Statement> body) {
|
||||
// Metadata
|
||||
if (options.emitMetadata && metadata.isNotEmpty) {
|
||||
body.add(js.statement('#[dart.metadata] = () => #;', [
|
||||
body.add(js.statement('#[#.metadata] = () => #;', [
|
||||
className,
|
||||
_runtimeModule,
|
||||
new JS.ArrayInitializer(
|
||||
new List<JS.Expression>.from(metadata.map(_instantiateAnnotation)))
|
||||
]));
|
||||
|
@ -1677,7 +1692,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
for (var e in extensions) {
|
||||
methodNames.add(_declareMemberName(e, useExtension: false));
|
||||
}
|
||||
body.add(js.statement('dart.defineExtensionMembers(#, #);', [
|
||||
body.add(_callHelperStatement('defineExtensionMembers(#, #);', [
|
||||
className,
|
||||
new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4)
|
||||
]));
|
||||
|
@ -1694,8 +1709,9 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
JS.Expression className,
|
||||
List<JS.Statement> body) {
|
||||
if (classElem.interfaces.isNotEmpty) {
|
||||
body.add(js.statement('#[dart.implements] = () => #;', [
|
||||
body.add(js.statement('#[#.implements] = () => #;', [
|
||||
className,
|
||||
_runtimeModule,
|
||||
new JS.ArrayInitializer(
|
||||
new List<JS.Expression>.from(classElem.interfaces.map(_emitType)))
|
||||
]));
|
||||
|
@ -1818,12 +1834,12 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
}
|
||||
if (!sigFields.isEmpty || extensions.isNotEmpty) {
|
||||
var sig = new JS.ObjectInitializer(sigFields);
|
||||
body.add(js.statement('dart.setSignature(#, #);', [className, sig]));
|
||||
body.add(_callHelperStatement('setSignature(#, #);', [className, sig]));
|
||||
}
|
||||
// Add static property dart._runtimeType to Object.
|
||||
// All other Dart classes will (statically) inherit this property.
|
||||
if (classElem == objectClass) {
|
||||
body.add(js.statement('dart.tagComputed(#, () => #.#);',
|
||||
body.add(_callHelperStatement('tagComputed(#, () => #.#);',
|
||||
[className, emitLibraryName(dartCoreLibrary), 'Type']));
|
||||
}
|
||||
}
|
||||
|
@ -1852,7 +1868,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
}
|
||||
}
|
||||
if (dartxNames.isNotEmpty) {
|
||||
body.add(js.statement('dart.defineExtensionNames(#)',
|
||||
body.add(_callHelperStatement('defineExtensionNames(#)',
|
||||
[new JS.ArrayInitializer(dartxNames, multiline: true)]));
|
||||
}
|
||||
}
|
||||
|
@ -2332,7 +2348,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
props.add(_loader.emitDeclaration(
|
||||
setter, (node) => _emitTopLevelProperty(node)));
|
||||
}
|
||||
return js.statement('dart.copyProperties(#, { # });',
|
||||
return _callHelperStatement('copyProperties(#, { # });',
|
||||
[emitLibraryName(currentLibrary), props]);
|
||||
}
|
||||
if (node.isSetter) {
|
||||
|
@ -2343,7 +2359,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
props.add(_loader.emitDeclaration(
|
||||
getter, (node) => _emitTopLevelProperty(node)));
|
||||
}
|
||||
return js.statement('dart.copyProperties(#, { # });',
|
||||
return _callHelperStatement('copyProperties(#, { # });',
|
||||
[emitLibraryName(currentLibrary), props]);
|
||||
}
|
||||
|
||||
|
@ -2442,9 +2458,9 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
var lazy = topLevel && !_typeIsLoaded(type);
|
||||
var typeRep = _emitFunctionType(type, definite: true);
|
||||
if (lazy) {
|
||||
return js.call('dart.lazyFn(#, () => #)', [fn, typeRep]);
|
||||
return _callHelper('lazyFn(#, () => #)', [fn, typeRep]);
|
||||
} else {
|
||||
return js.call('dart.fn(#, #)', [fn, typeRep]);
|
||||
return _callHelper('fn(#, #)', [fn, typeRep]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2596,7 +2612,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
}
|
||||
|
||||
var T = _emitType(returnType);
|
||||
return js.call('dart.#(#)', [
|
||||
return _callHelper('#(#)', [
|
||||
kind,
|
||||
[gen, T]..addAll(visitFormalParameterList(parameters, destructure: false))
|
||||
]);
|
||||
|
@ -2636,7 +2652,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
if (typeArgs == null) {
|
||||
return simpleId;
|
||||
}
|
||||
return js.call('dart.gbind(#, #)', [simpleId, typeArgs]);
|
||||
return _callHelper('gbind(#, #)', [simpleId, typeArgs]);
|
||||
}
|
||||
|
||||
/// Emits a simple identifier, handling implicit `this` as well as
|
||||
|
@ -2663,7 +2679,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
// If the type is a type literal expression in Dart code, wrap the raw
|
||||
// runtime type in a "Type" instance.
|
||||
if (!_isInForeignJS && _isTypeLiteral(node)) {
|
||||
typeName = js.call('dart.wrapType(#)', typeName);
|
||||
typeName = _callHelper('wrapType(#)', typeName);
|
||||
}
|
||||
|
||||
return typeName;
|
||||
|
@ -2694,8 +2710,8 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
// For instance members, we add implicit-this.
|
||||
// For method tear-offs, we ensure it's a bound method.
|
||||
var tearOff = element is MethodElement && !inInvocationContext(node);
|
||||
var code = (tearOff) ? 'dart.bind(this, #)' : 'this.#';
|
||||
return js.call(code, member);
|
||||
if (tearOff) return _callHelper('bind(this, #)', member);
|
||||
return js.call('this.#', member);
|
||||
}
|
||||
|
||||
if (element is ParameterElement) {
|
||||
|
@ -2812,7 +2828,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
nameType: nameType,
|
||||
hoistType: hoistType);
|
||||
var helper = (definite) ? 'definiteFunctionType' : 'functionType';
|
||||
var fullType = js.call('dart.${helper}(#)', [parts]);
|
||||
var fullType = _callHelper('${helper}(#)', [parts]);
|
||||
if (!nameType) return fullType;
|
||||
return _typeTable.nameType(type, fullType,
|
||||
hoistType: hoistType, definite: definite);
|
||||
|
@ -2908,11 +2924,11 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
JS.Expression className}) {
|
||||
// The void and dynamic types are not defined in core.
|
||||
if (type.isVoid) {
|
||||
return js.call('dart.void');
|
||||
return _callHelper('void');
|
||||
} else if (type.isDynamic) {
|
||||
return js.call('dart.dynamic');
|
||||
return _callHelper('dynamic');
|
||||
} else if (type.isBottom) {
|
||||
return js.call('dart.bottom');
|
||||
return _callHelper('bottom');
|
||||
}
|
||||
|
||||
_declareBeforeUse(type.element);
|
||||
|
@ -3059,11 +3075,18 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
var l = _visit(_bindValue(vars, 'l', target));
|
||||
var name = _emitMemberName(id.name);
|
||||
return new JS.MetaLet(vars, [
|
||||
js.call('(#[(#[dart._extensionType]) ? dartx[#] : #] = #)',
|
||||
[l, l, name, name, _visit(rhs)])
|
||||
js.call('(#[(#[#._extensionType]) ? #[#] : #] = #)', [
|
||||
l,
|
||||
l,
|
||||
_runtimeModule,
|
||||
name,
|
||||
_extensionSymbolsModule,
|
||||
name,
|
||||
_visit(rhs)
|
||||
])
|
||||
]);
|
||||
}
|
||||
return js.call('dart.#(#, #, #)', [
|
||||
return _callHelper('#(#, #, #)', [
|
||||
_emitDynamicOperationName('dput'),
|
||||
_visit(target),
|
||||
_emitMemberName(id.name),
|
||||
|
@ -3096,7 +3119,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
// TODO(sra): We should get here only for compiler bugs or weirdness due to
|
||||
// --unsafe-force-compile. Once those paths have been addressed, throw at
|
||||
// compile time.
|
||||
return js.call('dart.throwUnimplementedError((#, #, #))',
|
||||
return _callHelper('throwUnimplementedError((#, #, #))',
|
||||
[js.string('$lhs ='), _visit(rhs), js.string(problem)]);
|
||||
}
|
||||
|
||||
|
@ -3346,14 +3369,21 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
var vars = <JS.MetaLetVariable, JS.Expression>{};
|
||||
var l = _visit(_bindValue(vars, 'l', target));
|
||||
jsTarget = new JS.MetaLet(vars, [
|
||||
js.call('(#[(#[dart._extensionType]) ? dartx[#] : #]).bind(#)',
|
||||
[l, l, memberName, memberName, l])
|
||||
js.call('(#[(#[#._extensionType]) ? #[#] : #]).bind(#)', [
|
||||
l,
|
||||
l,
|
||||
_runtimeModule,
|
||||
memberName,
|
||||
_extensionSymbolsModule,
|
||||
memberName,
|
||||
l
|
||||
])
|
||||
]);
|
||||
if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs);
|
||||
return new JS.Call(jsTarget, args);
|
||||
}
|
||||
if (typeArgs != null) {
|
||||
return js.call('dart.#(#, #, #, #)', [
|
||||
return _callHelper('#(#, #, #, #)', [
|
||||
_emitDynamicOperationName('dgsend'),
|
||||
jsTarget,
|
||||
new JS.ArrayInitializer(typeArgs),
|
||||
|
@ -3361,13 +3391,13 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
args
|
||||
]);
|
||||
} else {
|
||||
return js.call('dart.#(#, #, #)',
|
||||
return _callHelper('#(#, #, #)',
|
||||
[_emitDynamicOperationName('dsend'), jsTarget, memberName, args]);
|
||||
}
|
||||
}
|
||||
if (_isObjectMemberCall(target, name)) {
|
||||
assert(typeArgs == null); // Object methods don't take type args.
|
||||
return js.call('dart.#(#, #)', [name, jsTarget, args]);
|
||||
return _callHelper('#(#, #)', [name, jsTarget, args]);
|
||||
}
|
||||
|
||||
jsTarget = new JS.PropertyAccess(jsTarget, memberName);
|
||||
|
@ -3380,13 +3410,13 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
InvocationExpression node, JS.Expression fn, List<JS.Expression> args) {
|
||||
var typeArgs = _emitInvokeTypeArguments(node);
|
||||
if (typeArgs != null) {
|
||||
return js.call('dart.dgcall(#, #, #)',
|
||||
[fn, new JS.ArrayInitializer(typeArgs), args]);
|
||||
return _callHelper(
|
||||
'dgcall(#, #, #)', [fn, new JS.ArrayInitializer(typeArgs), args]);
|
||||
} else {
|
||||
if (_inWhitelistCode(node, isCall: true)) {
|
||||
return new JS.Call(fn, args);
|
||||
}
|
||||
return js.call('dart.dcall(#, #)', [fn, args]);
|
||||
return _callHelper('dcall(#, #)', [fn, args]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3629,7 +3659,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
@override
|
||||
JS.Statement visitAssertStatement(AssertStatement node) =>
|
||||
// TODO(jmesserly): only emit in checked mode.
|
||||
js.statement('dart.assert(#);', _visit(node.condition));
|
||||
_callHelperStatement('assert(#);', _visit(node.condition));
|
||||
|
||||
@override
|
||||
JS.Statement visitReturnStatement(ReturnStatement node) {
|
||||
|
@ -3839,7 +3869,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
objExpr = emitLibraryName(target);
|
||||
}
|
||||
|
||||
return js.statement('dart.defineLazy(#, { # });', [objExpr, methods]);
|
||||
return _callHelperStatement('defineLazy(#, { # });', [objExpr, methods]);
|
||||
}
|
||||
|
||||
PropertyAccessorElement _findAccessor(VariableElement element,
|
||||
|
@ -3956,7 +3986,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
if (expr == null) return null;
|
||||
var jsExpr = _visit(expr);
|
||||
if (!isNullable(expr)) return jsExpr;
|
||||
return js.call('dart.notNull(#)', jsExpr);
|
||||
return _callHelper('notNull(#)', jsExpr);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -3986,7 +4016,8 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
return _emitSend(left, op.lexeme, [right]);
|
||||
} else {
|
||||
var bang = op.type == TokenType.BANG_EQ ? '!' : '';
|
||||
code = '${bang}dart.equals(#, #)';
|
||||
code = '${bang}#.equals(#, #)';
|
||||
return js.call(code, [_runtimeModule, _visit(left), _visit(right)]);
|
||||
}
|
||||
return js.call(code, [_visit(left), _visit(right)]);
|
||||
}
|
||||
|
@ -4299,7 +4330,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
}
|
||||
|
||||
JS.Expression _emitConst(JS.Expression expr()) =>
|
||||
_cacheConst(() => js.call('dart.const(#)', expr()));
|
||||
_cacheConst(() => _callHelper('const(#)', expr()));
|
||||
|
||||
/// Returns a new expression, which can be be used safely *once* on the
|
||||
/// left hand side, and *once* on the right side of an assignment.
|
||||
|
@ -4561,8 +4592,8 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
}
|
||||
}
|
||||
if (tail.isEmpty) return _visit(node);
|
||||
return js.call(
|
||||
'dart.nullSafe(#, #)', [_visit(node) as JS.Expression, tail.reversed]);
|
||||
return _callHelper(
|
||||
'nullSafe(#, #)', [_visit(node) as JS.Expression, tail.reversed]);
|
||||
}
|
||||
|
||||
static Token _getOperator(Expression node) {
|
||||
|
@ -4659,11 +4690,11 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
var vars = <JS.MetaLetVariable, JS.Expression>{};
|
||||
var l = _visit(_bindValue(vars, 'l', target));
|
||||
return new JS.MetaLet(vars, [
|
||||
js.call('(#[dart._extensionType]) ? #[dartx[#]] : #.#',
|
||||
[l, l, name, l, name])
|
||||
js.call('(#[#._extensionType]) ? #[#[#]] : #.#',
|
||||
[l, _runtimeModule, l, _extensionSymbolsModule, name, l, name])
|
||||
]);
|
||||
}
|
||||
return js.call('dart.#(#, #)',
|
||||
return _callHelper('#(#, #)',
|
||||
[_emitDynamicOperationName('dload'), _visit(target), name]);
|
||||
}
|
||||
|
||||
|
@ -4680,22 +4711,22 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
if (member != null && member is MethodElement && !isStatic) {
|
||||
// Tear-off methods: explicitly bind it.
|
||||
if (isSuper) {
|
||||
result = js.call('dart.bind(this, #, #.#)', [name, jsTarget, name]);
|
||||
result = _callHelper('bind(this, #, #.#)', [name, jsTarget, name]);
|
||||
} else if (_isObjectMemberCall(target, memberName)) {
|
||||
result = js.call('dart.bind(#, #, dart.#)',
|
||||
[jsTarget, _propertyName(memberName), memberName]);
|
||||
result = _callHelper('bind(#, #, #.#)',
|
||||
[jsTarget, _propertyName(memberName), _runtimeModule, memberName]);
|
||||
} else {
|
||||
result = js.call('dart.bind(#, #)', [jsTarget, name]);
|
||||
result = _callHelper('bind(#, #)', [jsTarget, name]);
|
||||
}
|
||||
} else if (_isObjectMemberCall(target, memberName)) {
|
||||
result = js.call('dart.#(#)', [memberName, jsTarget]);
|
||||
result = _callHelper('#(#)', [memberName, jsTarget]);
|
||||
} else {
|
||||
result = js.call('#.#', [jsTarget, name]);
|
||||
}
|
||||
if (typeArgs == null) {
|
||||
return result;
|
||||
}
|
||||
return js.call('dart.gbind(#, #)', [result, typeArgs]);
|
||||
return _callHelper('gbind(#, #)', [result, typeArgs]);
|
||||
}
|
||||
|
||||
/// Emits a generic send, like an operator method.
|
||||
|
@ -4712,18 +4743,26 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
var vars = <JS.MetaLetVariable, JS.Expression>{};
|
||||
var l = _visit(_bindValue(vars, 'l', target));
|
||||
return new JS.MetaLet(vars, [
|
||||
js.call('(#[(#[dart._extensionType]) ? dartx[#] : #]).call(#, #)',
|
||||
[l, l, memberName, memberName, l, _visitList(args)])
|
||||
js.call('(#[(#[#._extensionType]) ? #[#] : #]).call(#, #)', [
|
||||
l,
|
||||
l,
|
||||
_runtimeModule,
|
||||
memberName,
|
||||
_extensionSymbolsModule,
|
||||
memberName,
|
||||
l,
|
||||
_visitList(args)
|
||||
])
|
||||
]);
|
||||
}
|
||||
// dynamic dispatch
|
||||
var dynamicHelper = const {'[]': 'dindex', '[]=': 'dsetindex'}[name];
|
||||
if (dynamicHelper != null) {
|
||||
return js.call('dart.$dynamicHelper(#, #)',
|
||||
return _callHelper('$dynamicHelper(#, #)',
|
||||
[_visit(target) as JS.Expression, _visitList(args)]);
|
||||
} else {
|
||||
return js.call('dart.dsend(#, #, #)',
|
||||
[_visit(target), memberName, _visitList(args)]);
|
||||
return _callHelper(
|
||||
'dsend(#, #, #)', [_visit(target), memberName, _visitList(args)]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4767,9 +4806,9 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
visitThrowExpression(ThrowExpression node) {
|
||||
var expr = _visit(node.expression);
|
||||
if (node.parent is ExpressionStatement) {
|
||||
return js.statement('dart.throw(#);', expr);
|
||||
return _callHelperStatement('throw(#);', expr);
|
||||
} else {
|
||||
return js.call('dart.throw(#)', expr);
|
||||
return _callHelper('throw(#)', expr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4972,8 +5011,8 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
}
|
||||
if (node.stackTraceParameter != null) {
|
||||
var stackVar = node.stackTraceParameter.name;
|
||||
body.add(js.statement(
|
||||
'let # = dart.stackTrace(#);', [stackVar, _visit(name)]));
|
||||
body.add(js.statement('let # = #.stackTrace(#);',
|
||||
[stackVar, _runtimeModule, _visit(name)]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5055,7 +5094,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
_declareBeforeUse(_jsArray);
|
||||
if (isConst) {
|
||||
var typeRep = _emitType(elementType);
|
||||
list = js.call('dart.constList(#, #)', [list, typeRep]);
|
||||
list = _callHelper('constList(#, #)', [list, typeRep]);
|
||||
} else {
|
||||
// Call `new JSArray<E>.of(list)`
|
||||
var jsArrayType = _jsArray.type.instantiate(type.typeArguments);
|
||||
|
@ -5101,7 +5140,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
if (reifyTypeArgs) {
|
||||
types.addAll(typeArgs.map((e) => _emitType(e)));
|
||||
}
|
||||
return js.call('dart.map(#, #)', [mapArguments, types]);
|
||||
return _callHelper('map(#, #)', [mapArguments, types]);
|
||||
}
|
||||
|
||||
if (node.constKeyword != null) return _emitConst(emitMap);
|
||||
|
@ -5119,7 +5158,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
@override
|
||||
JS.Expression visitStringInterpolation(StringInterpolation node) {
|
||||
return new JS.TaggedTemplate(
|
||||
js.call('dart.str'), new JS.TemplateString(_visitList(node.elements)));
|
||||
_callHelper('str'), new JS.TemplateString(_visitList(node.elements)));
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -5141,7 +5180,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
_unimplementedCall('Unimplemented ${node.runtimeType}: $node');
|
||||
|
||||
JS.Expression _unimplementedCall(String comment) {
|
||||
return js.call('dart.throw(#)', [js.escapedString(comment)]);
|
||||
return _callHelper('throw(#)', [js.escapedString(comment)]);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -5198,10 +5237,10 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
}
|
||||
if (node is AsExpression && CoercionReifier.isImplicitCast(node)) {
|
||||
assert(node.staticType == types.boolType);
|
||||
return js.call('dart.test(#)', _visit(node.expression));
|
||||
return _callHelper('test(#)', _visit(node.expression));
|
||||
}
|
||||
JS.Expression result = _visit(node);
|
||||
if (isNullable(node)) result = js.call('dart.test(#)', result);
|
||||
if (isNullable(node)) result = _callHelper('test(#)', result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -5302,7 +5341,9 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
!isObjectMember(name);
|
||||
}
|
||||
|
||||
return useExtension ? js.call('dartx.#', result) : result;
|
||||
return useExtension
|
||||
? js.call('#.#', [_extensionSymbolsModule, result])
|
||||
: result;
|
||||
}
|
||||
|
||||
JS.TemporaryId _emitPrivateNameSymbol(LibraryElement library, String name) {
|
||||
|
@ -5405,6 +5446,26 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|||
}
|
||||
}
|
||||
|
||||
JS.Expression _callHelper(String code, [args]) {
|
||||
if (args is List) {
|
||||
args.insert(0, _runtimeModule);
|
||||
} else if (args != null) {
|
||||
args = [_runtimeModule, args];
|
||||
} else {
|
||||
args = _runtimeModule;
|
||||
}
|
||||
return js.call('#.$code', args);
|
||||
}
|
||||
|
||||
JS.Statement _callHelperStatement(String code, args) {
|
||||
if (args is List) {
|
||||
args.insert(0, _runtimeModule);
|
||||
} else {
|
||||
args = [_runtimeModule, args];
|
||||
}
|
||||
return js.statement('#.$code', args);
|
||||
}
|
||||
|
||||
/// Maps whitelisted files to a list of whitelisted methods
|
||||
/// within the file.
|
||||
///
|
||||
|
|
|
@ -122,13 +122,17 @@ class _CacheTable {
|
|||
class _GeneratorTable extends _CacheTable {
|
||||
final _defs = new HashMap<DartType, JS.Expression>();
|
||||
|
||||
final JS.Identifier _runtimeModule;
|
||||
|
||||
_GeneratorTable(this._runtimeModule);
|
||||
|
||||
JS.Statement _dischargeType(DartType t) {
|
||||
var name = _names.remove(t);
|
||||
if (name != null) {
|
||||
JS.Expression init = _defs.remove(t);
|
||||
assert(init != null);
|
||||
return js.statement(
|
||||
'let # = () => ((# = dart.constFn(#))());', [name, name, init]);
|
||||
return js.statement('let # = () => ((# = #.constFn(#))());',
|
||||
[name, name, _runtimeModule, init]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -154,10 +158,10 @@ class TypeTable {
|
|||
final _definiteCacheNames = new _CacheTable();
|
||||
|
||||
/// Generator variable names for hoisted types.
|
||||
final _generators = new _GeneratorTable();
|
||||
final _GeneratorTable _generators;
|
||||
|
||||
/// Generator variable names for hoisted definite function types.
|
||||
final _definiteGenerators = new _GeneratorTable();
|
||||
final _GeneratorTable _definiteGenerators;
|
||||
|
||||
/// Mapping from type parameters to the types which must have their
|
||||
/// cache/generator variables discharged at the binding site for the
|
||||
|
@ -166,6 +170,10 @@ class TypeTable {
|
|||
final _scopeDependencies =
|
||||
new HashMap<TypeParameterElement, List<DartType>>();
|
||||
|
||||
TypeTable(JS.Identifier runtime)
|
||||
: _generators = new _GeneratorTable(runtime),
|
||||
_definiteGenerators = new _GeneratorTable(runtime);
|
||||
|
||||
/// Emit a list of statements declaring the cache variables and generator
|
||||
/// definitions tracked by the table. If [formals] is present, only
|
||||
/// emit the definitions which depend on the formals.
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
main() {
|
||||
dynamic dart = 123;
|
||||
Expect.equals(dart.toDouble(), 123.0);
|
||||
}
|
Loading…
Reference in a new issue