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

Unified Diff: sdk/lib/_internal/compiler/implementation/js_emitter/old_emitter/emitter.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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
Index: sdk/lib/_internal/compiler/implementation/js_emitter/old_emitter/emitter.dart
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/old_emitter/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/old_emitter/emitter.dart
deleted file mode 100644
index 6c266153502120b97a67edcb207ad9877eaddfc2..0000000000000000000000000000000000000000
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/old_emitter/emitter.dart
+++ /dev/null
@@ -1,1998 +0,0 @@
-// Copyright (c) 2014, 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;
-
-
-class OldEmitter implements Emitter {
- final Compiler compiler;
- final CodeEmitterTask task;
-
- final ContainerBuilder containerBuilder = new ContainerBuilder();
- final ClassEmitter classEmitter = new ClassEmitter();
- final NsmEmitter nsmEmitter = new NsmEmitter();
- TypeTestEmitter get typeTestEmitter => task.typeTestEmitter;
- final InterceptorEmitter interceptorEmitter = new InterceptorEmitter();
- final MetadataEmitter metadataEmitter = new MetadataEmitter();
-
- final Set<ConstantValue> cachedEmittedConstants;
- final CodeBuffer cachedEmittedConstantsBuffer = new CodeBuffer();
- final Map<Element, ClassBuilder> cachedClassBuilders;
- final Set<Element> cachedElements;
-
- bool needsDefineClass = false;
- bool needsMixinSupport = false;
- bool needsLazyInitializer = false;
- final Namer namer;
- ConstantEmitter constantEmitter;
- NativeEmitter get nativeEmitter => task.nativeEmitter;
-
- // The full code that is written to each hunk part-file.
- Map<OutputUnit, CodeBuffer> outputBuffers = new Map<OutputUnit, CodeBuffer>();
- final CodeBuffer deferredConstants = new CodeBuffer();
-
- /** Shorter access to [isolatePropertiesName]. Both here in the code, as
- well as in the generated code. */
- String isolateProperties;
- String classesCollector;
- Set<ClassElement> get neededClasses => task.neededClasses;
- Map<OutputUnit, List<ClassElement>> get outputClassLists
- => task.outputClassLists;
- Map<OutputUnit, List<ConstantValue>> get outputConstantLists
- => task.outputConstantLists;
- List<ClassElement> get nativeClasses => task.nativeClasses;
- final Map<String, String> mangledFieldNames = <String, String>{};
- final Map<String, String> mangledGlobalFieldNames = <String, String>{};
- final Set<String> recordedMangledNames = new Set<String>();
-
- final Map<ClassElement, Map<String, jsAst.Expression>> additionalProperties =
- new Map<ClassElement, Map<String, jsAst.Expression>>();
-
- List<TypedefElement> get typedefsNeededForReflection =>
- task.typedefsNeededForReflection;
-
- JavaScriptBackend get backend => compiler.backend;
- TypeVariableHandler get typeVariableHandler => backend.typeVariableHandler;
-
- String get _ => space;
- String get space => compiler.enableMinification ? "" : " ";
- String get n => compiler.enableMinification ? "" : "\n";
- String get N => compiler.enableMinification ? "\n" : ";\n";
-
- CodeBuffer getBuffer(OutputUnit outputUnit) {
- return outputBuffers.putIfAbsent(outputUnit, () => new CodeBuffer());
- }
-
- CodeBuffer get mainBuffer {
- return getBuffer(compiler.deferredLoadTask.mainOutputUnit);
- }
-
- /**
- * List of expressions and statements that will be included in the
- * precompiled function.
- *
- * To save space, dart2js normally generates constructors and accessors
- * dynamically. This doesn't work in CSP mode, and may impact startup time
- * negatively. So dart2js will emit these functions to a separate file that
- * can be optionally included to support CSP mode or for faster startup.
- */
- Map<OutputUnit, List<jsAst.Node>> _cspPrecompiledFunctions =
- new Map<OutputUnit, List<jsAst.Node>>();
-
- Map<OutputUnit, List<jsAst.Expression>> _cspPrecompiledConstructorNames =
- new Map<OutputUnit, List<jsAst.Expression>>();
-
- /**
- * Accumulate properties for classes and libraries, describing their
- * static/top-level members.
- * Later, these members are emitted when the class or library is emitted.
- *
- * See [getElementDescriptor].
- */
- // TODO(ahe): Generate statics with their class, and store only libraries in
- // this map.
- final Map<Element, ClassBuilder> elementDescriptors =
- new Map<Element, ClassBuilder>();
-
- final bool generateSourceMap;
-
- OldEmitter(Compiler compiler, Namer namer, this.generateSourceMap, this.task)
- : this.compiler = compiler,
- this.namer = namer,
- cachedEmittedConstants = compiler.cacheStrategy.newSet(),
- cachedClassBuilders = compiler.cacheStrategy.newMap(),
- cachedElements = compiler.cacheStrategy.newSet() {
- constantEmitter =
- new ConstantEmitter(compiler, namer, makeConstantListTemplate);
- containerBuilder.emitter = this;
- classEmitter.emitter = this;
- nsmEmitter.emitter = this;
- interceptorEmitter.emitter = this;
- metadataEmitter.emitter = this;
- }
-
- List<jsAst.Node> cspPrecompiledFunctionFor(OutputUnit outputUnit) {
- return _cspPrecompiledFunctions.putIfAbsent(
- outputUnit,
- () => new List<jsAst.Node>());
- }
-
- List<jsAst.Expression> cspPrecompiledConstructorNamesFor(
- OutputUnit outputUnit) {
- return _cspPrecompiledConstructorNames.putIfAbsent(
- outputUnit,
- () => new List<jsAst.Expression>());
- }
-
- /// Erases the precompiled information for csp mode for all output units.
- /// Used by the incremental compiler.
- void clearCspPrecompiledNodes() {
- _cspPrecompiledFunctions.clear();
- _cspPrecompiledConstructorNames.clear();
- }
-
- void addComment(String comment, CodeBuffer buffer) {
- buffer.write(jsAst.prettyPrint(js.comment(comment), compiler));
- }
-
- jsAst.Expression constantReference(ConstantValue value) {
- return constantEmitter.reference(value);
- }
-
- jsAst.Expression constantInitializerExpression(ConstantValue value) {
- return constantEmitter.initializationExpression(value);
- }
-
- String get name => 'CodeEmitter';
-
- String get currentGenerateAccessorName
- => '${namer.currentIsolate}.\$generateAccessor';
- String get generateAccessorHolder
- => '$isolatePropertiesName.\$generateAccessor';
- String get finishClassesProperty
- => r'$finishClasses';
- String get finishClassesName
- => '${namer.isolateName}.$finishClassesProperty';
- String get finishIsolateConstructorName
- => '${namer.isolateName}.\$finishIsolateConstructor';
- String get isolatePropertiesName
- => '${namer.isolateName}.${namer.isolatePropertiesName}';
- String get lazyInitializerName
- => '${namer.isolateName}.\$lazy';
- String get initName => 'init';
- String get makeConstListProperty
- => namer.getMappedInstanceName('makeConstantList');
-
- /// For deferred loading we communicate the initializers via this global var.
- final String deferredInitializers = r"$dart_deferred_initializers";
-
- /// All the global state can be passed around with this variable.
- String get globalsHolder => namer.getMappedGlobalName("globalsHolder");
-
- jsAst.Expression generateEmbeddedGlobalAccess(String global) {
- return js(generateEmbeddedGlobalAccessString(global));
- }
-
- String generateEmbeddedGlobalAccessString(String global) {
- // TODO(floitsch): don't use 'init' as global embedder storage.
- return '$initName.$global';
- }
-
- 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 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;
- // },
- // });
-
- var defineClass = js('''function(name, cls, fields) {
- var accessors = [];
-
- var str = "function " + cls + "(";
- var body = "";
-
- for (var i = 0; i < fields.length; i++) {
- if(i != 0) str += ", ";
-
- var field = generateAccessor(fields[i], accessors, cls);
- var parameter = "parameter_" + field;
- str += parameter;
- body += ("this." + field + " = " + parameter + ";\\n");
- }
- str += ") {\\n" + body + "}\\n";
- str += cls + ".builtin\$cls=\\"" + name + "\\";\\n";
- str += "\$desc=\$collectedClasses." + cls + ";\\n";
- str += "if(\$desc instanceof Array) \$desc = \$desc[1];\\n";
- str += cls + ".prototype = \$desc;\\n";
- if (typeof defineClass.name != "string") {
- str += cls + ".name=\\"" + cls + "\\";\\n";
- }
- str += accessors.join("");
-
- return str;
- }''');
- // Declare a function called "generateAccessor". This is used in
- // defineClassFunction (it's a local declaration in init()).
- return [
- generateAccessorFunction,
- js('$generateAccessorHolder = generateAccessor'),
- new jsAst.FunctionDeclaration(
- new jsAst.VariableDeclaration('defineClass'), defineClass) ];
- }
-
- /** Needs defineClass to be defined. */
- List buildInheritFrom() {
- return [js(r'''
- var inheritFrom = function() {
- function tmp() {}
- var hasOwnProperty = Object.prototype.hasOwnProperty;
- return function (constructor, superConstructor) {
- tmp.prototype = superConstructor.prototype;
- var object = new tmp();
- var properties = constructor.prototype;
- for (var member in properties)
- if (hasOwnProperty.call(properties, member))
- object[member] = properties[member];
- object.constructor = constructor;
- constructor.prototype = object;
- return object;
- };
- }()
- ''')];
- }
-
- jsAst.Fun get finishClassesFunction {
- // 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.
-
- String reflectableField = namer.reflectableField;
- jsAst.Expression allClassesAccess =
- generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES);
- jsAst.Expression metadataAccess =
- generateEmbeddedGlobalAccess(embeddedNames.METADATA);
- jsAst.Expression interceptorsByTagAccess =
- generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG);
- jsAst.Expression leafTagsAccess =
- generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS);
-
- return js('''
- function(collectedClasses, isolateProperties, existingIsolateProperties) {
- var pendingClasses = Object.create(null);
- if (!#) # = Object.create(null); // embedded allClasses.
- var allClasses = #; // embedded allClasses;
-
- if (#) // DEBUG_FAST_OBJECTS
- print("Number of classes: " +
- Object.getOwnPropertyNames(\$\$).length);
-
- var hasOwnProperty = Object.prototype.hasOwnProperty;
-
- if (typeof dart_precompiled == "function") {
- var constructors = dart_precompiled(collectedClasses);
- } else {
- var combinedConstructorFunction =
- "function \$reflectable(fn){fn.$reflectableField=1;return fn};\\n"+
- "var \$desc;\\n";
- var constructorsList = [];
- }
-
- for (var cls in collectedClasses) {
- var desc = collectedClasses[cls];
- if (desc instanceof Array) desc = desc[1];
-
- /* The 'fields' are either a constructor function or a
- * string encoding fields, constructor and superclass. Get
- * the superclass and the fields in the format
- * '[name/]Super;field1,field2'
- * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor.
- * The 'name/' is optional and contains the name that should be used
- * when printing the runtime type string. It is used, for example,
- * to print the runtime type JSInt as 'int'.
- */
- var classData = desc["${namer.classDescriptorProperty}"],
- supr, name = cls, fields = classData;
- if (#) // backend.hasRetainedMetadata
- if (typeof classData == "object" &&
- classData instanceof Array) {
- classData = fields = classData[0];
- }
- if (typeof classData == "string") {
- var split = classData.split("/");
- if (split.length == 2) {
- name = split[0];
- fields = split[1];
- }
- }
-
- var s = fields.split(";");
- fields = s[1] == "" ? [] : s[1].split(",");
- supr = s[0];
- split = supr.split(":");
- if (split.length == 2) {
- supr = split[0];
- var functionSignature = split[1];
- if (functionSignature)
- desc.\$signature = (function(s) {
- return function(){ return #[s]; }; // embedded metadata.
- })(functionSignature);
- }
-
- if (#) // needsMixinSupport
- if (supr && supr.indexOf("+") > 0) {
- s = supr.split("+");
- supr = s[0];
- var mixin = collectedClasses[s[1]];
- if (mixin instanceof Array) mixin = mixin[1];
- for (var d in mixin) {
- if (hasOwnProperty.call(mixin, d) &&
- !hasOwnProperty.call(desc, d))
- desc[d] = mixin[d];
- }
- }
-
- if (typeof dart_precompiled != "function") {
- combinedConstructorFunction += defineClass(name, cls, fields);
- constructorsList.push(cls);
- }
- if (supr) pendingClasses[cls] = supr;
- }
-
- if (typeof dart_precompiled != "function") {
- combinedConstructorFunction +=
- "return [\\n " + constructorsList.join(",\\n ") + "\\n]";
- var constructors =
- new Function("\$collectedClasses", combinedConstructorFunction)
- (collectedClasses);
- combinedConstructorFunction = null;
- }
-
- for (var i = 0; i < constructors.length; i++) {
- var constructor = constructors[i];
- var cls = constructor.name;
- var desc = collectedClasses[cls];
- var globalObject = isolateProperties;
- if (desc instanceof Array) {
- globalObject = desc[0] || isolateProperties;
- desc = desc[1];
- }
- if (#) //backend.isTreeShakingDisabled,
- constructor["${namer.metadataField}"] = desc;
- allClasses[cls] = constructor;
- globalObject[cls] = constructor;
- }
-
- constructors = null;
-
- var finishedClasses = Object.create(null);
- # = Object.create(null); // embedded interceptorsByTag.
- # = Object.create(null); // embedded leafTags.
-
- #; // buildFinishClass(),
-
- #; // buildTrivialNsmHandlers()
-
- for (var cls in pendingClasses) finishClass(cls);
- }''', [
- allClassesAccess, allClassesAccess,
- allClassesAccess,
- DEBUG_FAST_OBJECTS,
- backend.hasRetainedMetadata,
- metadataAccess,
- needsMixinSupport,
- backend.isTreeShakingDisabled,
- interceptorsByTagAccess,
- leafTagsAccess,
- buildFinishClass(),
- nsmEmitter.buildTrivialNsmHandlers()]);
- }
-
- jsAst.Node optional(bool condition, jsAst.Node node) {
- return condition ? node : new jsAst.EmptyStatement();
- }
-
- jsAst.FunctionDeclaration buildFinishClass() {
- String specProperty = '"${namer.nativeSpecProperty}"'; // "%"
-
- jsAst.Expression interceptorsByTagAccess =
- generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG);
- jsAst.Expression leafTagsAccess =
- generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS);
-
- return js.statement('''
- function finishClass(cls) {
-
- if (finishedClasses[cls]) return;
- finishedClasses[cls] = true;
-
- var superclass = pendingClasses[cls];
-
- // 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") return;
- finishClass(superclass);
- var constructor = allClasses[cls];
- var superConstructor = allClasses[superclass];
-
- if (!superConstructor)
- superConstructor = existingIsolateProperties[superclass];
-
- var prototype = inheritFrom(constructor, superConstructor);
-
- if (#) { // !nativeClasses.isEmpty,
- // The property looks like this:
- //
- // HtmlElement: {
- // "%": "HTMLDivElement|HTMLAnchorElement;HTMLElement;FancyButton"
- //
- // The first two semicolon-separated parts contain dispatch tags, the
- // third contains the JavaScript names for classes.
- //
- // The tags indicate that JavaScript objects with the dispatch tags
- // (usually constructor names) HTMLDivElement, HTMLAnchorElement and
- // HTMLElement all map to the Dart native class named HtmlElement.
- // The first set is for effective leaf nodes in the hierarchy, the
- // second set is non-leaf nodes.
- //
- // The third part contains the JavaScript names of Dart classes that
- // extend the native class. Here, FancyButton extends HtmlElement, so
- // the runtime needs to know that window.HTMLElement.prototype is the
- // prototype that needs to be extended in creating the custom element.
- //
- // The information is used to build tables referenced by
- // getNativeInterceptor and custom element support.
- if (Object.prototype.hasOwnProperty.call(prototype, $specProperty)) {
- var nativeSpec = prototype[$specProperty].split(";");
- if (nativeSpec[0]) {
- var tags = nativeSpec[0].split("|");
- for (var i = 0; i < tags.length; i++) {
- #[tags[i]] = constructor; // embedded interceptorsByTag.
- #[tags[i]] = true; // embedded leafTags.
- }
- }
- if (nativeSpec[1]) {
- tags = nativeSpec[1].split("|");
- if (#) { // User subclassing of native classes?
- if (nativeSpec[2]) {
- var subclasses = nativeSpec[2].split("|");
- for (var i = 0; i < subclasses.length; i++) {
- var subclass = allClasses[subclasses[i]];
- subclass.\$nativeSuperclassTag = tags[0];
- }
- }
- for (i = 0; i < tags.length; i++) {
- #[tags[i]] = constructor; // embedded interceptorsByTag.
- #[tags[i]] = false; // embedded leafTags.
- }
- }
- }
- }
- }
- }''', [!nativeClasses.isEmpty,
- interceptorsByTagAccess,
- leafTagsAccess,
- true,
- interceptorsByTagAccess,
- leafTagsAccess]);
- }
-
- jsAst.Fun get finishIsolateConstructorFunction {
- // We replace the old Isolate function with a new one that initializes
- // all its fields with the initial (and often final) value of all globals.
- //
- // We also copy over old values like the prototype, and the
- // isolateProperties themselves.
- return js('''
- function (oldIsolate) {
- var isolateProperties = oldIsolate.#; // isolatePropertiesName
- function Isolate() {
- var hasOwnProperty = Object.prototype.hasOwnProperty;
- for (var staticName in isolateProperties)
- if (hasOwnProperty.call(isolateProperties, staticName))
- this[staticName] = isolateProperties[staticName];
-
- // Reset lazy initializers to null.
- // When forcing the object to fast mode (below) v8 will consider
- // functions as part the object's map. Since we will change them
- // (after the first call to the getter), we would have a map
- // transition.
- var lazies = init.lazies;
- for (var lazyInit in lazies) {
- this[lazies[lazyInit]] = null;
- }
-
- // Use the newly created object as prototype. In Chrome,
- // this creates a hidden class for the object and makes
- // sure it is fast to access.
- function ForceEfficientMap() {}
- ForceEfficientMap.prototype = this;
- new ForceEfficientMap();
-
- // Now, after being a fast map we can set the lazies again.
- for (var lazyInit in lazies) {
- var lazyInitName = lazies[lazyInit];
- this[lazyInitName] = isolateProperties[lazyInitName];
- }
- }
- Isolate.prototype = oldIsolate.prototype;
- Isolate.prototype.constructor = Isolate;
- Isolate.# = isolateProperties; // isolatePropertiesName
- if (#) // needsDefineClass.
- Isolate.# = oldIsolate.#; // finishClassesProperty * 2
- if (#) // outputContainsConstantList
- Isolate.# = oldIsolate.#; // makeConstListProperty * 2
- return Isolate;
- }''',
- [namer.isolatePropertiesName, namer.isolatePropertiesName,
- needsDefineClass, finishClassesProperty, finishClassesProperty,
- task.outputContainsConstantList,
- makeConstListProperty, makeConstListProperty ]);
- }
-
- jsAst.Fun get lazyInitializerFunction {
- String isolate = namer.currentIsolate;
- jsAst.Expression cyclicThrow =
- namer.elementAccess(backend.getCyclicThrowHelper());
- jsAst.Expression laziesAccess =
- generateEmbeddedGlobalAccess(embeddedNames.LAZIES);
-
- return js('''
- function (prototype, staticName, fieldName, getterName, lazyValue) {
- if (!#) # = Object.create(null);
- #[fieldName] = getterName;
-
- var sentinelUndefined = {};
- var sentinelInProgress = {};
- prototype[fieldName] = sentinelUndefined;
-
- prototype[getterName] = function () {
- var result = $isolate[fieldName];
- try {
- if (result === sentinelUndefined) {
- $isolate[fieldName] = sentinelInProgress;
-
- try {
- result = $isolate[fieldName] = lazyValue();
- } finally {
- // Use try-finally, not try-catch/throw as it destroys the
- // stack trace.
- if (result === sentinelUndefined)
- $isolate[fieldName] = null;
- }
- } else {
- if (result === sentinelInProgress)
- #(staticName);
- }
-
- return result;
- } finally {
- $isolate[getterName] = function() { return this[fieldName]; };
- }
- }
- }
- ''', [laziesAccess, laziesAccess,
- laziesAccess,
- cyclicThrow]);
- }
-
- List buildDefineClassAndFinishClassFunctionsIfNecessary() {
- if (!needsDefineClass) return [];
- return defineClassFunction
- ..addAll(buildInheritFrom())
- ..addAll([
- js('$finishClassesName = #', finishClassesFunction)
- ]);
- }
-
- List buildLazyInitializerFunctionIfNecessary() {
- if (!needsLazyInitializer) return [];
-
- return [js('# = #', [js(lazyInitializerName), lazyInitializerFunction])];
- }
-
- List buildFinishIsolateConstructor() {
- return [
- js('$finishIsolateConstructorName = #', finishIsolateConstructorFunction)
- ];
- }
-
- void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) {
- String isolate = namer.isolateName;
- buffer.write("$isolate = $finishIsolateConstructorName($isolate)$N");
- }
-
- /// In minified mode we want to keep the name for the most common core types.
- bool _isNativeTypeNeedingReflectionName(Element element) {
- if (!element.isClass) return false;
- return (element == compiler.intClass ||
- element == compiler.doubleClass ||
- element == compiler.numClass ||
- element == compiler.stringClass ||
- element == compiler.boolClass ||
- element == compiler.nullClass ||
- element == compiler.listClass);
- }
-
- /// Returns the "reflection name" of an [Element] or [Selector].
- /// The reflection name of a getter 'foo' is 'foo'.
- /// The reflection name of a setter 'foo' is 'foo='.
- /// The reflection name of a method 'foo' is 'foo:N:M:O', where N is the
- /// number of required arguments, M is the number of optional arguments, and
- /// O is the named arguments.
- /// The reflection name of a constructor is similar to a regular method but
- /// starts with 'new '.
- /// The reflection name of class 'C' is 'C'.
- /// An anonymous mixin application has no reflection name.
- /// This is used by js_mirrors.dart.
- String getReflectionName(elementOrSelector, String mangledName) {
- String name = elementOrSelector.name;
- if (backend.shouldRetainName(name) ||
- elementOrSelector is Element &&
- // Make sure to retain names of unnamed constructors, and
- // for common native types.
- ((name == '' &&
- backend.isAccessibleByReflection(elementOrSelector)) ||
- _isNativeTypeNeedingReflectionName(elementOrSelector))) {
-
- // TODO(ahe): Enable the next line when I can tell the difference between
- // an instance method and a global. They may have the same mangled name.
- // if (recordedMangledNames.contains(mangledName)) return null;
- recordedMangledNames.add(mangledName);
- return getReflectionNameInternal(elementOrSelector, mangledName);
- }
- return null;
- }
-
- String getReflectionNameInternal(elementOrSelector, String mangledName) {
- String name =
- namer.privateName(elementOrSelector.library, elementOrSelector.name);
- if (elementOrSelector.isGetter) return name;
- if (elementOrSelector.isSetter) {
- if (!mangledName.startsWith(namer.setterPrefix)) return '$name=';
- String base = mangledName.substring(namer.setterPrefix.length);
- String getter = '${namer.getterPrefix}$base';
- mangledFieldNames.putIfAbsent(getter, () => name);
- assert(mangledFieldNames[getter] == name);
- recordedMangledNames.add(getter);
- // TODO(karlklose,ahe): we do not actually need to store information
- // about the name of this setter in the output, but it is needed for
- // marking the function as invokable by reflection.
- return '$name=';
- }
- if (elementOrSelector is Element && elementOrSelector.isClosure) {
- // Closures are synthesized and their name might conflict with existing
- // globals. Assign an illegal name, and make sure they don't clash
- // with each other.
- return " $mangledName";
- }
- if (elementOrSelector is Selector
- || elementOrSelector.isFunction
- || elementOrSelector.isConstructor) {
- int requiredParameterCount;
- int optionalParameterCount;
- String namedArguments = '';
- bool isConstructor = false;
- if (elementOrSelector is Selector) {
- Selector selector = elementOrSelector;
- requiredParameterCount = selector.argumentCount;
- optionalParameterCount = 0;
- namedArguments = namedParametersAsReflectionNames(selector);
- } else {
- FunctionElement function = elementOrSelector;
- if (function.isConstructor) {
- isConstructor = true;
- name = Elements.reconstructConstructorName(function);
- }
- FunctionSignature signature = function.functionSignature;
- requiredParameterCount = signature.requiredParameterCount;
- optionalParameterCount = signature.optionalParameterCount;
- if (signature.optionalParametersAreNamed) {
- var names = [];
- for (Element e in signature.optionalParameters) {
- names.add(e.name);
- }
- Selector selector = new Selector.call(
- function.name,
- function.library,
- requiredParameterCount,
- names);
- namedArguments = namedParametersAsReflectionNames(selector);
- } else {
- // Named parameters are handled differently by mirrors. For unnamed
- // parameters, they are actually required if invoked
- // reflectively. Also, if you have a method c(x) and c([x]) they both
- // get the same mangled name, so they must have the same reflection
- // name.
- requiredParameterCount += optionalParameterCount;
- optionalParameterCount = 0;
- }
- }
- String suffix =
- // TODO(ahe): We probably don't need optionalParameterCount in the
- // reflection name.
- '$name:$requiredParameterCount:$optionalParameterCount'
- '$namedArguments';
- return (isConstructor) ? 'new $suffix' : suffix;
- }
- Element element = elementOrSelector;
- if (element.isGenerativeConstructorBody) {
- return null;
- } else if (element.isClass) {
- ClassElement cls = element;
- if (cls.isUnnamedMixinApplication) return null;
- return cls.name;
- } else if (element.isTypedef) {
- return element.name;
- }
- throw compiler.internalError(element,
- 'Do not know how to reflect on this $element.');
- }
-
- String namedParametersAsReflectionNames(Selector selector) {
- if (selector.getOrderedNamedArguments().isEmpty) return '';
- String names = selector.getOrderedNamedArguments().join(':');
- return ':$names';
- }
-
- jsAst.FunctionDeclaration buildCspPrecompiledFunctionFor(
- OutputUnit outputUnit) {
- // TODO(ahe): Compute a hash code.
- return js.statement('''
- function dart_precompiled(\$collectedClasses) {
- var \$desc;
- #;
- return #;
- }''',
- [cspPrecompiledFunctionFor(outputUnit),
- new jsAst.ArrayInitializer.from(
- cspPrecompiledConstructorNamesFor(outputUnit))]);
- }
-
- void generateClass(ClassElement classElement, ClassBuilder properties) {
- compiler.withCurrentElement(classElement, () {
- if (compiler.hasIncrementalSupport) {
- ClassBuilder builder =
- cachedClassBuilders.putIfAbsent(classElement, () {
- ClassBuilder builder = new ClassBuilder(classElement, namer);
- classEmitter.generateClass(
- classElement, builder, additionalProperties[classElement]);
- return builder;
- });
- invariant(classElement, builder.fields.isEmpty);
- invariant(classElement, builder.superName == null);
- invariant(classElement, builder.functionType == null);
- invariant(classElement, builder.fieldMetadata == null);
- properties.properties.addAll(builder.properties);
- } else {
- classEmitter.generateClass(
- classElement, properties, additionalProperties[classElement]);
- }
- });
- }
-
- void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) {
- if (needsDefineClass) {
- buffer.write('$finishClassesName($classesCollector,'
- '$_$isolateProperties,'
- '${_}null)$N');
-
- // Reset the map.
- buffer.write("$classesCollector$_=${_}null$N$n");
- }
- }
-
- void emitStaticFunctions(List<Element> staticFunctions) {
- for (Element element in staticFunctions) {
- ClassBuilder builder = new ClassBuilder(element, namer);
- containerBuilder.addMember(element, builder);
- getElementDescriptor(element).properties.addAll(builder.properties);
- }
- }
-
- void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) {
- JavaScriptConstantCompiler handler = backend.constants;
- Iterable<VariableElement> staticNonFinalFields =
- handler.getStaticNonFinalFieldsForEmission();
- for (Element element in Elements.sortedByPosition(staticNonFinalFields)) {
- // [:interceptedNames:] is handled in [emitInterceptedNames].
- if (element == backend.interceptedNames) continue;
- // `mapTypeToInterceptor` is handled in [emitMapTypeToInterceptor].
- if (element == backend.mapTypeToInterceptor) continue;
- compiler.withCurrentElement(element, () {
- ConstantValue initialValue = handler.getInitialValueFor(element).value;
- jsAst.Expression init =
- js('$isolateProperties.# = #',
- [namer.getNameOfGlobalField(element),
- constantEmitter.referenceInInitializationContext(initialValue)]);
- buffer.write(jsAst.prettyPrint(init, compiler,
- monitor: compiler.dumpInfoTask));
- buffer.write('$N');
- });
- }
- }
-
- void emitLazilyInitializedStaticFields(CodeBuffer buffer) {
- JavaScriptConstantCompiler handler = backend.constants;
- List<VariableElement> lazyFields =
- handler.getLazilyInitializedFieldsForEmission();
- if (!lazyFields.isEmpty) {
- needsLazyInitializer = true;
- for (VariableElement element in Elements.sortedByPosition(lazyFields)) {
- jsAst.Expression code = backend.generatedCode[element];
- // The code is null if we ended up not needing the lazily
- // initialized field after all because of constant folding
- // before code generation.
- if (code == null) continue;
- // The code only computes the initial value. We build the lazy-check
- // here:
- // lazyInitializer(prototype, 'name', fieldName, getterName, initial);
- // The name is used for error reporting. The 'initial' must be a
- // closure that constructs the initial value.
- jsAst.Expression init = js('#(#,#,#,#,#)',
- [js(lazyInitializerName),
- js(isolateProperties),
- js.string(element.name),
- js.string(namer.getNameX(element)),
- js.string(namer.getLazyInitializerName(element)),
- code]);
- buffer.write(jsAst.prettyPrint(init, compiler,
- monitor: compiler.dumpInfoTask));
- buffer.write("$N");
- }
- }
- }
-
- bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
- if (constant.isFunction) return true; // Already emitted.
- if (constant.isPrimitive) return true; // Inlined.
- if (constant.isDummy) return true; // Inlined.
- // The name is null when the constant is already a JS constant.
- // TODO(floitsch): every constant should be registered, so that we can
- // share the ones that take up too much space (like some strings).
- if (namer.constantName(constant) == null) return true;
- return false;
- }
-
- int compareConstants(ConstantValue a, ConstantValue b) {
- // Inlined constants don't affect the order and sometimes don't even have
- // names.
- int cmp1 = isConstantInlinedOrAlreadyEmitted(a) ? 0 : 1;
- int cmp2 = isConstantInlinedOrAlreadyEmitted(b) ? 0 : 1;
- if (cmp1 + cmp2 < 2) return cmp1 - cmp2;
-
- // Emit constant interceptors first. Constant interceptors for primitives
- // might be used by code that builds other constants. See Issue 18173.
- if (a.isInterceptor != b.isInterceptor) {
- return a.isInterceptor ? -1 : 1;
- }
-
- // Sorting by the long name clusters constants with the same constructor
- // which compresses a tiny bit better.
- int r = namer.constantLongName(a).compareTo(namer.constantLongName(b));
- if (r != 0) return r;
- // Resolve collisions in the long name by using the constant name (i.e. JS
- // name) which is unique.
- return namer.constantName(a).compareTo(namer.constantName(b));
- }
-
- void emitCompileTimeConstants(CodeBuffer buffer, OutputUnit outputUnit) {
- List<ConstantValue> constants = outputConstantLists[outputUnit];
- if (constants == null) return;
- bool isMainBuffer = buffer == mainBuffer;
- if (compiler.hasIncrementalSupport && isMainBuffer) {
- buffer = cachedEmittedConstantsBuffer;
- }
- for (ConstantValue constant in constants) {
- if (compiler.hasIncrementalSupport && isMainBuffer) {
- if (cachedEmittedConstants.contains(constant)) continue;
- cachedEmittedConstants.add(constant);
- }
- String name = namer.constantName(constant);
- jsAst.Expression init = js('#.# = #',
- [namer.globalObjectForConstant(constant), name,
- constantInitializerExpression(constant)]);
- buffer.write(jsAst.prettyPrint(init, compiler,
- monitor: compiler.dumpInfoTask));
- buffer.write('$N');
- }
- if (compiler.hasIncrementalSupport && isMainBuffer) {
- mainBuffer.add(cachedEmittedConstantsBuffer);
- }
- }
-
- jsAst.Template get makeConstantListTemplate {
- // TODO(floitsch): there is no harm in caching the template.
- return jsAst.js.uncachedExpressionTemplate(
- '${namer.isolateName}.$makeConstListProperty(#)');
- }
-
- void emitMakeConstantList(CodeBuffer buffer) {
- buffer.write(
- jsAst.prettyPrint(
- // Functions are stored in the hidden class and not as properties in
- // the object. We never actually look at the value, but only want
- // to know if the property exists.
- js.statement(r'''#.# = function(list) {
- list.immutable$list = Array;
- list.fixed$length = Array;
- return list;
- }''',
- [namer.isolateName, makeConstListProperty]),
- compiler, monitor: compiler.dumpInfoTask));
- buffer.write(N);
- }
-
- /// Returns the code equivalent to:
- /// `function(args) { $.startRootIsolate(X.main$closure(), args); }`
- jsAst.Expression buildIsolateSetupClosure(Element appMain,
- Element isolateMain) {
- jsAst.Expression mainAccess = namer.isolateStaticClosureAccess(appMain);
- // Since we pass the closurized version of the main method to
- // the isolate method, we must make sure that it exists.
- return js('function(a){ #(#, a); }',
- [namer.elementAccess(isolateMain), mainAccess]);
- }
-
- /**
- * Emits code that sets the `isolateTag embedded global to a unique string.
- */
- jsAst.Expression generateIsolateAffinityTagInitialization() {
- jsAst.Expression getIsolateTagAccess =
- generateEmbeddedGlobalAccess(embeddedNames.GET_ISOLATE_TAG);
- jsAst.Expression isolateTagAccess =
- generateEmbeddedGlobalAccess(embeddedNames.ISOLATE_TAG);
-
- return js('''
- !function() {
- // On V8, the 'intern' function converts a string to a symbol, which
- // makes property access much faster.
- function intern(s) {
- var o = {};
- o[s] = 1;
- return Object.keys(convertToFastObject(o))[0];
- }
-
- # = function(name) { // embedded getIsolateTag
- return intern("___dart_" + name + #); // embedded isolateTag
- };
-
- // To ensure that different programs loaded into the same context (page)
- // use distinct dispatch properies, we place an object on `Object` to
- // contain the names already in use.
- var tableProperty = "___dart_isolate_tags_";
- var usedProperties = Object[tableProperty] ||
- (Object[tableProperty] = Object.create(null));
-
- var rootProperty = "_${generateIsolateTagRoot()}";
- for (var i = 0; ; i++) {
- var property = intern(rootProperty + "_" + i + "_");
- if (!(property in usedProperties)) {
- usedProperties[property] = 1;
- # = property; // embedded isolateTag
- break;
- }
- }
- }()
- ''', [getIsolateTagAccess,
- isolateTagAccess,
- isolateTagAccess]);
- }
-
- jsAst.Expression generateDispatchPropertyNameInitialization() {
- jsAst.Expression dispatchPropertyNameAccess =
- generateEmbeddedGlobalAccess(embeddedNames.DISPATCH_PROPERTY_NAME);
- jsAst.Expression getIsolateTagAccess =
- generateEmbeddedGlobalAccess(embeddedNames.GET_ISOLATE_TAG);
- return js('# = #("dispatch_record")',
- [dispatchPropertyNameAccess,
- getIsolateTagAccess]);
- }
-
- String generateIsolateTagRoot() {
- // TODO(sra): MD5 of contributing source code or URIs?
- return 'ZxYxX';
- }
-
- emitMain(CodeBuffer buffer) {
- if (compiler.isMockCompilation) return;
- Element main = compiler.mainFunction;
- jsAst.Expression mainCallClosure = null;
- if (compiler.hasIsolateSupport) {
- Element isolateMain =
- backend.isolateHelperLibrary.find(JavaScriptBackend.START_ROOT_ISOLATE);
- mainCallClosure = buildIsolateSetupClosure(main, isolateMain);
- } else if (compiler.hasIncrementalSupport) {
- mainCallClosure =
- js('function() { return #(); }', namer.elementAccess(main));
- } else {
- mainCallClosure = namer.elementAccess(main);
- }
-
- if (backend.needToInitializeIsolateAffinityTag) {
- buffer.write(
- jsAst.prettyPrint(generateIsolateAffinityTagInitialization(),
- compiler, monitor: compiler.dumpInfoTask));
- buffer.write(N);
- }
- if (backend.needToInitializeDispatchProperty) {
- assert(backend.needToInitializeIsolateAffinityTag);
- buffer.write(
- jsAst.prettyPrint(generateDispatchPropertyNameInitialization(),
- compiler, monitor: compiler.dumpInfoTask));
- buffer.write(N);
- }
-
- jsAst.Expression currentScriptAccess =
- generateEmbeddedGlobalAccess(embeddedNames.CURRENT_SCRIPT);
-
- addComment('BEGIN invoke [main].', buffer);
- // This code finds the currently executing script by listening to the
- // onload event of all script tags and getting the first script which
- // finishes. Since onload is called immediately after execution this should
- // not substantially change execution order.
- jsAst.Statement invokeMain = js.statement('''
-(function (callback) {
- if (typeof document === "undefined") {
- callback(null);
- return;
- }
- if (document.currentScript) {
- callback(document.currentScript);
- return;
- }
-
- var scripts = document.scripts;
- function onLoad(event) {
- for (var i = 0; i < scripts.length; ++i) {
- scripts[i].removeEventListener("load", onLoad, false);
- }
- callback(event.target);
- }
- for (var i = 0; i < scripts.length; ++i) {
- scripts[i].addEventListener("load", onLoad, false);
- }
-})(function(currentScript) {
- # = currentScript; // embedded currentScript.
-
- if (typeof dartMainRunner === "function") {
- dartMainRunner(#, []); // mainCallClosure.
- } else {
- #([]); // mainCallClosure.
- }
-})$N''', [currentScriptAccess,
- mainCallClosure,
- mainCallClosure]);
-
- buffer.write(';');
- buffer.write(jsAst.prettyPrint(invokeMain,
- compiler, monitor: compiler.dumpInfoTask));
- buffer.write(N);
- addComment('END invoke [main].', buffer);
- }
-
- void emitInitFunction(CodeBuffer buffer) {
- jsAst.FunctionDeclaration decl = js.statement('''
- function init() {
- $isolateProperties = Object.create(null);
- #; #; #;
- }''', [
- buildDefineClassAndFinishClassFunctionsIfNecessary(),
- buildLazyInitializerFunctionIfNecessary(),
- buildFinishIsolateConstructor()]);
-
- buffer.write(jsAst.prettyPrint(decl,
- compiler, monitor: compiler.dumpInfoTask).getText());
- if (compiler.enableMinification) buffer.write('\n');
- }
-
- void emitConvertToFastObjectFunction() {
- List<jsAst.Statement> debugCode = <jsAst.Statement>[];
- if (DEBUG_FAST_OBJECTS) {
- debugCode.add(js.statement(r'''
- // The following only works on V8 when run with option
- // "--allow-natives-syntax". We use'new Function' because the
- // miniparser does not understand V8 native syntax.
- if (typeof print === "function") {
- var HasFastProperties =
- new Function("a", "return %HasFastProperties(a)");
- print("Size of global object: "
- + String(Object.getOwnPropertyNames(properties).length)
- + ", fast properties " + HasFastProperties(properties));
- }'''));
- }
-
- jsAst.Statement convertToFastObject = js.statement(r'''
- function convertToFastObject(properties) {
- // Create an instance that uses 'properties' as prototype. This should
- // make 'properties' a fast object.
- function MyClass() {};
- MyClass.prototype = properties;
- new MyClass();
- #;
- return properties;
- }''', [debugCode]);
-
- mainBuffer.add(jsAst.prettyPrint(convertToFastObject, compiler));
- mainBuffer.add(N);
- }
-
- void writeLibraryDescriptors(CodeBuffer buffer, LibraryElement library) {
- var uri = "";
- if (!compiler.enableMinification || backend.mustPreserveUris) {
- uri = library.canonicalUri;
- if (uri.scheme == 'file' && compiler.outputUri != null) {
- uri = relativize(compiler.outputUri, library.canonicalUri, false);
- }
- }
- ClassBuilder descriptor = elementDescriptors[library];
- if (descriptor == null) {
- // Nothing of the library was emitted.
- // TODO(floitsch): this should not happen. We currently have an example
- // with language/prefix6_negative_test.dart where we have an instance
- // method without its corresponding class.
- return;
- }
-
- String libraryName =
- (!compiler.enableMinification || backend.mustRetainLibraryNames) ?
- library.getLibraryName() :
- "";
-
- jsAst.Fun metadata = metadataEmitter.buildMetadataFunction(library);
-
- jsAst.ObjectInitializer initializers = descriptor.toObjectInitializer();
-
- compiler.dumpInfoTask.registerElementAst(library, metadata);
- compiler.dumpInfoTask.registerElementAst(library, initializers);
- buffer
- ..write('["$libraryName",$_')
- ..write('"${uri}",$_')
- ..write(metadata == null ? "" : jsAst.prettyPrint(metadata,
- compiler,
- monitor: compiler.dumpInfoTask))
- ..write(',$_')
- ..write(namer.globalObjectFor(library))
- ..write(',$_')
- ..write(jsAst.prettyPrint(initializers,
- compiler,
- monitor: compiler.dumpInfoTask))
- ..write(library == compiler.mainApp ? ',${n}1' : "")
- ..write('],$n');
- }
-
- void emitPrecompiledConstructor(OutputUnit outputUnit,
- String constructorName,
- jsAst.Expression constructorAst) {
- cspPrecompiledFunctionFor(outputUnit).add(
- new jsAst.FunctionDeclaration(
- new jsAst.VariableDeclaration(constructorName), constructorAst));
- cspPrecompiledFunctionFor(outputUnit).add(
- js.statement(r'''{
- #.builtin$cls = #;
- if (!"name" in #)
- #.name = #;
- $desc=$collectedClasses.#;
- if ($desc instanceof Array) $desc = $desc[1];
- #.prototype = $desc;
- }''',
- [ constructorName, js.string(constructorName),
- constructorName,
- constructorName, js.string(constructorName),
- constructorName,
- constructorName
- ]));
-
- cspPrecompiledConstructorNamesFor(outputUnit).add(js('#', constructorName));
- }
-
- /// Extracts the output name of the compiler's outputUri.
- String deferredPartFileName(OutputUnit outputUnit,
- {bool addExtension: true}) {
- String outPath = compiler.outputUri != null
- ? compiler.outputUri.path
- : "out";
- String outName = outPath.substring(outPath.lastIndexOf('/') + 1);
- String extension = addExtension ? ".part.js" : "";
- if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) {
- return "$outName$extension";
- } else {
- String name = outputUnit.name;
- return "${outName}_$name$extension";
- }
- }
-
- void emitLibraries(Iterable<LibraryElement> libraries) {
- if (libraries.isEmpty) return;
-
- // TODO(karlklose): document what kinds of fields this loop adds to the
- // library class builder.
- for (LibraryElement element in libraries) {
- LibraryElement library = element;
- ClassBuilder builder = new ClassBuilder(library, namer);
- if (classEmitter.emitFields(library, builder, null, emitStatics: true)) {
- jsAst.ObjectInitializer initializer = builder.toObjectInitializer();
- compiler.dumpInfoTask.registerElementAst(builder.element, initializer);
- getElementDescriptor(library).properties.addAll(initializer.properties);
- }
- }
- }
-
- void emitTypedefs() {
- OutputUnit mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit;
-
- // Emit all required typedef declarations into the main output unit.
- // TODO(karlklose): unify required classes and typedefs to declarations
- // and have builders for each kind.
- for (TypedefElement typedef in typedefsNeededForReflection) {
- OutputUnit mainUnit = compiler.deferredLoadTask.mainOutputUnit;
- LibraryElement library = typedef.library;
- // TODO(karlklose): add a TypedefBuilder and move this code there.
- DartType type = typedef.alias;
- int typeIndex = metadataEmitter.reifyType(type);
- String typeReference =
- encoding.encodeTypedefFieldDescriptor(typeIndex);
- jsAst.Property descriptor = new jsAst.Property(
- js.string(namer.classDescriptorProperty),
- js.string(typeReference));
- jsAst.Node declaration = new jsAst.ObjectInitializer([descriptor]);
- String mangledName = namer.getNameX(typedef);
- String reflectionName = getReflectionName(typedef, mangledName);
- getElementDescriptor(library)
- ..addProperty(mangledName, declaration)
- ..addProperty("+$reflectionName", js.string(''));
- // Also emit a trivial constructor for CSP mode.
- String constructorName = mangledName;
- jsAst.Expression constructorAst = js('function() {}');
- emitPrecompiledConstructor(mainOutputUnit,
- constructorName,
- constructorAst);
- }
- }
-
- void emitMangledNames() {
- if (!mangledFieldNames.isEmpty) {
- var keys = mangledFieldNames.keys.toList();
- keys.sort();
- var properties = [];
- for (String key in keys) {
- var value = js.string('${mangledFieldNames[key]}');
- properties.add(new jsAst.Property(js.string(key), value));
- }
-
- jsAst.Expression mangledNamesAccess =
- generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES);
- var map = new jsAst.ObjectInitializer(properties);
- mainBuffer.write(
- jsAst.prettyPrint(
- js.statement('# = #', [mangledNamesAccess, map]),
- compiler,
- monitor: compiler.dumpInfoTask));
- if (compiler.enableMinification) {
- mainBuffer.write(';');
- }
- }
- if (!mangledGlobalFieldNames.isEmpty) {
- var keys = mangledGlobalFieldNames.keys.toList();
- keys.sort();
- var properties = [];
- for (String key in keys) {
- var value = js.string('${mangledGlobalFieldNames[key]}');
- properties.add(new jsAst.Property(js.string(key), value));
- }
- jsAst.Expression mangledGlobalNamesAccess =
- generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES);
- var map = new jsAst.ObjectInitializer(properties);
- mainBuffer.write(
- jsAst.prettyPrint(
- js.statement('# = #', [mangledGlobalNamesAccess, map]),
- compiler,
- monitor: compiler.dumpInfoTask));
- if (compiler.enableMinification) {
- mainBuffer.write(';');
- }
- }
- }
-
- void checkEverythingEmitted(Iterable<Element> elements) {
- List<Element> pendingStatics;
- if (!compiler.hasIncrementalSupport) {
- pendingStatics =
- Elements.sortedByPosition(elements.where((e) => !e.isLibrary));
-
- pendingStatics.forEach((element) =>
- compiler.reportInfo(
- element, MessageKind.GENERIC, {'text': 'Pending statics.'}));
- }
-
- if (pendingStatics != null && !pendingStatics.isEmpty) {
- compiler.internalError(pendingStatics.first,
- 'Pending statics (see above).');
- }
- }
-
- void emitMainOutputUnit(Map<OutputUnit, String> deferredLoadHashes,
- CodeBuffer nativeBuffer) {
- bool isProgramSplit = compiler.deferredLoadTask.isProgramSplit;
- OutputUnit mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit;
-
- mainBuffer.add(buildGeneratedBy());
- addComment(HOOKS_API_USAGE, mainBuffer);
-
- if (isProgramSplit) {
- /// For deferred loading we communicate the initializers via this global
- /// variable. The deferred hunks will add their initialization to this.
- /// The semicolon is important in minified mode, without it the
- /// following parenthesis looks like a call to the object literal.
- mainBuffer..add(
- 'self.${deferredInitializers} = self.${deferredInitializers} || '
- 'Object.create(null);$n');
- }
-
- // Using a named function here produces easier to read stack traces in
- // Chrome/V8.
- mainBuffer.add('(function(${namer.currentIsolate})$_{\n');
- if (compiler.hasIncrementalSupport) {
- mainBuffer.add(
- '(this.\$dart_unsafe_eval ='
- ' this.\$dart_unsafe_eval || Object.create(null))'
- '.patch = function(a) { eval(a) }$N');
- }
- if (isProgramSplit) {
- /// We collect all the global state of the, so it can be passed to the
- /// initializer of deferred files.
- mainBuffer.add('var ${globalsHolder}$_=${_}Object.create(null)$N');
- }
- mainBuffer.add('function dart()$_{$n'
- '${_}${_}this.x$_=${_}0$N'
- '${_}${_}delete this.x$N'
- '}$n');
- for (String globalObject in Namer.reservedGlobalObjectNames) {
- // The global objects start as so-called "slow objects". For V8, this
- // means that it won't try to make map transitions as we add properties
- // to these objects. Later on, we attempt to turn these objects into
- // fast objects by calling "convertToFastObject" (see
- // [emitConvertToFastObjectFunction]).
- mainBuffer.write('var ${globalObject}$_=${_}');
- if(isProgramSplit) {
- mainBuffer.add('${globalsHolder}.$globalObject$_=${_}');
- }
- mainBuffer.write('new dart$N');
- }
-
- mainBuffer.add('function ${namer.isolateName}()$_{}\n');
- if (isProgramSplit) {
- mainBuffer
- .write('${globalsHolder}.${namer.isolateName}$_=$_'
- '${namer.isolateName}$N'
- '${globalsHolder}.$initName$_=${_}$initName$N');
- }
- mainBuffer.add('init()$N$n');
- mainBuffer.add('$isolateProperties$_=$_$isolatePropertiesName$N');
-
- emitStaticFunctions(task.outputStaticLists[mainOutputUnit]);
-
- // Only output the classesCollector if we actually have any classes.
- if (!(nativeClasses.isEmpty &&
- compiler.codegenWorld.staticFunctionsNeedingGetter.isEmpty &&
- outputClassLists.values.every((classList) => classList.isEmpty) &&
- typedefsNeededForReflection.isEmpty)) {
- // Shorten the code by using "$$" as temporary.
- classesCollector = r"$$";
- mainBuffer.add('var $classesCollector$_=${_}Object.create(null)$N$n');
- }
-
- if (!nativeClasses.isEmpty) {
- addComment('Native classes', mainBuffer);
- }
-
- List<ClassElement> classes = task.outputClassLists[mainOutputUnit];
- if (classes != null) {
- for (ClassElement element in classes) {
- generateClass(element, getElementDescriptor(element));
- }
- }
-
- if (compiler.enableMinification) {
- mainBuffer.write(';');
- }
-
- if (elementDescriptors.isNotEmpty) {
- Iterable<LibraryElement> libraries =
- task.outputLibraryLists[mainOutputUnit];
- if (libraries == null) libraries = [];
- emitLibraries(libraries);
- emitTypedefs();
- emitMangledNames();
-
- checkEverythingEmitted(elementDescriptors.keys);
-
- CodeBuffer libraryBuffer = new CodeBuffer();
- for (LibraryElement library in Elements.sortedByPosition(libraries)) {
- writeLibraryDescriptors(libraryBuffer, library);
- elementDescriptors.remove(library);
- }
-
- mainBuffer
- ..write('(')
- ..write(
- jsAst.prettyPrint(
- getReflectionDataParser(classesCollector, backend),
- compiler))
- ..write(')')
- ..write('([$n')
- ..add(libraryBuffer)
- ..write('])$N');
-
- emitFinishClassesInvocationIfNecessary(mainBuffer);
- }
-
- typeTestEmitter.emitRuntimeTypeSupport(mainBuffer, mainOutputUnit);
- interceptorEmitter.emitGetInterceptorMethods(mainBuffer);
- interceptorEmitter.emitOneShotInterceptors(mainBuffer);
-
- if (task.outputContainsConstantList) {
- emitMakeConstantList(mainBuffer);
- }
-
- // Constants in checked mode call into RTI code to set type information
- // which may need getInterceptor (and one-shot interceptor) methods, so
- // we have to make sure that [emitGetInterceptorMethods] and
- // [emitOneShotInterceptors] have been called.
- emitCompileTimeConstants(mainBuffer, mainOutputUnit);
-
- emitDeferredBoilerPlate(mainBuffer, deferredLoadHashes);
-
- // Static field initializations require the classes and compile-time
- // constants to be set up.
- emitStaticNonFinalFieldInitializations(mainBuffer);
- interceptorEmitter.emitInterceptedNames(mainBuffer);
- interceptorEmitter.emitMapTypeToInterceptor(mainBuffer);
- emitLazilyInitializedStaticFields(mainBuffer);
-
- mainBuffer.writeln();
- mainBuffer.add(nativeBuffer);
-
- metadataEmitter.emitMetadata(mainBuffer);
-
- isolateProperties = isolatePropertiesName;
- // The following code should not use the short-hand for the
- // initialStatics.
- mainBuffer.add('${namer.currentIsolate}$_=${_}null$N');
-
- emitFinishIsolateConstructorInvocation(mainBuffer);
- mainBuffer.add(
- '${namer.currentIsolate}$_=${_}new ${namer.isolateName}()$N');
-
- emitConvertToFastObjectFunction();
- for (String globalObject in Namer.reservedGlobalObjectNames) {
- mainBuffer.add('$globalObject = convertToFastObject($globalObject)$N');
- }
- if (DEBUG_FAST_OBJECTS) {
- mainBuffer.add(r'''
- // The following only works on V8 when run with option
- // "--allow-natives-syntax". We use'new Function' because the
- // miniparser does not understand V8 native syntax.
- if (typeof print === "function") {
- var HasFastProperties =
- new Function("a", "return %HasFastProperties(a)");
- print("Size of global helper object: "
- + String(Object.getOwnPropertyNames(H).length)
- + ", fast properties " + HasFastProperties(H));
- print("Size of global platform object: "
- + String(Object.getOwnPropertyNames(P).length)
- + ", fast properties " + HasFastProperties(P));
- print("Size of global dart:html object: "
- + String(Object.getOwnPropertyNames(W).length)
- + ", fast properties " + HasFastProperties(W));
- print("Size of isolate properties object: "
- + String(Object.getOwnPropertyNames($).length)
- + ", fast properties " + HasFastProperties($));
- print("Size of constant object: "
- + String(Object.getOwnPropertyNames(C).length)
- + ", fast properties " + HasFastProperties(C));
- var names = Object.getOwnPropertyNames($);
- for (var i = 0; i < names.length; i++) {
- print("$." + names[i]);
- }
- }
-''');
- for (String object in Namer.userGlobalObjects) {
- mainBuffer.add('''
- if (typeof print === "function") {
- print("Size of $object: "
- + String(Object.getOwnPropertyNames($object).length)
- + ", fast properties " + HasFastProperties($object));
-}
-''');
- }
- }
-
- jsAst.FunctionDeclaration precompiledFunctionAst =
- buildCspPrecompiledFunctionFor(mainOutputUnit);
- emitInitFunction(mainBuffer);
- emitMain(mainBuffer);
- mainBuffer.add('})()\n');
-
- if (compiler.useContentSecurityPolicy) {
- mainBuffer.write(
- jsAst.prettyPrint(
- precompiledFunctionAst,
- compiler,
- monitor: compiler.dumpInfoTask,
- allowVariableMinification: false).getText());
- }
-
- String assembledCode = mainBuffer.getText();
- if (generateSourceMap) {
- outputSourceMap(assembledCode, mainBuffer, '',
- compiler.sourceMapUri, compiler.outputUri);
- mainBuffer.add(
- generateSourceMapTag(compiler.sourceMapUri, compiler.outputUri));
- assembledCode = mainBuffer.getText();
- }
-
- compiler.outputProvider('', 'js')
- ..add(assembledCode)
- ..close();
- compiler.assembledCode = assembledCode;
-
- if (!compiler.useContentSecurityPolicy) {
- CodeBuffer cspBuffer = new CodeBuffer();
- cspBuffer.add(mainBuffer);
- cspBuffer.write("""
-{
- var message =
- 'Deprecation: Automatic generation of output for Content Security\\n' +
- 'Policy is deprecated and will be removed with the next development\\n' +
- 'release. Use the --csp option to generate CSP restricted output.';
- if (typeof dartPrint == "function") {
- dartPrint(message);
- } else if (typeof console == "object" && typeof console.log == "function") {
- console.log(message);
- } else if (typeof print == "function") {
- print(message);
- }
-}\n""");
-
- cspBuffer.write(
- jsAst.prettyPrint(
- precompiledFunctionAst, compiler,
- allowVariableMinification: false).getText());
-
- compiler.outputProvider('', 'precompiled.js')
- ..add(cspBuffer.getText())
- ..close();
- }
- }
-
- /// Returns a map from OutputUnit to a hash of its content. The hash uniquely
- /// identifies the code of the output-unit. It does not include
- /// boilerplate JS code, like the sourcemap directives or the hash
- /// itself.
- Map<OutputUnit, String> emitDeferredOutputUnits() {
- if (!compiler.deferredLoadTask.isProgramSplit) return const {};
-
- Map<OutputUnit, CodeBuffer> outputBuffers =
- new Map<OutputUnit, CodeBuffer>();
-
- for (OutputUnit outputUnit in compiler.deferredLoadTask.allOutputUnits) {
- if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) continue;
-
- List<Element> functions = task.outputStaticLists[outputUnit];
- if (functions != null) {
- emitStaticFunctions(functions);
- }
-
- List<ClassElement> classes = task.outputClassLists[outputUnit];
- if (classes != null) {
- for (ClassElement element in classes) {
- generateClass(element, getElementDescriptor(element));
- }
- }
-
- if (elementDescriptors.isNotEmpty) {
- Iterable<LibraryElement> libraries =
- task.outputLibraryLists[outputUnit];
- if (libraries == null) libraries = [];
- emitLibraries(libraries);
-
- CodeBuffer buffer = new CodeBuffer();
- outputBuffers[outputUnit] = buffer;
- for (LibraryElement library in Elements.sortedByPosition(libraries)) {
- writeLibraryDescriptors(buffer, library);
- elementDescriptors.remove(library);
- }
- }
- }
-
- return emitDeferredCode(outputBuffers);
- }
-
- CodeBuffer buildNativesBuffer() {
- // Emit native classes on [nativeBuffer].
- final CodeBuffer nativeBuffer = new CodeBuffer();
-
- if (nativeClasses.isEmpty) return nativeBuffer;
-
-
- addComment('Native classes', nativeBuffer);
-
- nativeEmitter.generateNativeClasses(nativeClasses, mainBuffer,
- additionalProperties);
-
- nativeEmitter.finishGenerateNativeClasses();
- nativeEmitter.assembleCode(nativeBuffer);
-
- return nativeBuffer;
- }
-
- void emitProgram(Program program) {
- // Shorten the code by using [namer.currentIsolate] as temporary.
- isolateProperties = namer.currentIsolate;
-
- classesCollector = r"$$";
-
- // Emit deferred units first, so we have their hashes.
- // Map from OutputUnit to a hash of its content. The hash uniquely
- // identifies the code of the output-unit. It does not include
- // boilerplate JS code, like the sourcemap directives or the hash
- // itself.
- Map<OutputUnit, String> deferredLoadHashes = emitDeferredOutputUnits();
- CodeBuffer nativeBuffer = buildNativesBuffer();
- emitMainOutputUnit(deferredLoadHashes, nativeBuffer);
-
- if (backend.requiresPreamble &&
- !backend.htmlLibraryIsLoaded) {
- compiler.reportHint(NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE);
- }
- }
-
- String generateSourceMapTag(Uri sourceMapUri, Uri fileUri) {
- if (sourceMapUri != null && fileUri != null) {
- String sourceMapFileName = relativize(fileUri, sourceMapUri, false);
- return '''
-
-//# sourceMappingURL=$sourceMapFileName
-''';
- }
- return '';
- }
-
- ClassBuilder getElementDescriptor(Element element) {
- Element owner = element.library;
- if (!element.isLibrary && !element.isTopLevel && !element.isNative) {
- // For static (not top level) elements, record their code in a buffer
- // specific to the class. For now, not supported for native classes and
- // native elements.
- ClassElement cls =
- element.enclosingClassOrCompilationUnit.declaration;
- if (compiler.codegenWorld.directlyInstantiatedClasses.contains(cls)
- && !cls.isNative) {
- owner = cls;
- }
- }
- if (owner == null) {
- compiler.internalError(element, 'Owner is null.');
- }
- return elementDescriptors.putIfAbsent(
- owner,
- () => new ClassBuilder(owner, namer));
- }
-
- /// Emits support-code for deferred loading into [buffer].
- void emitDeferredBoilerPlate(CodeBuffer buffer,
- Map<OutputUnit, String> deferredLoadHashes) {
- // Function for checking if a hunk is loaded given its hash.
- buffer.write(jsAst.prettyPrint(
- js('# = function(hunkHash) {'
- ' return !!$deferredInitializers[hunkHash];'
- '}', generateEmbeddedGlobalAccess(embeddedNames.IS_HUNK_LOADED)),
- compiler, monitor: compiler.dumpInfoTask));
- buffer.write('$N');
- // Function for initializing a loaded hunk, given its hash.
- buffer.write(jsAst.prettyPrint(
- js('# = function(hunkHash) {'
- ' $deferredInitializers[hunkHash]('
- '$globalsHolder, ${namer.currentIsolate})'
- '}',
- generateEmbeddedGlobalAccess(
- embeddedNames.INITIALIZE_LOADED_HUNK)),
- compiler, monitor: compiler.dumpInfoTask));
- buffer.write('$N');
- // Write a javascript mapping from Deferred import load ids (derrived
- // from the import prefix.) to a list of lists of uris of hunks to load,
- // and a corresponding mapping to a list of hashes used by
- // INITIALIZE_LOADED_HUNK and IS_HUNK_LOADED.
- Map<String, List<String>> deferredLibraryUris =
- new Map<String, List<String>>();
- Map<String, List<String>> deferredLibraryHashes =
- new Map<String, List<String>>();
- compiler.deferredLoadTask.hunksToLoad.forEach(
- (String loadId, List<OutputUnit>outputUnits) {
- List<String> uris = new List<String>();
- List<String> hashes = new List<String>();
- deferredLibraryHashes[loadId] = new List<String>();
- for (OutputUnit outputUnit in outputUnits) {
- uris.add(deferredPartFileName(outputUnit));
- hashes.add(deferredLoadHashes[outputUnit]);
- }
-
- deferredLibraryUris[loadId] = uris;
- deferredLibraryHashes[loadId] = hashes;
- });
-
- void emitMapping(String name, Map<String, List<String>> mapping) {
- List<jsAst.Property> properties = new List<jsAst.Property>();
- mapping.forEach((String key, List<String> values) {
- properties.add(new jsAst.Property(js.escapedString(key),
- new jsAst.ArrayInitializer.from(
- values.map(js.escapedString))));
- });
- jsAst.Node initializer =
- new jsAst.ObjectInitializer(properties, isOneLiner: true);
-
- jsAst.Node globalName = generateEmbeddedGlobalAccess(name);
- buffer.write(jsAst.prettyPrint(
- js("# = #", [globalName, initializer]),
- compiler, monitor: compiler.dumpInfoTask));
- buffer.write('$N');
-
- }
-
- emitMapping(embeddedNames.DEFERRED_LIBRARY_URIS, deferredLibraryUris);
- emitMapping(embeddedNames.DEFERRED_LIBRARY_HASHES,
- deferredLibraryHashes);
- }
-
- /// Emits code for all output units except the main.
- /// Returns a mapping from outputUnit to a hash of the corresponding hunk that
- /// can be used for calling the initializer.
- Map<OutputUnit, String> emitDeferredCode(
- Map<OutputUnit, CodeBuffer> deferredBuffers) {
-
- Map<OutputUnit, String> hunkHashes = new Map<OutputUnit, String>();
-
- for (OutputUnit outputUnit in compiler.deferredLoadTask.allOutputUnits) {
- if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) continue;
-
- CodeBuffer libraryDescriptorBuffer = deferredBuffers[outputUnit];
-
- CodeBuffer outputBuffer = new CodeBuffer();
-
- outputBuffer..write(buildGeneratedBy())
- ..write('${deferredInitializers}.current$_=$_'
- 'function$_(${globalsHolder}) {$N');
- for (String globalObject in Namer.reservedGlobalObjectNames) {
- outputBuffer
- .write('var $globalObject$_=$_'
- '${globalsHolder}.$globalObject$N');
- }
- outputBuffer
- ..write('var init$_=$_${globalsHolder}.init$N')
- ..write('var ${namer.isolateName}$_=$_'
- '${globalsHolder}.${namer.isolateName}$N');
- if (libraryDescriptorBuffer != null) {
- // TODO(ahe): This defines a lot of properties on the
- // Isolate.prototype object. We know this will turn it into a
- // slow object in V8, so instead we should do something similar
- // to Isolate.$finishIsolateConstructor.
- outputBuffer
- ..write('var ${namer.currentIsolate}$_=$_$isolatePropertiesName$N')
- // The classesCollector object ($$).
- ..write('$classesCollector$_=${_}Object.create(null);$n')
- ..write('(')
- ..write(
- jsAst.prettyPrint(
- getReflectionDataParser(classesCollector, backend),
- compiler, monitor: compiler.dumpInfoTask))
- ..write(')')
- ..write('([$n')
- ..addBuffer(libraryDescriptorBuffer)
- ..write('])$N');
-
- if (outputClassLists.containsKey(outputUnit)) {
- outputBuffer.write(
- '$finishClassesName($classesCollector,$_${namer.currentIsolate},'
- '$_$isolatePropertiesName)$N');
- }
-
- }
-
- // Set the currentIsolate variable to the current isolate (which is
- // provided as second argument).
- // We need to do this, because we use the same variable for setting up
- // the isolate-properties and for storing the current isolate. During
- // the setup (the code above this lines) we must set the variable to
- // the isolate-properties.
- // After we have done the setup (finishing with `finishClasses`) it must
- // point to the current Isolate. Otherwise all methods/functions
- // accessing isolate variables will access the wrong object.
- outputBuffer.write("${namer.currentIsolate}$_=${_}arguments[1]$N");
- typeTestEmitter.emitRuntimeTypeSupport(outputBuffer, outputUnit);
-
- emitCompileTimeConstants(outputBuffer, outputUnit);
- outputBuffer.write('}$N');
-
- if (compiler.useContentSecurityPolicy) {
- jsAst.FunctionDeclaration precompiledFunctionAst =
- buildCspPrecompiledFunctionFor(outputUnit);
-
- outputBuffer.write(
- jsAst.prettyPrint(
- precompiledFunctionAst, compiler,
- monitor: compiler.dumpInfoTask,
- allowVariableMinification: false).getText());
- }
-
- // Make a unique hash of the code (before the sourcemaps are added)
- // This will be used to retrieve the initializing function from the global
- // variable.
- String hash = hashOfString(outputBuffer.getText());
-
- outputBuffer.add('${deferredInitializers}["$hash"]$_=$_'
- '${deferredInitializers}.current$N');
-
- String partPrefix = deferredPartFileName(outputUnit, addExtension: false);
- if (generateSourceMap) {
- Uri mapUri, partUri;
- Uri sourceMapUri = compiler.sourceMapUri;
- Uri outputUri = compiler.outputUri;
-
- String partName = "$partPrefix.part";
-
- if (sourceMapUri != null) {
- String mapFileName = partName + ".js.map";
- List<String> mapSegments = sourceMapUri.pathSegments.toList();
- mapSegments[mapSegments.length - 1] = mapFileName;
- mapUri = compiler.sourceMapUri.replace(pathSegments: mapSegments);
- }
-
- if (outputUri != null) {
- String partFileName = partName + ".js";
- List<String> partSegments = outputUri.pathSegments.toList();
- partSegments[partSegments.length - 1] = partFileName;
- partUri = compiler.outputUri.replace(pathSegments: partSegments);
- }
-
- outputSourceMap(outputBuffer.getText(), outputBuffer, partName,
- mapUri, partUri);
- outputBuffer.add(generateSourceMapTag(mapUri, partUri));
- }
-
- outputBuffers[outputUnit] = outputBuffer;
- compiler.outputProvider(partPrefix, 'part.js')
- ..add(outputBuffer.getText())
- ..close();
-
- hunkHashes[outputUnit] = hash;
- }
- return hunkHashes;
- }
-
- String buildGeneratedBy() {
- var suffix = '';
- if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}';
- return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n';
- }
-
- void outputSourceMap(String code, CodeBuffer buffer, String name,
- [Uri sourceMapUri, Uri fileUri]) {
- if (!generateSourceMap) return;
- // Create a source file for the compilation output. This allows using
- // [:getLine:] to transform offsets to line numbers in [SourceMapBuilder].
- SourceFile compiledFile = new StringSourceFile(null, code);
- SourceMapBuilder sourceMapBuilder =
- new SourceMapBuilder(sourceMapUri, fileUri, compiledFile);
- buffer.forEachSourceLocation(sourceMapBuilder.addMapping);
- String sourceMap = sourceMapBuilder.build();
- compiler.outputProvider(name, 'js.map')
- ..add(sourceMap)
- ..close();
- }
-
- void invalidateCaches() {
- if (!compiler.hasIncrementalSupport) return;
- if (cachedElements.isEmpty) return;
- for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) {
- if (element.isInstanceMember) {
- cachedClassBuilders.remove(element.enclosingClass);
-
- nativeEmitter.cachedBuilders.remove(element.enclosingClass);
-
- }
- }
- }
-}

Powered by Google App Engine
This is Rietveld 408576698