Index: pkg/compiler/lib/src/js_emitter/old_emitter/setup_program_builder.dart |
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/setup_program_builder.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/setup_program_builder.dart |
deleted file mode 100644 |
index 115ec4fef9eeb1c0b53c6eb916aa9a59f471ea3e..0000000000000000000000000000000000000000 |
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/setup_program_builder.dart |
+++ /dev/null |
@@ -1,855 +0,0 @@ |
-// Copyright (c) 2013, 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. |
- |
-part of dart2js.js_emitter; |
- |
-// TODO(ahe): Share these with js_helper.dart. |
-const FUNCTION_INDEX = 0; |
-const NAME_INDEX = 1; |
-const CALL_NAME_INDEX = 2; |
-const REQUIRED_PARAMETER_INDEX = 3; |
-const OPTIONAL_PARAMETER_INDEX = 4; |
-const DEFAULT_ARGUMENTS_INDEX = 5; |
- |
-const bool VALIDATE_DATA = false; |
- |
-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); |
- |
-const String setupProgramName ='setupProgram'; |
-// TODO(floitsch): make sure this property can't clash with anything. It's |
-// unlikely since it lives on types, but still. |
-const String typeNameProperty = r'builtin$cls'; |
- |
-jsAst.Statement buildSetupProgram(Program program, Compiler compiler, |
- JavaScriptBackend backend, |
- Namer namer, |
- OldEmitter emitter) { |
- |
- jsAst.Expression typeInformationAccess = |
- emitter.generateEmbeddedGlobalAccess(embeddedNames.TYPE_INFORMATION); |
- jsAst.Expression globalFunctionsAccess = |
- emitter.generateEmbeddedGlobalAccess(embeddedNames.GLOBAL_FUNCTIONS); |
- jsAst.Expression staticsAccess = |
- emitter.generateEmbeddedGlobalAccess(embeddedNames.STATICS); |
- jsAst.Expression interceptedNamesAccess = |
- emitter.generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTED_NAMES); |
- jsAst.Expression mangledGlobalNamesAccess = |
- emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); |
- jsAst.Expression mangledNamesAccess = |
- emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES); |
- jsAst.Expression librariesAccess = |
- emitter.generateEmbeddedGlobalAccess(embeddedNames.LIBRARIES); |
- jsAst.Expression typesAccess = |
- emitter.generateEmbeddedGlobalAccess(embeddedNames.TYPES); |
- jsAst.Expression createNewIsolateFunctionAccess = |
- emitter.generateEmbeddedGlobalAccess(embeddedNames.CREATE_NEW_ISOLATE); |
- jsAst.Expression classIdExtractorAccess = |
- emitter.generateEmbeddedGlobalAccess(embeddedNames.CLASS_ID_EXTRACTOR); |
- jsAst.Expression allClassesAccess = |
- emitter.generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); |
- jsAst.Expression precompiledAccess = |
- emitter.generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED); |
- jsAst.Expression finishedClassesAccess = |
- emitter.generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); |
- jsAst.Expression interceptorsByTagAccess = |
- emitter.generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); |
- jsAst.Expression leafTagsAccess = |
- emitter.generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); |
- jsAst.Expression initializeEmptyInstanceAccess = |
- emitter.generateEmbeddedGlobalAccess( |
- embeddedNames.INITIALIZE_EMPTY_INSTANCE); |
- jsAst.Expression classFieldsExtractorAccess = |
- emitter.generateEmbeddedGlobalAccess( |
- embeddedNames.CLASS_FIELDS_EXTRACTOR); |
- jsAst.Expression instanceFromClassIdAccess = |
- emitter.generateEmbeddedGlobalAccess( |
- embeddedNames.INSTANCE_FROM_CLASS_ID); |
- |
- String reflectableField = namer.reflectableField; |
- String reflectionInfoField = namer.reflectionInfoField; |
- String reflectionNameField = namer.reflectionNameField; |
- String metadataIndexField = namer.metadataIndexField; |
- String defaultValuesField = namer.defaultValuesField; |
- String methodsWithOptionalArgumentsField = |
- namer.methodsWithOptionalArgumentsField; |
- String unmangledNameIndex = backend.mustRetainMetadata |
- ? ' 3 * optionalParameterCount + 2 * requiredParameterCount + 3' |
- : ' 2 * optionalParameterCount + requiredParameterCount + 3'; |
- String receiverParamName = compiler.enableMinification ? "r" : "receiver"; |
- String valueParamName = compiler.enableMinification ? "v" : "value"; |
- String space = compiler.enableMinification ? "" : " "; |
- String _ = space; |
- |
- String specProperty = '"${namer.nativeSpecProperty}"'; // "%" |
- jsAst.Expression nativeInfoAccess = js('prototype[$specProperty]', []); |
- jsAst.Expression constructorAccess = js('constructor', []); |
- Function subclassReadGenerator = |
- (jsAst.Expression subclass) => js('allClasses[#]', subclass); |
- jsAst.Statement nativeInfoHandler = emitter. |
- buildNativeInfoHandler(nativeInfoAccess, constructorAccess, |
- subclassReadGenerator, interceptorsByTagAccess, |
- leafTagsAccess); |
- |
- Map<String, dynamic> holes = |
- {'needsClassSupport': emitter.needsClassSupport, |
- 'libraries': librariesAccess, |
- 'mangledNames': mangledNamesAccess, |
- 'mangledGlobalNames': mangledGlobalNamesAccess, |
- 'statics': staticsAccess, |
- 'typeInformation': typeInformationAccess, |
- 'globalFunctions': globalFunctionsAccess, |
- 'enabledInvokeOn': compiler.enabledInvokeOn, |
- 'interceptedNames': interceptedNamesAccess, |
- 'interceptedNamesSet': emitter.generateInterceptedNamesSet(), |
- 'notInCspMode': !compiler.useContentSecurityPolicy, |
- 'inCspMode': compiler.useContentSecurityPolicy, |
- 'deferredAction': namer.deferredAction, |
- 'hasIsolateSupport': program.hasIsolateSupport, |
- 'fieldNamesProperty': js.string(OldEmitter.FIELD_NAMES_PROPERTY_NAME), |
- 'hasIncrementalSupport': compiler.hasIncrementalSupport, |
- 'incrementalHelper': namer.accessIncrementalHelper, |
- 'createNewIsolateFunction': createNewIsolateFunctionAccess, |
- 'isolateName': namer.isolateName, |
- 'classIdExtractor': classIdExtractorAccess, |
- 'classFieldsExtractor': classFieldsExtractorAccess, |
- 'instanceFromClassId': instanceFromClassIdAccess, |
- 'initializeEmptyInstance': initializeEmptyInstanceAccess, |
- 'allClasses': allClassesAccess, |
- 'debugFastObjects': DEBUG_FAST_OBJECTS, |
- 'isTreeShakingDisabled': backend.isTreeShakingDisabled, |
- 'precompiled': precompiledAccess, |
- 'finishedClassesAccess': finishedClassesAccess, |
- 'needsMixinSupport': emitter.needsMixinSupport, |
- 'needsNativeSupport': program.needsNativeSupport, |
- 'isInterceptorClass': namer.operatorIs(backend.jsInterceptorClass), |
- 'isObject' : namer.operatorIs(compiler.objectClass), |
- 'specProperty': js.string(namer.nativeSpecProperty), |
- 'trivialNsmHandlers': emitter.buildTrivialNsmHandlers(), |
- 'hasRetainedMetadata': backend.hasRetainedMetadata, |
- 'types': typesAccess, |
- 'objectClassName': js.quoteName( |
- namer.runtimeTypeName(compiler.objectClass)), |
- 'needsStructuredMemberInfo': emitter.needsStructuredMemberInfo, |
- 'usesMangledNames': |
- compiler.mirrorsLibrary != null || compiler.enabledFunctionApply, |
- 'tearOffCode': buildTearOffCode(backend), |
- 'nativeInfoHandler': nativeInfoHandler, |
- 'operatorIsPrefix' : js.string(namer.operatorIsPrefix), |
- 'deferredActionString': js.string(namer.deferredAction)}; |
- |
- String skeleton = ''' |
-function $setupProgramName(programData, typesOffset) { |
- "use strict"; |
- if (#needsClassSupport) { |
- |
- 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; |
- } |
- |
- // 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; |
- // }, |
- // }); |
- function defineClass(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." + #deferredActionString + "();"; |
- } |
- str += ") {\\n" + body + "}\\n"; |
- str += name + ".$typeNameProperty=\\"" + 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; |
- } |
- |
- if (#hasIncrementalSupport) { |
- #incrementalHelper.defineClass = defineClass; |
- } |
- |
- if (#hasIsolateSupport) { |
- #createNewIsolateFunction = function() { return new #isolateName(); }; |
- |
- #classIdExtractor = function(o) { return o.constructor.name; }; |
- |
- #classFieldsExtractor = 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; |
- }; |
- |
- #instanceFromClassId = function(name) { return new #allClasses[name](); }; |
- |
- #initializeEmptyInstance = function(name, o, fields) { |
- #allClasses[name].apply(o, fields); |
- return o; // |
- } |
- } |
- |
- // If the browser supports changing the prototype via __proto__, we make |
- // use of that feature. Otherwise, we copy the properties into a new |
- // constructor. |
- var inheritFrom = 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; |
- }; |
- }(); |
- |
- if (#hasIncrementalSupport) { |
- #incrementalHelper.inheritFrom = inheritFrom; |
- } |
- |
- // Class descriptions are collected in a JS object. |
- // 'finishClasses' takes all collected descriptions and sets up |
- // the prototype. |
- // Once set up, the constructors prototype field satisfy: |
- // - it contains all (local) members. |
- // - its internal prototype (__proto__) points to the superclass' |
- // prototype field. |
- // - the prototype's constructor field points to the JavaScript |
- // constructor. |
- // For engines where we have access to the '__proto__' we can manipulate |
- // the object literal directly. For other engines we have to create a new |
- // object and copy over the members. |
- function finishClasses(processedClasses) { |
- if (#debugFastObjects) |
- print("Number of classes: " + |
- Object.getOwnPropertyNames(processedClasses.collected).length); |
- |
- var allClasses = #allClasses; |
- |
- if (#inCspMode) { |
- var constructors = #precompiled(processedClasses.collected); |
- } |
- |
- if (#notInCspMode) { |
- processedClasses.combinedConstructorFunction += |
- "return [\\n" + processedClasses.constructorsList.join(",\\n ") + |
- "\\n]"; |
- var constructors = |
- new Function("\$collectedClasses", |
- processedClasses.combinedConstructorFunction) |
- (processedClasses.collected); |
- processedClasses.combinedConstructorFunction = null; |
- } |
- |
- for (var i = 0; i < constructors.length; i++) { |
- var constructor = constructors[i]; |
- var cls = constructor.name; |
- var desc = processedClasses.collected[cls]; |
- var globalObject = desc[0]; |
- desc = desc[1]; |
- if (#isTreeShakingDisabled) |
- constructor["${namer.metadataField}"] = desc; |
- allClasses[cls] = constructor; |
- globalObject[cls] = constructor; |
- } |
- constructors = null; |
- |
- 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 = function() {}; |
- return; |
- } |
- finishClass(superclass); |
- var superConstructor = allClasses[superclass]; |
- |
- if (!superConstructor) { |
- superConstructor = existingIsolateProperties[superclass]; |
- } |
- |
- var constructor = allClasses[cls]; |
- var prototype = inheritFrom(constructor, superConstructor); |
- |
- if (#needsMixinSupport) { |
- if (mixinPrototype) { |
- prototype.#deferredAction |
- = mixinDeferredActionHelper(mixinPrototype, prototype); |
- } |
- } |
- |
- 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. |
- prototype.#deferredAction(); |
- } |
- } |
- // Interceptors (or rather their prototypes) are also used without |
- // first instantiating them first. |
- if (prototype.#isInterceptorClass) { |
- prototype.#deferredAction(); |
- } |
- } |
- |
- #trivialNsmHandlers; |
- |
- var properties = Object.keys(processedClasses.pending); |
- for (var i = 0; i < properties.length; i++) finishClass(properties[i]); |
- } |
- |
- // Generic handler for deferred class setup. The handler updates the |
- // prototype that it is installed on (it traverses the prototype chain |
- // of [this] to find itself) and then removes itself. It recurses by |
- // calling deferred handling again, which terminates on Object due to |
- // the final handler. |
- function finishAddStubsHelper() { |
- var prototype = this; |
- // Find the actual prototype that this handler is installed on. |
- while (!prototype.hasOwnProperty(#deferredActionString)) { |
- prototype = prototype.__proto__; |
- } |
- delete prototype.#deferredAction; // Intended to make it slow, too. |
- var properties = Object.keys(prototype); |
- for (var index = 0; index < properties.length; index++) { |
- var property = properties[index]; |
- var firstChar = property.charCodeAt(0); |
- var elem; |
- // We have to filter out some special properties that are used for |
- // metadata in descriptors. Currently, we filter everything that |
- // starts with + or *. This has to stay in sync with the special |
- // properties that are used by processClassData below. |
- if (property !== "${namer.classDescriptorProperty}" && |
- property !== "$reflectableField" && |
- firstChar !== 43 && // 43 is aka "+". |
- firstChar !== 42 && // 42 is aka "*" |
- (elem = prototype[property]) != null && |
- elem.constructor === Array && |
- property !== "<>") { |
- addStubs(prototype, elem, property, false, []); |
- } |
- } |
- convertToFastObject(prototype); |
- prototype = prototype.__proto__; |
- // Call other handlers. |
- prototype.#deferredAction(); |
- } |
- |
- if (#needsMixinSupport) { |
- // Returns a deferred class setup handler that first invokes the |
- // handler on [mixinPrototype] and then resumes handling on |
- // [targetPrototype]. If [targetPrototype] already has a handler |
- // installed, the handler is preserved in the generated closure and |
- // thus can be safely overwritten. |
- function mixinDeferredActionHelper(mixinPrototype, targetPrototype) { |
- var chain; |
- if (targetPrototype.hasOwnProperty(#deferredActionString)) { |
- chain = targetPrototype.#deferredAction; |
- } |
- return function foo() { |
- var prototype = this; |
- // Find the actual prototype that this handler is installed on. |
- while (!prototype.hasOwnProperty(#deferredActionString)) { |
- prototype = prototype.__proto__; |
- } |
- if (chain) { |
- prototype.#deferredAction = chain; |
- } else { |
- delete prototype.#deferredAction; |
- convertToFastObject(prototype); |
- } |
- mixinPrototype.#deferredAction(); |
- prototype.#deferredAction(); |
- } |
- } |
- } |
- |
- function processClassData(cls, descriptor, processedClasses) { |
- descriptor = convertToSlowObject(descriptor); // Use a slow object. |
- var previousProperty; |
- var properties = Object.keys(descriptor); |
- var hasDeferredWork = false; |
- var shouldDeferWork = |
- supportsDirectProtoAccess && cls != #objectClassName; |
- for (var i = 0; i < properties.length; i++) { |
- var property = properties[i]; |
- var firstChar = property.charCodeAt(0); |
- if (property === "static") { |
- processStatics(#statics[cls] = descriptor.static, |
- processedClasses); |
- delete descriptor.static; |
- } else if (firstChar === 43) { // 43 is "+". |
- mangledNames[previousProperty] = property.substring(1); |
- var flag = descriptor[property]; |
- if (flag > 0) |
- descriptor[previousProperty].$reflectableField = flag; |
- } else if (firstChar === 42) { // 42 is "*" |
- descriptor[previousProperty].$defaultValuesField = |
- descriptor[property]; |
- var optionalMethods = descriptor.$methodsWithOptionalArgumentsField; |
- if (!optionalMethods) { |
- descriptor.$methodsWithOptionalArgumentsField = optionalMethods={} |
- } |
- optionalMethods[property] = previousProperty; |
- } else { |
- var elem = descriptor[property]; |
- if (property !== "${namer.classDescriptorProperty}" && |
- elem != null && |
- elem.constructor === Array && |
- property !== "<>") { |
- if (shouldDeferWork) { |
- hasDeferredWork = true; |
- } else { |
- addStubs(descriptor, elem, property, false, []); |
- } |
- } else { |
- previousProperty = property; |
- } |
- } |
- } |
- |
- if (hasDeferredWork) |
- descriptor.#deferredAction = finishAddStubsHelper; |
- |
- /* The 'fields' are either a constructor function or a |
- * string encoding fields, constructor and superclass. Gets the |
- * superclass and fields in the format |
- * 'Super;field1,field2' |
- * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor. |
- */ |
- var classData = descriptor["${namer.classDescriptorProperty}"], |
- split, supr, fields = classData; |
- |
- if (#hasRetainedMetadata) |
- if (typeof classData == "object" && |
- classData instanceof Array) { |
- classData = fields = classData[0]; |
- } |
- // ${ClassBuilder.fieldEncodingDescription}. |
- var s = fields.split(";"); |
- fields = s[1] ? s[1].split(",") : []; |
- supr = s[0]; |
- // ${ClassBuilder.functionTypeEncodingDescription}. |
- split = supr.split(":"); |
- if (split.length == 2) { |
- supr = split[0]; |
- var functionSignature = split[1]; |
- if (functionSignature) |
- descriptor.${namer.operatorSignature} = function(s) { |
- return function() { |
- return #types[s]; |
- }; |
- }(functionSignature); |
- } |
- |
- if (supr) processedClasses.pending[cls] = supr; |
- if (#notInCspMode) { |
- processedClasses.combinedConstructorFunction += |
- defineClass(cls, fields); |
- processedClasses.constructorsList.push(cls); |
- } |
- processedClasses.collected[cls] = [globalObject, descriptor]; |
- classes.push(cls); |
- } |
- } |
- |
- function processStatics(descriptor, processedClasses) { |
- var properties = Object.keys(descriptor); |
- for (var i = 0; i < properties.length; i++) { |
- var property = properties[i]; |
- if (property === "${namer.classDescriptorProperty}") continue; |
- var element = descriptor[property]; |
- var firstChar = property.charCodeAt(0); |
- var previousProperty; |
- if (firstChar === 43) { // 43 is "+". |
- mangledGlobalNames[previousProperty] = property.substring(1); |
- var flag = descriptor[property]; |
- if (flag > 0) |
- descriptor[previousProperty].$reflectableField = flag; |
- if (element && element.length) |
- #typeInformation[previousProperty] = element; |
- } else if (firstChar === 42) { // 42 is "*" |
- globalObject[previousProperty].$defaultValuesField = element; |
- var optionalMethods = descriptor.$methodsWithOptionalArgumentsField; |
- if (!optionalMethods) { |
- descriptor.$methodsWithOptionalArgumentsField = optionalMethods = {} |
- } |
- optionalMethods[property] = previousProperty; |
- } else if (typeof element === "function") { |
- globalObject[previousProperty = property] = element; |
- functions.push(property); |
- #globalFunctions[property] = element; |
- } else if (element.constructor === Array) { |
- if (#needsStructuredMemberInfo) { |
- addStubs(globalObject, element, property, true, functions); |
- } |
- } else { |
- // We will not enter this case if no classes are defined. |
- if (#needsClassSupport) { |
- previousProperty = property; |
- processClassData(property, element, processedClasses); |
- } |
- } |
- } |
- } |
- |
- if (#needsStructuredMemberInfo) { |
- |
- // See [dart2js.js_emitter.ContainerBuilder.addMemberMethod] for format of |
- // [array]. |
- |
- // Processes the stub declaration given by [array] and stores the results |
- // in the corresponding [prototype]. [name] is the property name in |
- // [prototype] that the stub declaration belongs to. |
- // If [isStatic] is true, the property being processed belongs to a static |
- // function and thus is stored as a global. In that case we also add all |
- // generated functions to the [functions] array, which is used by the |
- // mirrors system to enumerate all static functions of a library. For |
- // non-static functions we might still add some functions to [functions] but |
- // the information is thrown away at the call site. This is to avoid |
- // conditionals. |
- function addStubs(prototype, array, name, isStatic, functions) { |
- var index = $FUNCTION_INDEX, alias = array[index], f; |
- if (typeof alias == "string") { |
- f = array[++index]; |
- } else { |
- f = alias; |
- alias = name; |
- } |
- var funcs = [prototype[name] = prototype[alias] = f]; |
- f.\$stubName = name; |
- functions.push(name); |
- for (index++; index < array.length; index++) { |
- f = array[index]; |
- if (typeof f != "function") break; |
- if (!isStatic) { |
- f.\$stubName = ${readString("array", "++index")}; |
- } |
- funcs.push(f); |
- if (f.\$stubName) { |
- prototype[f.\$stubName] = f; |
- functions.push(f.\$stubName); |
- } |
- } |
- |
- for (var i = 0; i < funcs.length; index++, i++) { |
- funcs[i].\$callName = ${readString("array", "index")}; |
- } |
- var getterStubName = ${readString("array", "index")}; |
- array = array.slice(++index); |
- var requiredParameterInfo = ${readInt("array", "0")}; |
- var requiredParameterCount = requiredParameterInfo >> 1; |
- var isAccessor = (requiredParameterInfo & 1) === 1; |
- var isSetter = requiredParameterInfo === 3; |
- var isGetter = requiredParameterInfo === 1; |
- var optionalParameterInfo = ${readInt("array", "1")}; |
- var optionalParameterCount = optionalParameterInfo >> 1; |
- var optionalParametersAreNamed = (optionalParameterInfo & 1) === 1; |
- var isIntercepted = |
- requiredParameterCount + optionalParameterCount != funcs[0].length; |
- var functionTypeIndex = ${readFunctionType("array", "2")}; |
- if (typeof functionTypeIndex == "number") |
- ${readFunctionType("array", "2")} = functionTypeIndex + typesOffset; |
- var unmangledNameIndex = $unmangledNameIndex; |
- |
- if (getterStubName) { |
- f = tearOff(funcs, array, isStatic, name, isIntercepted); |
- prototype[name].\$getter = f; |
- f.\$getterStub = true; |
- // Used to create an isolate using spawnFunction. |
- if (isStatic) { |
- #globalFunctions[name] = f; |
- functions.push(getterStubName); |
- } |
- prototype[getterStubName] = f; |
- funcs.push(f); |
- f.\$stubName = getterStubName; |
- f.\$callName = null; |
- // Update the interceptedNames map (which only exists if `invokeOn` was |
- // enabled). |
- if (#enabledInvokeOn) |
- if (isIntercepted) #interceptedNames[getterStubName] = 1; |
- } |
- |
- if (#usesMangledNames) { |
- var isReflectable = array.length > unmangledNameIndex; |
- if (isReflectable) { |
- funcs[0].$reflectableField = 1; |
- funcs[0].$reflectionInfoField = array; |
- for (var i = 1; i < funcs.length; i++) { |
- funcs[i].$reflectableField = 2; |
- funcs[i].$reflectionInfoField = array; |
- } |
- var mangledNames = isStatic ? #mangledGlobalNames : #mangledNames; |
- var unmangledName = ${readString("array", "unmangledNameIndex")}; |
- // The function is either a getter, a setter, or a method. |
- // If it is a method, it might also have a tear-off closure. |
- // The unmangledName is the same as the getter-name. |
- var reflectionName = unmangledName; |
- if (getterStubName) mangledNames[getterStubName] = reflectionName; |
- if (isSetter) { |
- reflectionName += "="; |
- } else if (!isGetter) { |
- reflectionName += ":" + |
- (requiredParameterCount + optionalParameterCount); |
- } |
- mangledNames[name] = reflectionName; |
- funcs[0].$reflectionNameField = reflectionName; |
- funcs[0].$metadataIndexField = unmangledNameIndex + 1; |
- if (optionalParameterCount) prototype[unmangledName + "*"] = funcs[0]; |
- } |
- } |
- } |
- |
- #tearOffCode; |
- } |
- |
- if (#hasIncrementalSupport) { |
- #incrementalHelper.addStubs = addStubs; |
- } |
- |
- var functionCounter = 0; |
- if (!#libraries) #libraries = []; |
- if (!#mangledNames) #mangledNames = map(); |
- if (!#mangledGlobalNames) #mangledGlobalNames = map(); |
- if (!#statics) #statics = map(); |
- if (!#typeInformation) #typeInformation = map(); |
- if (!#globalFunctions) #globalFunctions = map(); |
- if (#enabledInvokeOn) |
- if (!#interceptedNames) #interceptedNames = #interceptedNamesSet; |
- var libraries = #libraries; |
- var mangledNames = #mangledNames; |
- var mangledGlobalNames = #mangledGlobalNames; |
- var hasOwnProperty = Object.prototype.hasOwnProperty; |
- var length = programData.length; |
- var processedClasses = map(); |
- processedClasses.collected = map(); |
- processedClasses.pending = map(); |
- if (#notInCspMode) { |
- processedClasses.constructorsList = []; |
- // For every class processed [processedClasses.combinedConstructorFunction] |
- // will be updated with the corresponding constructor function. |
- processedClasses.combinedConstructorFunction = |
- "function \$reflectable(fn){fn.$reflectableField=1;return fn};\\n"+ |
- "var \$desc;\\n"; |
- } |
- for (var i = 0; i < length; i++) { |
- var data = programData[i]; |
- |
-// [data] contains these elements: |
-// 0. The library name (not unique). |
-// 1. The library URI (unique). |
-// 2. A function returning the metadata associated with this library. |
-// 3. The global object to use for this library. |
-// 4. An object literal listing the members of the library. |
-// 5. This element is optional and if present it is true and signals that this |
-// library is the root library (see dart:mirrors IsolateMirror.rootLibrary). |
-// |
-// The entries of [data] are built in [assembleProgram] above. |
- |
- var name = data[0]; |
- var uri = data[1]; |
- var metadata = data[2]; |
- var globalObject = data[3]; |
- var descriptor = data[4]; |
- var isRoot = !!data[5]; |
- var fields = descriptor && descriptor["${namer.classDescriptorProperty}"]; |
- if (fields instanceof Array) fields = fields[0]; |
- var classes = []; |
- var functions = []; |
- processStatics(descriptor, processedClasses); |
- libraries.push([name, uri, classes, functions, metadata, fields, isRoot, |
- globalObject]); |
- } |
- if (#needsClassSupport) finishClasses(processedClasses); |
-}'''; |
- |
- // TODO(zarah): Remove empty else branches in output when if(#hole) is false. |
- return js.statement(skeleton, holes); |
-} |
- |
-String readString(String array, String index) { |
- return readChecked( |
- array, index, 'result != null && typeof result != "string"', 'string'); |
-} |
- |
-String readInt(String array, String index) { |
- return readChecked( |
- array, index, |
- 'result != null && (typeof result != "number" || (result|0) !== result)', |
- 'int'); |
-} |
- |
-String readFunctionType(String array, String index) { |
- return readChecked( |
- array, index, |
- 'result != null && ' |
- '(typeof result != "number" || (result|0) !== result) && ' |
- 'typeof result != "function"', |
- 'function or int'); |
-} |
- |
-String readChecked(String array, String index, String check, String type) { |
- if (!VALIDATE_DATA) return '$array[$index]'; |
- return ''' |
-(function() { |
- var result = $array[$index]; |
- if ($check) { |
- throw new Error( |
- name + ": expected value of type \'$type\' at index " + ($index) + |
- " but got " + (typeof result)); |
- } |
- return result; |
-})()'''; |
-} |