| Index: pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
|
| diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
|
| index 334b7462e8518239135b2a111047fc190f7cd8e4..27498505b37e687e9e123ef91802259435bbf18b 100644
|
| --- a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
|
| +++ b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
|
| @@ -43,9 +43,11 @@ class OldEmitter implements Emitter {
|
| => task.outputClassLists;
|
| Map<OutputUnit, List<ConstantValue>> get outputConstantLists
|
| => task.outputConstantLists;
|
| - final Map<String, String> mangledFieldNames = <String, String>{};
|
| - final Map<String, String> mangledGlobalFieldNames = <String, String>{};
|
| - final Set<String> recordedMangledNames = new Set<String>();
|
| + final Map<jsAst.Name, String> mangledFieldNames =
|
| + new HashMap<jsAst.Name, String>();
|
| + final Map<jsAst.Name, String> mangledGlobalFieldNames =
|
| + new HashMap<jsAst.Name, String>();
|
| + final Set<jsAst.Name> recordedMangledNames = new Set<jsAst.Name>();
|
|
|
| List<TypedefElement> get typedefsNeededForReflection =>
|
| task.typedefsNeededForReflection;
|
| @@ -93,7 +95,7 @@ class OldEmitter implements Emitter {
|
| cachedClassBuilders = compiler.cacheStrategy.newMap(),
|
| cachedElements = compiler.cacheStrategy.newSet() {
|
| constantEmitter = new ConstantEmitter(
|
| - compiler, namer, this.constantReference, makeConstantListTemplate);
|
| + compiler, namer, this.constantReference, constantListGenerator);
|
| containerBuilder.emitter = this;
|
| classEmitter.emitter = this;
|
| nsmEmitter.emitter = this;
|
| @@ -152,7 +154,9 @@ class OldEmitter implements Emitter {
|
| if (r != 0) return r;
|
| // Resolve collisions in the long name by using the constant name (i.e. JS
|
| // name) which is unique.
|
| - return namer.constantName(a).compareTo(namer.constantName(b));
|
| + // TODO(herhut): Find a better way to resolve collisions.
|
| + return namer.constantName(a).hashCode.compareTo(
|
| + namer.constantName(b).hashCode);
|
| }
|
|
|
| @override
|
| @@ -187,7 +191,8 @@ class OldEmitter implements Emitter {
|
| => '${namer.isolateName}.${lazyInitializerProperty}';
|
| String get initName => 'init';
|
|
|
| - String get makeConstListProperty => namer.internalGlobal('makeConstantList');
|
| + jsAst.Name get makeConstListProperty
|
| + => namer.internalGlobal('makeConstantList');
|
|
|
| /// The name of the property that contains all field names.
|
| ///
|
| @@ -199,7 +204,7 @@ class OldEmitter implements Emitter {
|
|
|
| /// Contains the global state that is needed to initialize and load a
|
| /// deferred library.
|
| - String get globalsHolder => namer.internalGlobal("globalsHolder");
|
| + jsAst.Name get globalsHolder => namer.internalGlobal("globalsHolder");
|
|
|
| @override
|
| jsAst.Expression generateEmbeddedGlobalAccess(String global) {
|
| @@ -212,8 +217,8 @@ class OldEmitter implements Emitter {
|
| }
|
|
|
| jsAst.PropertyAccess globalPropertyAccess(Element element) {
|
| - String name = namer.globalPropertyName(element);
|
| - jsAst.PropertyAccess pa = new jsAst.PropertyAccess.field(
|
| + jsAst.Name name = namer.globalPropertyName(element);
|
| + jsAst.PropertyAccess pa = new jsAst.PropertyAccess(
|
| new jsAst.VariableUse(namer.globalObjectFor(element)),
|
| name);
|
| return pa;
|
| @@ -293,23 +298,8 @@ class OldEmitter implements Emitter {
|
| return jsAst.js.expressionTemplateFor(
|
| "('$isPrefix' + #) in #.prototype");
|
|
|
| - case JsBuiltin.isFunctionTypeRti:
|
| - String functionClassName =
|
| - backend.namer.runtimeTypeName(compiler.functionClass);
|
| - return jsAst.js.expressionTemplateFor(
|
| - '#.$typeNameProperty === "$functionClassName"');
|
| -
|
| - case JsBuiltin.isDartObjectTypeRti:
|
| - String objectClassName =
|
| - backend.namer.runtimeTypeName(compiler.objectClass);
|
| - return jsAst.js.expressionTemplateFor(
|
| - '#.$typeNameProperty === "$objectClassName"');
|
| -
|
| - case JsBuiltin.isNullTypeRti:
|
| - String nullClassName =
|
| - backend.namer.runtimeTypeName(compiler.nullClass);
|
| - return jsAst.js.expressionTemplateFor(
|
| - '#.$typeNameProperty === "$nullClassName"');
|
| + case JsBuiltin.isGivenTypeRti:
|
| + return jsAst.js.expressionTemplateFor('#.$typeNameProperty === #');
|
|
|
| case JsBuiltin.getMetadata:
|
| String metadataAccess =
|
| @@ -371,7 +361,7 @@ class OldEmitter implements Emitter {
|
| /// The reflection name of class 'C' is 'C'.
|
| /// An anonymous mixin application has no reflection name.
|
| /// This is used by js_mirrors.dart.
|
| - String getReflectionName(elementOrSelector, String mangledName) {
|
| + String getReflectionName(elementOrSelector, jsAst.Name mangledName) {
|
| String name = elementOrSelector.name;
|
| if (backend.shouldRetainName(name) ||
|
| elementOrSelector is Element &&
|
| @@ -390,13 +380,15 @@ class OldEmitter implements Emitter {
|
| return null;
|
| }
|
|
|
| - String getReflectionNameInternal(elementOrSelector, String mangledName) {
|
| + String getReflectionNameInternal(elementOrSelector,
|
| + jsAst.Name mangledName) {
|
| String name = namer.privateName(elementOrSelector.memberName);
|
| if (elementOrSelector.isGetter) return name;
|
| if (elementOrSelector.isSetter) {
|
| - if (!mangledName.startsWith(namer.setterPrefix)) return '$name=';
|
| - String base = mangledName.substring(namer.setterPrefix.length);
|
| - String getter = '${namer.getterPrefix}$base';
|
| + if (mangledName is! SetterName) return '$name=';
|
| + SetterName setterName = mangledName;
|
| + jsAst.Name base = setterName.base;
|
| + jsAst.Name getter = namer.deriveGetterName(base);
|
| mangledFieldNames.putIfAbsent(getter, () => name);
|
| assert(mangledFieldNames[getter] == name);
|
| recordedMangledNames.add(getter);
|
| @@ -409,7 +401,7 @@ class OldEmitter implements Emitter {
|
| // Closures are synthesized and their name might conflict with existing
|
| // globals. Assign an illegal name, and make sure they don't clash
|
| // with each other.
|
| - return " $mangledName";
|
| + return " $name";
|
| }
|
| if (elementOrSelector is Selector
|
| || elementOrSelector.isFunction
|
| @@ -501,7 +493,8 @@ class OldEmitter implements Emitter {
|
| if (compiler.hasIncrementalSupport) {
|
| ClassBuilder cachedBuilder =
|
| cachedClassBuilders.putIfAbsent(classElement, () {
|
| - ClassBuilder builder = new ClassBuilder(classElement, namer);
|
| + ClassBuilder builder =
|
| + new ClassBuilder.forClass(classElement, namer);
|
| classEmitter.emitClass(cls, builder, fragment);
|
| return builder;
|
| });
|
| @@ -525,7 +518,7 @@ class OldEmitter implements Emitter {
|
| // We need to filter out null-elements for the interceptors.
|
| // TODO(floitsch): use the precomputed interceptors here.
|
| if (element == null) continue;
|
| - ClassBuilder builder = new ClassBuilder(element, namer);
|
| + ClassBuilder builder = new ClassBuilder.forStatics(element, namer);
|
| containerBuilder.addMemberMethod(method, builder);
|
| getElementDescriptor(element, fragment).properties
|
| .addAll(builder.properties);
|
| @@ -625,12 +618,12 @@ class OldEmitter implements Emitter {
|
| // before code generation.
|
| if (code == null) continue;
|
| if (compiler.enableMinification) {
|
| - laziesInfo.addAll([js.string(namer.globalPropertyName(element)),
|
| - js.string(namer.lazyInitializerName(element)),
|
| + laziesInfo.addAll([js.quoteName(namer.globalPropertyName(element)),
|
| + js.quoteName(namer.lazyInitializerName(element)),
|
| code]);
|
| } else {
|
| - laziesInfo.addAll([js.string(namer.globalPropertyName(element)),
|
| - js.string(namer.lazyInitializerName(element)),
|
| + laziesInfo.addAll([js.quoteName(namer.globalPropertyName(element)),
|
| + js.quoteName(namer.lazyInitializerName(element)),
|
| code,
|
| js.string(element.name)]);
|
| }
|
| @@ -655,8 +648,8 @@ class OldEmitter implements Emitter {
|
| // in new lazy values.
|
| return js('#(#,#,#,#,#)',
|
| [js(lazyInitializerName),
|
| - js.string(namer.globalPropertyName(element)),
|
| - js.string(namer.lazyInitializerName(element)),
|
| + js.quoteName(namer.globalPropertyName(element)),
|
| + js.quoteName(namer.lazyInitializerName(element)),
|
| code,
|
| js.string(element.name),
|
| isolateProperties]);
|
| @@ -665,14 +658,14 @@ class OldEmitter implements Emitter {
|
| if (compiler.enableMinification) {
|
| return js('#(#,#,#)',
|
| [js(lazyInitializerName),
|
| - js.string(namer.globalPropertyName(element)),
|
| - js.string(namer.lazyInitializerName(element)),
|
| + js.quoteName(namer.globalPropertyName(element)),
|
| + js.quoteName(namer.lazyInitializerName(element)),
|
| code]);
|
| } else {
|
| return js('#(#,#,#,#)',
|
| [js(lazyInitializerName),
|
| - js.string(namer.globalPropertyName(element)),
|
| - js.string(namer.lazyInitializerName(element)),
|
| + js.quoteName(namer.globalPropertyName(element)),
|
| + js.quoteName(namer.lazyInitializerName(element)),
|
| code,
|
| js.string(element.name)]);
|
| }
|
| @@ -720,16 +713,15 @@ class OldEmitter implements Emitter {
|
| }
|
|
|
| jsAst.Statement buildConstantInitializer(ConstantValue constant) {
|
| - String name = namer.constantName(constant);
|
| + jsAst.Name name = namer.constantName(constant);
|
| return js.statement('#.# = #',
|
| [namer.globalObjectForConstant(constant), name,
|
| constantInitializerExpression(constant)]);
|
| }
|
|
|
| - jsAst.Template get makeConstantListTemplate {
|
| + jsAst.Expression constantListGenerator(jsAst.Expression array) {
|
| // TODO(floitsch): there is no harm in caching the template.
|
| - return jsAst.js.uncachedExpressionTemplate(
|
| - '${namer.isolateName}.$makeConstListProperty(#)');
|
| + return js('${namer.isolateName}.#(#)', [makeConstListProperty, array]);
|
| }
|
|
|
| jsAst.Statement buildMakeConstantList() {
|
| @@ -1024,12 +1016,11 @@ class OldEmitter implements Emitter {
|
| }
|
|
|
| void assemblePrecompiledConstructor(OutputUnit outputUnit,
|
| - String constructorName,
|
| + jsAst.Name constructorName,
|
| jsAst.Expression constructorAst,
|
| List<String> fields) {
|
| cspPrecompiledFunctionFor(outputUnit).add(
|
| - new jsAst.FunctionDeclaration(
|
| - new jsAst.VariableDeclaration(constructorName), constructorAst));
|
| + new jsAst.FunctionDeclaration(constructorName, constructorAst));
|
|
|
| String fieldNamesProperty = FIELD_NAMES_PROPERTY_NAME;
|
| bool hasIsolateSupport = compiler.hasIsolateSupport;
|
| @@ -1051,7 +1042,7 @@ class OldEmitter implements Emitter {
|
| }''',
|
| {"constructorName": constructorName,
|
| "typeNameProperty": typeNameProperty,
|
| - "constructorNameString": js.string(constructorName),
|
| + "constructorNameString": js.quoteName(constructorName),
|
| "hasIsolateSupport": hasIsolateSupport,
|
| "fieldNamesArray": fieldNamesArray}));
|
|
|
| @@ -1073,10 +1064,11 @@ class OldEmitter implements Emitter {
|
| // typedefs is supported.
|
| jsAst.Expression typeIndex =
|
| task.metadataCollector.reifyType(type, ignoreTypeVariables: true);
|
| - ClassBuilder builder = new ClassBuilder(typedef, namer);
|
| - builder.addProperty(embeddedNames.TYPEDEF_TYPE_PROPERTY_NAME, typeIndex);
|
| - builder.addProperty(embeddedNames.TYPEDEF_PREDICATE_PROPERTY_NAME,
|
| - js.boolean(true));
|
| + ClassBuilder builder = new ClassBuilder.forStatics(typedef, namer);
|
| + builder.addPropertyByName(embeddedNames.TYPEDEF_TYPE_PROPERTY_NAME,
|
| + typeIndex);
|
| + builder.addPropertyByName(embeddedNames.TYPEDEF_PREDICATE_PROPERTY_NAME,
|
| + js.boolean(true));
|
|
|
| // We can be pretty sure that the objectClass is initialized, since
|
| // typedefs are only emitted with reflection, which requires lots of
|
| @@ -1084,13 +1076,13 @@ class OldEmitter implements Emitter {
|
| assert(compiler.objectClass != null);
|
| builder.superName = namer.className(compiler.objectClass);
|
| jsAst.Node declaration = builder.toObjectInitializer();
|
| - String mangledName = namer.globalPropertyName(typedef);
|
| + jsAst.Name mangledName = namer.globalPropertyName(typedef);
|
| String reflectionName = getReflectionName(typedef, mangledName);
|
| getElementDescriptor(library, mainFragment)
|
| ..addProperty(mangledName, declaration)
|
| - ..addProperty("+$reflectionName", js.string(''));
|
| + ..addPropertyByName("+$reflectionName", js.string(''));
|
| // Also emit a trivial constructor for CSP mode.
|
| - String constructorName = mangledName;
|
| + jsAst.Name constructorName = mangledName;
|
| jsAst.Expression constructorAst = js('function() {}');
|
| List<String> fieldNames = [];
|
| assemblePrecompiledConstructor(mainOutputUnit,
|
| @@ -1190,12 +1182,11 @@ class OldEmitter implements Emitter {
|
| List<jsAst.Statement> parts = <jsAst.Statement>[];
|
|
|
| if (!mangledFieldNames.isEmpty) {
|
| - var keys = mangledFieldNames.keys.toList();
|
| - keys.sort();
|
| + List<jsAst.Name> keys = mangledFieldNames.keys.toList()..sort();
|
| var properties = [];
|
| - for (String key in keys) {
|
| - var value = js.string('${mangledFieldNames[key]}');
|
| - properties.add(new jsAst.Property(js.string(key), value));
|
| + for (jsAst.Name key in keys) {
|
| + var value = js.string(mangledFieldNames[key]);
|
| + properties.add(new jsAst.Property(key, value));
|
| }
|
|
|
| jsAst.Expression mangledNamesAccess =
|
| @@ -1205,16 +1196,16 @@ class OldEmitter implements Emitter {
|
| }
|
|
|
| if (!mangledGlobalFieldNames.isEmpty) {
|
| - var keys = mangledGlobalFieldNames.keys.toList();
|
| - keys.sort();
|
| - var properties = [];
|
| - for (String key in keys) {
|
| - var value = js.string('${mangledGlobalFieldNames[key]}');
|
| - properties.add(new jsAst.Property(js.string(key), value));
|
| + List<jsAst.Name> keys = mangledGlobalFieldNames.keys.toList()
|
| + ..sort();
|
| + List<jsAst.Property> properties = <jsAst.Property>[];
|
| + for (jsAst.Name key in keys) {
|
| + jsAst.Literal value = js.string(mangledGlobalFieldNames[key]);
|
| + properties.add(new jsAst.Property(js.quoteName(key), value));
|
| }
|
| jsAst.Expression mangledGlobalNamesAccess =
|
| generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES);
|
| - var map = new jsAst.ObjectInitializer(properties);
|
| + jsAst.ObjectInitializer map = new jsAst.ObjectInitializer(properties);
|
| parts.add(js.statement('# = #', [mangledGlobalNamesAccess, map]));
|
| }
|
|
|
| @@ -1717,6 +1708,7 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
|
|
| ClassBuilder getElementDescriptor(Element element, Fragment fragment) {
|
| Element owner = element.library;
|
| + bool isClass = false;
|
| if (!element.isLibrary && !element.isTopLevel && !element.isNative) {
|
| // For static (not top level) elements, record their code in a buffer
|
| // specific to the class. For now, not supported for native classes and
|
| @@ -1735,7 +1727,9 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
| }
|
| return elementDescriptors
|
| .putIfAbsent(fragment, () => new Map<Element, ClassBuilder>())
|
| - .putIfAbsent(owner, () => new ClassBuilder(owner, namer));
|
| + .putIfAbsent(owner, () {
|
| + return new ClassBuilder(owner, namer, owner.isClass);
|
| + });
|
| }
|
|
|
| /// Emits support-code for deferred loading into [output].
|
| @@ -1757,11 +1751,12 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
| // Function for initializing a loaded hunk, given its hash.
|
| #initializeLoadedHunk = function(hunkHash) {
|
| $deferredInitializers[hunkHash](
|
| - $globalsHolder, ${namer.currentIsolate});
|
| + #globalsHolder, ${namer.currentIsolate});
|
| #deferredInitialized[hunkHash] = true;
|
| };
|
| }
|
| - ''', {"isHunkLoaded": generateEmbeddedGlobalAccess(
|
| + ''', {"globalsHolder": globalsHolder,
|
| + "isHunkLoaded": generateEmbeddedGlobalAccess(
|
| embeddedNames.IS_HUNK_LOADED),
|
| "isHunkInitialized": generateEmbeddedGlobalAccess(
|
| embeddedNames.IS_HUNK_INITIALIZED),
|
| @@ -1834,14 +1829,18 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
| body.add(js.comment("/* ::norenaming:: "));
|
|
|
| for (String globalObject in Namer.reservedGlobalObjectNames) {
|
| - body.add(js.statement('var #object = ${globalsHolder}.#object;',
|
| - {'object': globalObject}));
|
| + body.add(js.statement('var #object = #globalsHolder.#object;',
|
| + {'globalsHolder': globalsHolder,
|
| + 'object': globalObject}));
|
| }
|
| - body..add(js.statement('var init = ${globalsHolder}.init;'))
|
| + body..add(js.statement('var init = #globalsHolder.init;',
|
| + {'globalsHolder': globalsHolder}))
|
| ..add(js.statement('var $setupProgramName = '
|
| - '$globalsHolder.$setupProgramName;'))
|
| + '#globalsHolder.$setupProgramName;',
|
| + {'globalsHolder': globalsHolder}))
|
| ..add(js.statement('var ${namer.isolateName} = '
|
| - '${globalsHolder}.${namer.isolateName};'));
|
| + '#globalsHolder.${namer.isolateName};',
|
| + {'globalsHolder': globalsHolder}));
|
| String typesAccess =
|
| generateEmbeddedGlobalAccessString(embeddedNames.TYPES);
|
| if (libraryDescriptor != null) {
|
| @@ -1874,10 +1873,10 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
| statements
|
| ..add(buildGeneratedBy())
|
| ..add(js.statement('${deferredInitializers}.current = '
|
| - """function (${globalsHolder}) {
|
| + """function (#) {
|
| #
|
| }
|
| - """, [body]));
|
| + """, [globalsHolder, body]));
|
|
|
| result[outputUnit] = new jsAst.Program(statements);
|
| }
|
|
|