From ce76fc1fe5268a8621b85780fc90b7e829ee9b53 Mon Sep 17 00:00:00 2001 From: Jennifer Messerly Date: Fri, 21 Oct 2016 11:48:19 -0700 Subject: [PATCH] fix #27644, allow "dart" and "dartx" to be renamed if needed R=vsm@google.com Review URL: https://codereview.chromium.org/2435223002 . --- .../lib/src/compiler/code_generator.dart | 321 +++++++++++------- .../lib/src/compiler/type_utilities.dart | 16 +- .../language/variable_named_dart_test.dart | 10 + 3 files changed, 213 insertions(+), 134 deletions(-) create mode 100644 pkg/dev_compiler/test/codegen/language/variable_named_dart_test.dart diff --git a/pkg/dev_compiler/lib/src/compiler/code_generator.dart b/pkg/dev_compiler/lib/src/compiler/code_generator.dart index 4938b1a2d5b..42a72cac83d 100644 --- a/pkg/dev_compiler/lib/src/compiler/code_generator.dart +++ b/pkg/dev_compiler/lib/src/compiler/code_generator.dart @@ -74,7 +74,7 @@ class CodeGenerator extends GeneralizingAstVisitor final _moduleItems = []; /// 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(); - 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(); @@ -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 = []; 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 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 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 ctors, List 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 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.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 body) { if (classElem.interfaces.isNotEmpty) { - body.add(js.statement('#[dart.implements] = () => #;', [ + body.add(js.statement('#[#.implements] = () => #;', [ className, + _runtimeModule, new JS.ArrayInitializer( new List.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 = {}; 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 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 = {}; 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 = {}; 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.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. /// diff --git a/pkg/dev_compiler/lib/src/compiler/type_utilities.dart b/pkg/dev_compiler/lib/src/compiler/type_utilities.dart index 27abedd3a29..7632f08124f 100644 --- a/pkg/dev_compiler/lib/src/compiler/type_utilities.dart +++ b/pkg/dev_compiler/lib/src/compiler/type_utilities.dart @@ -122,13 +122,17 @@ class _CacheTable { class _GeneratorTable extends _CacheTable { final _defs = new HashMap(); + 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>(); + 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. diff --git a/pkg/dev_compiler/test/codegen/language/variable_named_dart_test.dart b/pkg/dev_compiler/test/codegen/language/variable_named_dart_test.dart new file mode 100644 index 00000000000..233b60f899e --- /dev/null +++ b/pkg/dev_compiler/test/codegen/language/variable_named_dart_test.dart @@ -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); +}