| Index: pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart
|
| diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart
|
| deleted file mode 100644
|
| index a1d3610313a000087529643d0c114996f2b51616..0000000000000000000000000000000000000000
|
| --- a/pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart
|
| +++ /dev/null
|
| @@ -1,409 +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;
|
| -
|
| -// TODO(ahe): This code should be integrated in CodeEmitterTask.finishClasses.
|
| -jsAst.Expression getReflectionDataParser(String classesCollector,
|
| - JavaScriptBackend backend) {
|
| - Namer namer = backend.namer;
|
| - Compiler compiler = backend.compiler;
|
| - CodeEmitterTask emitter = backend.emitter;
|
| -
|
| - String metadataField = '"${namer.metadataField}"';
|
| - String reflectableField = namer.reflectableField;
|
| -
|
| - // TODO(ahe): Move this string constants to namer.
|
| - String reflectionInfoField = r'$reflectionInfo';
|
| - String reflectionNameField = r'$reflectionName';
|
| - String metadataIndexField = r'$metadataIndex';
|
| -
|
| - String defaultValuesField = namer.defaultValuesField;
|
| - String methodsWithOptionalArgumentsField =
|
| - namer.methodsWithOptionalArgumentsField;
|
| -
|
| - String unmangledNameIndex = backend.mustRetainMetadata
|
| - ? ' 3 * optionalParameterCount + 2 * requiredParameterCount + 3'
|
| - : ' 2 * optionalParameterCount + requiredParameterCount + 3';
|
| -
|
| - 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.Statement header = js.statement('''
|
| -// [map] returns an object literal that V8 shouldn not try to optimize with a
|
| -// hidden class. This prevents a potential performance problem where V8 tries
|
| -// to build a hidden class for an object used as a hashMap.
|
| -// It requires fewer characters to declare a variable as a parameter than
|
| -// with `var`.
|
| - function map(x){x=Object.create(null);x.x=0;delete x.x;return x}
|
| -''');
|
| -
|
| - jsAst.Statement processStatics = js.statement('''
|
| - function processStatics(descriptor) {
|
| - for (var property in descriptor) {
|
| - if (!hasOwnProperty.call(descriptor, property)) continue;
|
| - if (property === "${namer.classDescriptorProperty}") continue;
|
| - var element = descriptor[property];
|
| - var firstChar = property.substring(0, 1);
|
| - var previousProperty;
|
| - if (firstChar === "+") {
|
| - mangledGlobalNames[previousProperty] = property.substring(1);
|
| - var flag = descriptor[property];
|
| - if (flag > 0)
|
| - descriptor[previousProperty].$reflectableField = flag;
|
| - if (element && element.length)
|
| - #[previousProperty] = element; // embedded typeInformation.
|
| - } else if (firstChar === "@") {
|
| - property = property.substring(1);
|
| - ${namer.currentIsolate}[property][$metadataField] = element;
|
| - } else if (firstChar === "*") {
|
| - 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);
|
| - #[property] = element; // embedded globalFunctions.
|
| - } else if (element.constructor === Array) {
|
| - addStubs(globalObject, element, property,
|
| - true, descriptor, functions);
|
| - } else {
|
| - previousProperty = property;
|
| - var newDesc = {};
|
| - var previousProp;
|
| - for (var prop in element) {
|
| - if (!hasOwnProperty.call(element, prop)) continue;
|
| - firstChar = prop.substring(0, 1);
|
| - if (prop === "static") {
|
| - processStatics(#[property] = element[prop]); // embedded statics.
|
| - } else if (firstChar === "+") {
|
| - mangledNames[previousProp] = prop.substring(1);
|
| - var flag = element[prop];
|
| - if (flag > 0)
|
| - element[previousProp].$reflectableField = flag;
|
| - } else if (firstChar === "@" && prop !== "@") {
|
| - newDesc[prop.substring(1)][$metadataField] = element[prop];
|
| - } else if (firstChar === "*") {
|
| - newDesc[previousProp].$defaultValuesField = element[prop];
|
| - var optionalMethods = newDesc.$methodsWithOptionalArgumentsField;
|
| - if (!optionalMethods) {
|
| - newDesc.$methodsWithOptionalArgumentsField = optionalMethods={}
|
| - }
|
| - optionalMethods[prop] = previousProp;
|
| - } else {
|
| - var elem = element[prop];
|
| - if (prop !== "${namer.classDescriptorProperty}" &&
|
| - elem != null &&
|
| - elem.constructor === Array &&
|
| - prop !== "<>") {
|
| - addStubs(newDesc, elem, prop, false, element, []);
|
| - } else {
|
| - newDesc[previousProp = prop] = elem;
|
| - }
|
| - }
|
| - }
|
| - $classesCollector[property] = [globalObject, newDesc];
|
| - classes.push(property);
|
| - }
|
| - }
|
| - }
|
| -''', [typeInformationAccess, globalFunctionsAccess, staticsAccess]);
|
| -
|
| -
|
| - /**
|
| - * See [dart2js.js_emitter.ContainerBuilder.addMemberMethod] for format of
|
| - * [array].
|
| - */
|
| - jsAst.Statement addStubs = js.statement('''
|
| - function addStubs(descriptor, array, name, isStatic,
|
| - originalDescriptor, functions) {
|
| - var f, funcs =
|
| - [originalDescriptor[name] =
|
| - descriptor[name] = f = ${readFunction("array", "$FUNCTION_INDEX")}];
|
| - f.\$stubName = name;
|
| - functions.push(name);
|
| - for (var index = $FUNCTION_INDEX; 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) {
|
| - originalDescriptor[f.\$stubName] = descriptor[f.\$stubName] = f;
|
| - functions.push(f.\$stubName);
|
| - }
|
| - }
|
| - for (var i = 0; i < funcs.length; index++, i++) {
|
| - funcs[i].\$callName = ${readString("array", "index + 1")};
|
| - }
|
| - 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;
|
| - var isReflectable = array.length > unmangledNameIndex;
|
| -
|
| - if (getterStubName) {
|
| - f = tearOff(funcs, array, isStatic, name, isIntercepted);
|
| - descriptor[name].\$getter = f;
|
| - f.\$getterStub = true;
|
| - // Used to create an isolate using spawnFunction.
|
| - if (isStatic) #[name] = f; // embedded globalFunctions.
|
| - originalDescriptor[getterStubName] = descriptor[getterStubName] = f;
|
| - funcs.push(f);
|
| - if (getterStubName) functions.push(getterStubName);
|
| - f.\$stubName = getterStubName;
|
| - f.\$callName = null;
|
| - if (isIntercepted) #[getterStubName] = true; // embedded interceptedNames.
|
| - }
|
| - if (isReflectable) {
|
| - for (var i = 0; i < funcs.length; i++) {
|
| - funcs[i].$reflectableField = 1;
|
| - funcs[i].$reflectionInfoField = array;
|
| - }
|
| - var mangledNames = isStatic ? # : #; // embedded 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) descriptor[unmangledName + "*"] = funcs[0];
|
| - }
|
| - }
|
| -''', [globalFunctionsAccess, interceptedNamesAccess,
|
| - mangledGlobalNamesAccess, mangledNamesAccess]);
|
| -
|
| - List<jsAst.Statement> tearOffCode = buildTearOffCode(backend);
|
| -
|
| - jsAst.Statement init = js.statement('''{
|
| - var functionCounter = 0;
|
| - var tearOffGetter = (typeof dart_precompiled == "function")
|
| - ? tearOffGetterCsp : tearOffGetterNoCsp;
|
| - if (!#) # = []; // embedded libraries.
|
| - if (!#) # = map(); // embedded mangledNames.
|
| - if (!#) # = map(); // embedded mangledGlobalNames.
|
| - if (!#) # = map(); // embedded statics.
|
| - if (!#) # = map(); // embedded typeInformation.
|
| - if (!#) # = map(); // embedded globalFunctions.
|
| - if (!#) # = map(); // embedded interceptedNames.
|
| - var libraries = #; // embeded libraries.
|
| - var mangledNames = #; // embedded mangledNames.
|
| - var mangledGlobalNames = #; // embedded mangledGlobalNames.
|
| - var hasOwnProperty = Object.prototype.hasOwnProperty;
|
| - var length = reflectionData.length;
|
| - for (var i = 0; i < length; i++) {
|
| - var data = reflectionData[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);
|
| - libraries.push([name, uri, classes, functions, metadata, fields, isRoot,
|
| - globalObject]);
|
| - }
|
| -}''', [librariesAccess, librariesAccess,
|
| - mangledNamesAccess, mangledNamesAccess,
|
| - mangledGlobalNamesAccess, mangledGlobalNamesAccess,
|
| - staticsAccess, staticsAccess,
|
| - typeInformationAccess, typeInformationAccess,
|
| - globalFunctionsAccess, globalFunctionsAccess,
|
| - interceptedNamesAccess, interceptedNamesAccess,
|
| - librariesAccess,
|
| - mangledNamesAccess,
|
| - mangledGlobalNamesAccess]);
|
| -
|
| - return js('''
|
| -(function (reflectionData) {
|
| - "use strict";
|
| - #; // header
|
| - #; // processStatics
|
| - #; // addStubs
|
| - #; // tearOffCode
|
| - #; // init
|
| -})''', [header, processStatics, addStubs, tearOffCode, init]);
|
| -}
|
| -
|
| -
|
| -List<jsAst.Statement> buildTearOffCode(JavaScriptBackend backend) {
|
| - Namer namer = backend.namer;
|
| - Compiler compiler = backend.compiler;
|
| -
|
| - Element closureFromTearOff = backend.findHelper('closureFromTearOff');
|
| - String tearOffAccessText;
|
| - jsAst.Expression tearOffAccessExpression;
|
| - String tearOffGlobalObjectName;
|
| - String tearOffGlobalObject;
|
| - if (closureFromTearOff != null) {
|
| - // We need both the AST that references [closureFromTearOff] and a string
|
| - // for the NoCsp version that constructs a function.
|
| - tearOffAccessExpression = namer.elementAccess(closureFromTearOff);
|
| - tearOffAccessText =
|
| - jsAst.prettyPrint(tearOffAccessExpression, compiler).getText();
|
| - tearOffGlobalObjectName = tearOffGlobalObject =
|
| - namer.globalObjectFor(closureFromTearOff);
|
| - } else {
|
| - // Default values for mocked-up test libraries.
|
| - tearOffAccessText =
|
| - r'''function() { throw 'Helper \'closureFromTearOff\' missing.' }''';
|
| - tearOffAccessExpression = js(tearOffAccessText);
|
| - tearOffGlobalObjectName = 'MissingHelperFunction';
|
| - tearOffGlobalObject = '($tearOffAccessText())';
|
| - }
|
| -
|
| - // This template is uncached because it is constructed from code fragments
|
| - // that can change from compilation to compilation. Some of these could be
|
| - // avoided, except for the string literals that contain the compiled access
|
| - // path to 'closureFromTearOff'.
|
| - jsAst.Statement tearOffGetterNoCsp = js.uncachedStatementTemplate('''
|
| - function tearOffGetterNoCsp(funcs, reflectionInfo, name, isIntercepted) {
|
| - return isIntercepted
|
| - ? new Function("funcs", "reflectionInfo", "name",
|
| - "$tearOffGlobalObjectName", "c",
|
| - "return function tearOff_" + name + (functionCounter++)+ "(x) {" +
|
| - "if (c === null) c = $tearOffAccessText(" +
|
| - "this, funcs, reflectionInfo, false, [x], name);" +
|
| - "return new c(this, funcs[0], x, name);" +
|
| - "}")(funcs, reflectionInfo, name, $tearOffGlobalObject, null)
|
| - : new Function("funcs", "reflectionInfo", "name",
|
| - "$tearOffGlobalObjectName", "c",
|
| - "return function tearOff_" + name + (functionCounter++)+ "() {" +
|
| - "if (c === null) c = $tearOffAccessText(" +
|
| - "this, funcs, reflectionInfo, false, [], name);" +
|
| - "return new c(this, funcs[0], null, name);" +
|
| - "}")(funcs, reflectionInfo, name, $tearOffGlobalObject, null);
|
| - }''').instantiate([]);
|
| -
|
| - jsAst.Statement tearOffGetterCsp = js.statement('''
|
| - function tearOffGetterCsp(funcs, reflectionInfo, name, isIntercepted) {
|
| - var cache = null;
|
| - return isIntercepted
|
| - ? function(x) {
|
| - if (cache === null) cache = #(
|
| - this, funcs, reflectionInfo, false, [x], name);
|
| - return new cache(this, funcs[0], x, name);
|
| - }
|
| - : function() {
|
| - if (cache === null) cache = #(
|
| - this, funcs, reflectionInfo, false, [], name);
|
| - return new cache(this, funcs[0], null, name);
|
| - };
|
| - }''', [tearOffAccessExpression, tearOffAccessExpression]);
|
| -
|
| - jsAst.Statement tearOff = js.statement('''
|
| - function tearOff(funcs, reflectionInfo, isStatic, name, isIntercepted) {
|
| - var cache;
|
| - return isStatic
|
| - ? function() {
|
| - if (cache === void 0) cache = #(
|
| - this, funcs, reflectionInfo, true, [], name).prototype;
|
| - return cache;
|
| - }
|
| - : tearOffGetter(funcs, reflectionInfo, name, isIntercepted);
|
| - }''', tearOffAccessExpression);
|
| -
|
| - return <jsAst.Statement>[tearOffGetterNoCsp, tearOffGetterCsp, tearOff];
|
| -}
|
| -
|
| -
|
| -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 readFunction(String array, String index) {
|
| - return readChecked(
|
| - array, index, 'result != null && typeof result != "function"',
|
| - 'function');
|
| -}
|
| -
|
| -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;
|
| -})()''';
|
| -}
|
|
|