| 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 e05d1df1d8847e3dc77fcabd367e338640a928f4..0a8e2d16bc80d56c82e553a0a6753184b9f4ddaf 100644
|
| --- a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
|
| +++ b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
|
| @@ -273,344 +273,20 @@ class OldEmitter implements Emitter {
|
| return nsmEmitter.buildTrivialNsmHandlers();
|
| }
|
|
|
| - jsAst.FunctionDeclaration get generateAccessorFunction {
|
| - const RANGE1_SIZE = RANGE1_LAST - RANGE1_FIRST + 1;
|
| - const RANGE2_SIZE = RANGE2_LAST - RANGE2_FIRST + 1;
|
| - const RANGE1_ADJUST = - (FIRST_FIELD_CODE - RANGE1_FIRST);
|
| - const RANGE2_ADJUST = - (FIRST_FIELD_CODE + RANGE1_SIZE - RANGE2_FIRST);
|
| - const RANGE3_ADJUST =
|
| - - (FIRST_FIELD_CODE + RANGE1_SIZE + RANGE2_SIZE - RANGE3_FIRST);
|
| -
|
| - String receiverParamName = compiler.enableMinification ? "r" : "receiver";
|
| - String valueParamName = compiler.enableMinification ? "v" : "value";
|
| - String reflectableField = namer.reflectableField;
|
| -
|
| - return js.statement('''
|
| - function generateAccessor(fieldDescriptor, accessors, cls) {
|
| - var fieldInformation = fieldDescriptor.split("-");
|
| - var field = fieldInformation[0];
|
| - var len = field.length;
|
| - var code = field.charCodeAt(len - 1);
|
| - var reflectable;
|
| - if (fieldInformation.length > 1) reflectable = true;
|
| - else reflectable = false;
|
| - code = ((code >= $RANGE1_FIRST) && (code <= $RANGE1_LAST))
|
| - ? code - $RANGE1_ADJUST
|
| - : ((code >= $RANGE2_FIRST) && (code <= $RANGE2_LAST))
|
| - ? code - $RANGE2_ADJUST
|
| - : ((code >= $RANGE3_FIRST) && (code <= $RANGE3_LAST))
|
| - ? code - $RANGE3_ADJUST
|
| - : $NO_FIELD_CODE;
|
| -
|
| - if (code) { // needsAccessor
|
| - var getterCode = code & 3;
|
| - var setterCode = code >> 2;
|
| - var accessorName = field = field.substring(0, len - 1);
|
| -
|
| - var divider = field.indexOf(":");
|
| - if (divider > 0) { // Colon never in first position.
|
| - accessorName = field.substring(0, divider);
|
| - field = field.substring(divider + 1);
|
| - }
|
| -
|
| - if (getterCode) { // needsGetter
|
| - var args = (getterCode & 2) ? "$receiverParamName" : "";
|
| - var receiver = (getterCode & 1) ? "this" : "$receiverParamName";
|
| - var body = "return " + receiver + "." + field;
|
| - var property =
|
| - cls + ".prototype.${namer.getterPrefix}" + accessorName + "=";
|
| - var fn = "function(" + args + "){" + body + "}";
|
| - if (reflectable)
|
| - accessors.push(property + "\$reflectable(" + fn + ");\\n");
|
| - else
|
| - accessors.push(property + fn + ";\\n");
|
| - }
|
| -
|
| - if (setterCode) { // needsSetter
|
| - var args = (setterCode & 2)
|
| - ? "$receiverParamName,${_}$valueParamName"
|
| - : "$valueParamName";
|
| - var receiver = (setterCode & 1) ? "this" : "$receiverParamName";
|
| - var body = receiver + "." + field + "$_=$_$valueParamName";
|
| - var property =
|
| - cls + ".prototype.${namer.setterPrefix}" + accessorName + "=";
|
| - var fn = "function(" + args + "){" + body + "}";
|
| - if (reflectable)
|
| - accessors.push(property + "\$reflectable(" + fn + ");\\n");
|
| - else
|
| - accessors.push(property + fn + ";\\n");
|
| - }
|
| - }
|
| -
|
| - return field;
|
| - }''');
|
| - }
|
| -
|
| - List<jsAst.Node> get defineClassFunction {
|
| - // First the class name, then the field names in an array and the members
|
| - // (inside an Object literal).
|
| - // The caller can also pass in the constructor as a function if needed.
|
| - //
|
| - // Example:
|
| - // defineClass("A", ["x", "y"], {
|
| - // foo$1: function(y) {
|
| - // print(this.x + y);
|
| - // },
|
| - // bar$2: function(t, v) {
|
| - // this.x = t - v;
|
| - // },
|
| - // });
|
| -
|
| - bool hasIsolateSupport = compiler.hasIsolateSupport;
|
| - String fieldNamesProperty = FIELD_NAMES_PROPERTY_NAME;
|
| -
|
| - jsAst.Expression defineClass = js(r'''
|
| - function(name, fields) {
|
| - var accessors = [];
|
| -
|
| - var str = "function " + name + "(";
|
| - var body = "";
|
| - if (#hasIsolateSupport) { var fieldNames = ""; }
|
| -
|
| - for (var i = 0; i < fields.length; i++) {
|
| - if(i != 0) str += ", ";
|
| -
|
| - var field = generateAccessor(fields[i], accessors, name);
|
| - if (#hasIsolateSupport) { fieldNames += "'" + field + "',"; }
|
| - var parameter = "p_" + field;
|
| - str += parameter;
|
| - body += ("this." + field + " = " + parameter + ";\n");
|
| - }
|
| - if (supportsDirectProtoAccess) {
|
| - body += "this." + #deferredAction + "();";
|
| - }
|
| - str += ") {\n" + body + "}\n";
|
| - str += name + ".builtin$cls=\"" + name + "\";\n";
|
| - str += "$desc=$collectedClasses." + name + "[1];\n";
|
| - str += name + ".prototype = $desc;\n";
|
| - if (typeof defineClass.name != "string") {
|
| - str += name + ".name=\"" + name + "\";\n";
|
| - }
|
| - if (#hasIsolateSupport) {
|
| - str += name + "." + #fieldNamesProperty + "=[" + fieldNames
|
| - + "];\n";
|
| - }
|
| - str += accessors.join("");
|
| -
|
| - return str;
|
| - }''', { 'deferredAction': js.string(namer.deferredAction),
|
| - 'hasIsolateSupport': hasIsolateSupport,
|
| - 'fieldNamesProperty': js.string(fieldNamesProperty)});
|
| -
|
| - // Declare a function called "generateAccessor". This is used in
|
| - // defineClassFunction.
|
| - List result = <jsAst.Node>[
|
| - generateAccessorFunction,
|
| - new jsAst.FunctionDeclaration(
|
| - new jsAst.VariableDeclaration('defineClass'), defineClass) ];
|
| -
|
| - if (compiler.hasIncrementalSupport) {
|
| - result.add(
|
| - js(r'#.defineClass = defineClass', [namer.accessIncrementalHelper]));
|
| - }
|
| -
|
| - if (hasIsolateSupport) {
|
| - jsAst.Expression createNewIsolateFunctionAccess =
|
| - generateEmbeddedGlobalAccess(embeddedNames.CREATE_NEW_ISOLATE);
|
| - var createIsolateAssignment =
|
| - js('# = function() { return new ${namer.isolateName}(); }',
|
| - createNewIsolateFunctionAccess);
|
| -
|
| - jsAst.Expression classIdExtractorAccess =
|
| - generateEmbeddedGlobalAccess(embeddedNames.CLASS_ID_EXTRACTOR);
|
| - var classIdExtractorAssignment =
|
| - js('# = function(o) { return o.constructor.name; }',
|
| - classIdExtractorAccess);
|
| -
|
| - jsAst.Expression classFieldsExtractorAccess =
|
| - generateEmbeddedGlobalAccess(embeddedNames.CLASS_FIELDS_EXTRACTOR);
|
| - var classFieldsExtractorAssignment = js('''
|
| - # = function(o) {
|
| - var fieldNames = o.constructor.$fieldNamesProperty;
|
| - if (!fieldNames) return []; // TODO(floitsch): do something else here.
|
| - var result = [];
|
| - result.length = fieldNames.length;
|
| - for (var i = 0; i < fieldNames.length; i++) {
|
| - result[i] = o[fieldNames[i]];
|
| - }
|
| - return result;
|
| - }''', classFieldsExtractorAccess);
|
| -
|
| - jsAst.Expression instanceFromClassIdAccess =
|
| - generateEmbeddedGlobalAccess(embeddedNames.INSTANCE_FROM_CLASS_ID);
|
| - jsAst.Expression allClassesAccess =
|
| - generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES);
|
| - var instanceFromClassIdAssignment =
|
| - js('# = function(name) { return new #[name](); }',
|
| - [instanceFromClassIdAccess, allClassesAccess]);
|
| -
|
| - jsAst.Expression initializeEmptyInstanceAccess =
|
| - generateEmbeddedGlobalAccess(embeddedNames.INITIALIZE_EMPTY_INSTANCE);
|
| - var initializeEmptyInstanceAssignment = js('''
|
| - # = function(name, o, fields) {
|
| - #[name].apply(o, fields);
|
| - return o;
|
| - }''', [ initializeEmptyInstanceAccess, allClassesAccess ]);
|
| -
|
| - result.addAll([createIsolateAssignment,
|
| - classIdExtractorAssignment,
|
| - classFieldsExtractorAssignment,
|
| - instanceFromClassIdAssignment,
|
| - initializeEmptyInstanceAssignment]);
|
| - }
|
| -
|
| - return result;
|
| - }
|
| -
|
| - /** Needs defineClass to be defined. */
|
| - jsAst.Expression buildInheritFrom() {
|
| - jsAst.Expression result = js(r"""
|
| - // If the browser supports changing the prototype via __proto__, we make
|
| - // use of that feature. Otherwise, we copy the properties into a new
|
| - // constructor.
|
| - supportsDirectProtoAccess ?
|
| - function(constructor, superConstructor) {
|
| - var prototype = constructor.prototype;
|
| - prototype.__proto__ = superConstructor.prototype;
|
| - // Use a function for `true` here, as functions are stored in the
|
| - // hidden class and not as properties in the object.
|
| - prototype.constructor = constructor;
|
| - prototype[#operatorIsPrefix + constructor.name] = constructor;
|
| - return convertToFastObject(prototype);
|
| - } :
|
| - function() {
|
| - function tmp() {}
|
| - return function (constructor, superConstructor) {
|
| - tmp.prototype = superConstructor.prototype;
|
| - var object = new tmp();
|
| - convertToSlowObject(object);
|
| - var properties = constructor.prototype;
|
| - var members = Object.keys(properties);
|
| - for (var i = 0; i < members.length; i++) {
|
| - var member = members[i];
|
| - object[member] = properties[member];
|
| - }
|
| - // Use a function for `true` here, as functions are stored in the
|
| - // hidden class and not as properties in the object.
|
| - object[#operatorIsPrefix + constructor.name] = constructor;
|
| - object.constructor = constructor;
|
| - constructor.prototype = object;
|
| - return object;
|
| - };
|
| - }()
|
| - """, { 'operatorIsPrefix' : js.string(namer.operatorIsPrefix)});
|
| - if (compiler.hasIncrementalSupport) {
|
| - result = js(
|
| - r'#.inheritFrom = #', [namer.accessIncrementalHelper, result]);
|
| - }
|
| - return js(r'var inheritFrom = #', [result]);
|
| + jsAst.Statement buildNativeInfoHandler(
|
| + jsAst.Expression infoAccess,
|
| + jsAst.Expression constructorAccess,
|
| + jsAst.Expression subclassReadGenerator(jsAst.Expression subclass),
|
| + jsAst.Expression interceptorsByTagAccess,
|
| + jsAst.Expression leafTagsAccess) {
|
| + return nativeEmitter.buildNativeInfoHandler(infoAccess, constructorAccess,
|
| + subclassReadGenerator,
|
| + interceptorsByTagAccess,
|
| + leafTagsAccess);
|
| }
|
|
|
| - jsAst.Statement buildFinishClass(bool needsNativeSupport) {
|
| - String specProperty = '"${namer.nativeSpecProperty}"'; // "%"
|
| -
|
| - jsAst.Expression finishedClassesAccess =
|
| - generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES);
|
| -
|
| - jsAst.Expression nativeInfoAccess = js('prototype[$specProperty]', []);
|
| - jsAst.Expression constructorAccess = js('constructor', []);
|
| - Function subclassReadGenerator =
|
| - (jsAst.Expression subclass) => js('allClasses[#]', subclass);
|
| - jsAst.Expression interceptorsByTagAccess =
|
| - generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG);
|
| - jsAst.Expression leafTagsAccess =
|
| - generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS);
|
| - jsAst.Statement nativeInfoHandler = nativeEmitter.buildNativeInfoHandler(
|
| - nativeInfoAccess,
|
| - constructorAccess,
|
| - subclassReadGenerator,
|
| - interceptorsByTagAccess,
|
| - leafTagsAccess);
|
| -
|
| - return js.statement('''
|
| - {
|
| - var finishedClasses = #finishedClassesAccess;
|
| -
|
| - function finishClass(cls) {
|
| -
|
| - if (finishedClasses[cls]) return;
|
| - finishedClasses[cls] = true;
|
| -
|
| - var superclass = processedClasses.pending[cls];
|
| -
|
| - if (#needsMixinSupport) {
|
| - if (superclass && superclass.indexOf("+") > 0) {
|
| - var s = superclass.split("+");
|
| - superclass = s[0];
|
| - var mixinClass = s[1];
|
| - finishClass(mixinClass);
|
| - var mixin = allClasses[mixinClass];
|
| - var mixinPrototype = mixin.prototype;
|
| - var clsPrototype = allClasses[cls].prototype;
|
| -
|
| - var properties = Object.keys(mixinPrototype);
|
| - for (var i = 0; i < properties.length; i++) {
|
| - var d = properties[i];
|
| - if (!hasOwnProperty.call(clsPrototype, d))
|
| - clsPrototype[d] = mixinPrototype[d];
|
| - }
|
| - }
|
| - }
|
| -
|
| - // The superclass is only false (empty string) for the Dart Object
|
| - // class. The minifier together with noSuchMethod can put methods on
|
| - // the Object.prototype object, and they show through here, so we check
|
| - // that we have a string.
|
| - if (!superclass || typeof superclass != "string") {
|
| - // Inlined special case of InheritFrom here for performance reasons.
|
| - // Fix up the the Dart Object class' prototype.
|
| - var constructor = allClasses[cls];
|
| - var prototype = constructor.prototype;
|
| - prototype.constructor = constructor;
|
| - prototype.#isObject = constructor;
|
| - prototype.#deferredAction = #markerFun;
|
| - return;
|
| - }
|
| - finishClass(superclass);
|
| - var superConstructor = allClasses[superclass];
|
| -
|
| - if (!superConstructor) {
|
| - superConstructor = existingIsolateProperties[superclass];
|
| - }
|
| -
|
| - var constructor = allClasses[cls];
|
| - var prototype = inheritFrom(constructor, superConstructor);
|
| -
|
| - if (#needsNativeSupport) {
|
| - if (Object.prototype.hasOwnProperty.call(prototype, $specProperty)) {
|
| - #nativeInfoHandler;
|
| - // As native classes can come into existence without a constructor
|
| - // call, we have to ensure that the class has been fully
|
| - // initialized.
|
| - if (constructor.prototype.#deferredAction)
|
| - finishAddStubsHelper(constructor.prototype);
|
| - }
|
| - }
|
| - // Interceptors (or rather their prototypes) are also used without
|
| - // first instantiating them first.
|
| - if (prototype.#isInterceptorClass &&
|
| - constructor.prototype.#deferredAction) {
|
| - finishAddStubsHelper(constructor.prototype);
|
| - }
|
| - }
|
| - }''', {'deferredAction': namer.deferredAction,
|
| - 'finishedClassesAccess': finishedClassesAccess,
|
| - 'markerFun': markerFun,
|
| - 'needsMixinSupport': needsMixinSupport,
|
| - 'needsNativeSupport': needsNativeSupport,
|
| - 'nativeInfoHandler': nativeInfoHandler,
|
| - 'isInterceptorClass': namer.operatorIs(backend.jsInterceptorClass),
|
| - 'isObject' : namer.operatorIs(compiler.objectClass) });
|
| + jsAst.ObjectInitializer generateInterceptedNamesSet() {
|
| + return interceptorEmitter.generateInterceptedNamesSet();
|
| }
|
|
|
| void emitFinishIsolateConstructorInvocation(CodeOutput output) {
|
| @@ -1500,8 +1176,8 @@ class OldEmitter implements Emitter {
|
| mainOutput.add(
|
| '${globalsHolder}.${namer.isolateName}$_=$_${namer.isolateName}$N'
|
| '${globalsHolder}.$initName$_=${_}$initName$N'
|
| - '${globalsHolder}.$parseReflectionDataName$_=$_'
|
| - '$parseReflectionDataName$N');
|
| + '${globalsHolder}.$setupProgramName$_=$_'
|
| + '$setupProgramName$N');
|
| }
|
| mainOutput.add('init()$N$n');
|
| mainOutput.add('$isolateProperties$_=$_$isolatePropertiesName$N');
|
| @@ -1543,7 +1219,7 @@ class OldEmitter implements Emitter {
|
| bool needsNativeSupport = program.needsNativeSupport;
|
| mainOutput.addBuffer(
|
| jsAst.prettyPrint(
|
| - getReflectionDataParser(this, backend, needsNativeSupport),
|
| + buildSetupProgram(program, compiler, backend, namer, this),
|
| compiler));
|
|
|
| // The argument to reflectionDataParser is assigned to a temporary 'dart'
|
| @@ -1564,7 +1240,7 @@ class OldEmitter implements Emitter {
|
| mainOutput.add(N);
|
| }
|
|
|
| - mainOutput.add('$parseReflectionDataName(dart)$N');
|
| + mainOutput.add('$setupProgramName(dart)$N');
|
|
|
| interceptorEmitter.emitGetInterceptorMethods(mainOutput);
|
| interceptorEmitter.emitOneShotInterceptors(mainOutput);
|
| @@ -1996,8 +1672,8 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
| }
|
| output
|
| ..add('var init$_=$_${globalsHolder}.init$N')
|
| - ..add('var $parseReflectionDataName$_=$_'
|
| - '$globalsHolder.$parseReflectionDataName$N')
|
| + ..add('var $setupProgramName$_=$_'
|
| + '$globalsHolder.$setupProgramName$N')
|
| ..add('var ${namer.isolateName}$_=$_'
|
| '${globalsHolder}.${namer.isolateName}$N');
|
| if (libraryDescriptorBuffer != null) {
|
| @@ -2025,7 +1701,7 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
| allowVariableMinification: false));
|
| output.add(N);
|
| }
|
| - output.add('$parseReflectionDataName(dart)$N');
|
| + output.add('$setupProgramName(dart)$N');
|
| }
|
|
|
| // Set the currentIsolate variable to the current isolate (which is
|
|
|