Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(888)

Unified Diff: pkg/compiler/lib/src/js_emitter/old_emitter/setup_program_builder.dart

Issue 1024523003: dart2js: rename and refactor reflection_data_parser. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
new file mode 100644
index 0000000000000000000000000000000000000000..86fdcd8d73a329f65e45f77e81d030ef919cc46c
--- /dev/null
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/setup_program_builder.dart
@@ -0,0 +1,811 @@
+// 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);
+
+String get setupProgramName => 'setupProgram';
+
+
+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,
+ 'markerFun': emitter.markerFun,
+ '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.string(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) {
+ "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 + ".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;
+ }
+
+ 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 = #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);
+ }
+ }
+
+ #trivialNsmHandlers;
+
+ var properties = Object.keys(processedClasses.pending);
+ for (var i = 0; i < properties.length; i++) finishClass(properties[i]);
+ }
+
+
+ // For convenience, this method can be called with a prototype as argument
+ // or, if it was bound to an object, by invoking it as a method. Therefore,
+ // if prototype is undefined, this is used as prototype.
+ function finishAddStubsHelper(prototype) {
+ var prototype = prototype || this;
+ var object;
+ while (prototype.#deferredAction != #markerFun) {
+ if (prototype.hasOwnProperty(#deferredActionString)) {
+ 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__;
+ }
+ }
+
+ 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 < array.length; index += 2) {
+ f = array[index + 1];
+ if (typeof f != "function") break;
+ f.\$stubName = ${readString("array", "index + 2")};
+ funcs.push(f);
+ if (f.\$stubName) {
+ prototype[f.\$stubName] = f;
+ functions.push(f.\$stubName);
+ }
+ }
+ index++;
+ 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")};
+ 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) {
+ for (var i = 0; i < funcs.length; i++) {
+ funcs[i].$reflectableField = 1;
+ 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;
+})()''';
+}
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698