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

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

Issue 237583014: JS templates (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: cleanup Created 6 years, 8 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
Index: sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
index c5dd94aaae0da35570c35080e1f94d7b88a4d23b..5bb280f3989a24a4ce7dbb7657925a0525b2bd86 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
@@ -148,74 +148,65 @@ class CodeEmitterTask extends CompilerTask {
String valueParamName = compiler.enableMinification ? "v" : "value";
String reflectableField = namer.reflectableField;
- // function generateAccessor(field, prototype, cls) {
- jsAst.Fun fun = js.fun(['fieldDescriptor', 'accessors', 'cls'], [
- js('var fieldInformation = fieldDescriptor.split("-")'),
- js('var field = fieldInformation[0]'),
- js('var len = field.length'),
- js('var code = field.charCodeAt(len - 1)'),
- js('var reflectable'),
- js.if_('fieldInformation.length > 1', js('reflectable = true'),
- js('reflectable = false')),
- js('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 (needsAccessor) {
- js.if_('code', [
- js('var getterCode = code & 3'),
- js('var setterCode = code >> 2'),
- js('var accessorName = field = field.substring(0, len - 1)'),
-
- js('var divider = field.indexOf(":")'),
- js.if_('divider > 0', [ // Colon never in first position.
- js('accessorName = field.substring(0, divider)'),
- js('field = field.substring(divider + 1)')
- ]),
-
- // if (needsGetter) {
- js.if_('getterCode', [
- js('var args = (getterCode & 2) ? "$receiverParamName" : ""'),
- js('var receiver = (getterCode & 1) ? "this" : "$receiverParamName"'),
- js('var body = "return " + receiver + "." + field'),
- js('var property ='
- ' cls + ".prototype.${namer.getterPrefix}" + accessorName + "="'),
- js('var fn = "function(" + args + "){" + body + "}"'),
- js.if_(
- 'reflectable',
- js('accessors.push(property + "\$reflectable(" + fn + ");\\n")'),
- js('accessors.push(property + fn + ";\\n")')),
- ]),
-
- // if (needsSetter) {
- js.if_('setterCode', [
- js('var args = (setterCode & 2)'
- ' ? "$receiverParamName,${_}$valueParamName"'
- ' : "$valueParamName"'),
- js('var receiver = (setterCode & 1) ? "this" : "$receiverParamName"'),
- js('var body = receiver + "." + field + "$_=$_$valueParamName"'),
- js('var property ='
- ' cls + ".prototype.${namer.setterPrefix}" + accessorName + "="'),
- js('var fn = "function(" + args + "){" + body + "}"'),
- js.if_(
- 'reflectable',
- js('accessors.push(property + "\$reflectable(" + fn + ");\\n")'),
- js('accessors.push(property + fn + ";\\n")')),
- ]),
-
- ]),
-
- // return field;
- js.return_('field')
- ]);
+ 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;
floitsch 2014/04/22 16:11:18 var reflectable = fieldInformation.length > 1;
sra1 2014/04/23 02:33:50 I agree, but the process for this change it to cha
+ 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 new jsAst.FunctionDeclaration(
- new jsAst.VariableDeclaration('generateAccessor'),
- fun);
+ return field;
+ }''');
}
List get defineClassFunction {
@@ -304,130 +295,134 @@ class CodeEmitterTask extends CompilerTask {
// object and copy over the members.
String reflectableField = namer.reflectableField;
- List<jsAst.Node> statements = [
- js('var pendingClasses = {}'),
- js.if_('!init.allClasses', js('init.allClasses = {}')),
- js('var allClasses = init.allClasses'),
-
- optional(
- DEBUG_FAST_OBJECTS,
- js('print("Number of classes: "'
- r' + Object.getOwnPropertyNames($$).length)')),
-
- js('var hasOwnProperty = Object.prototype.hasOwnProperty'),
-
- js.if_('typeof dart_precompiled == "function"',
- [js('var constructors = dart_precompiled(collectedClasses)')],
-
- [js('var combinedConstructorFunction = "function \$reflectable(fn){'
- 'fn.$reflectableField=1;return fn};\\n"+ "var \$desc;\\n"'),
- js('var constructorsList = []')]),
- js.forIn('cls', 'collectedClasses', [
- js.if_('hasOwnProperty.call(collectedClasses, cls)', [
- js('var desc = collectedClasses[cls]'),
- js.if_('desc instanceof Array', js('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'.
- */
- js('var classData = desc["${namer.classDescriptorProperty}"], '
- 'supr, name = cls, fields = classData'),
- optional(
- backend.hasRetainedMetadata,
- js.if_('typeof classData == "object" && '
- 'classData instanceof Array',
- [js('classData = fields = classData[0]')])),
-
- js.if_('typeof classData == "string"', [
- js('var split = classData.split("/")'),
- js.if_('split.length == 2', [
- js('name = split[0]'),
- js('fields = split[1]')
- ])
- ]),
-
- js('var s = fields.split(";")'),
- js('fields = s[1] == "" ? [] : s[1].split(",")'),
- js('supr = s[0]'),
- js('split = supr.split(":")'),
- js.if_('split.length == 2', [
- js('supr = split[0]'),
- js('var functionSignature = split[1]'),
- js.if_('functionSignature',
- js('desc.\$signature = #',
- js.fun('s',
- js.return_(js.fun([], js.return_('init.metadata[s]'))))(
- js('functionSignature'))))
- ]),
-
- optional(needsMixinSupport, js.if_('supr && supr.indexOf("+") > 0', [
- js('s = supr.split("+")'),
- js('supr = s[0]'),
- js('var mixin = collectedClasses[s[1]]'),
- js.if_('mixin instanceof Array', js('mixin = mixin[1]')),
- js.forIn('d', 'mixin', [
- js.if_('hasOwnProperty.call(mixin, d)'
- '&& !hasOwnProperty.call(desc, d)',
- js('desc[d] = mixin[d]'))
- ]),
- ])),
-
- js.if_('typeof dart_precompiled != "function"',
- [js('combinedConstructorFunction +='
- ' defineClass(name, cls, fields)'),
- js('constructorsList.push(cls)')]),
- js.if_('supr', js('pendingClasses[cls] = supr'))
- ])
- ]),
- js.statement('''
- if (typeof dart_precompiled != "function") {
- combinedConstructorFunction +=
- "return [\\n " + constructorsList.join(",\\n ") + "\\n]";
- var constructors =
- new Function("\$collectedClasses", combinedConstructorFunction)
- (collectedClasses);
- combinedConstructorFunction = null;
- }'''),
- js.for_('var i = 0', 'i < constructors.length', 'i++', [
- js('var constructor = constructors[i]'),
- js('var cls = constructor.name'),
- js('var desc = collectedClasses[cls]'),
- js('var globalObject = isolateProperties'),
- js.if_('desc instanceof Array', [
- js('globalObject = desc[0] || isolateProperties'),
- js('desc = desc[1]')
- ]),
- optional(backend.isTreeShakingDisabled,
- js('constructor["${namer.metadataField}"] = desc')),
- js('allClasses[cls] = constructor'),
- js('globalObject[cls] = constructor'),
- ]),
- js('constructors = null'),
-
- js('var finishedClasses = {}'),
- js('init.interceptorsByTag = Object.create(null)'),
- js('init.leafTags = {}'),
-
- buildFinishClass(),
- ];
- nsmEmitter.addTrivialNsmHandlers(statements);
+ return js('''
+ function(collectedClasses, isolateProperties, existingIsolateProperties) {
+ var pendingClasses = {};
+ if (!init.allClasses) init.allClasses = {};
+ var allClasses = init.allClasses;
+
+ if (#) // DEBUG_FAST_OBJECTS
+ print("Number of classes: " +
+ Object.getOwnPropertyNames(\$\$).length);
- statements.add(
- js.statement('for (var cls in pendingClasses) finishClass(cls);')
- );
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+ if (typeof dart_precompiled == "function") {
floitsch 2014/04/22 16:11:18 Not this CL, but I think this is a compile-time co
sra1 2014/04/23 02:33:50 I'm not sure because the csp stuff is appended. It
+ 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) {
+ if (hasOwnProperty.call(collectedClasses, cls)) {
+ 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 init.metadata[s]; };
+ })(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;
+ }
- // function(collectedClasses,
- // isolateProperties,
- // existingIsolateProperties)
- return js.fun(['collectedClasses', 'isolateProperties',
- 'existingIsolateProperties'], statements);
+ constructors = null;
+
+ var finishedClasses = {};
+ init.interceptorsByTag = Object.create(null);
+ init.leafTags = {};
+
+ #; // buildFinishClass(),
+
+ #; // buildTrivialNsmHandlers()
+
+ for (var cls in pendingClasses) finishClass(cls);
+ }''', [
+ DEBUG_FAST_OBJECTS,
+ backend.hasRetainedMetadata,
+ needsMixinSupport,
+ backend.isTreeShakingDisabled,
+ buildFinishClass(),
+ nsmEmitter.buildTrivialNsmHandlers()]);
+
}
jsAst.Node optional(bool condition, jsAst.Node node) {
@@ -437,38 +432,35 @@ class CodeEmitterTask extends CompilerTask {
jsAst.FunctionDeclaration buildFinishClass() {
String specProperty = '"${namer.nativeSpecProperty}"'; // "%"
- // function finishClass(cls) {
- jsAst.Fun fun = js.fun(['cls'], [
+ return js.statement('''
+ function finishClass(cls) {
- // TODO(8540): Remove this work around.
- /* Opera does not support 'getOwnPropertyNames'. Therefore we use
- hasOwnProperty instead. */
- js('var hasOwnProperty = Object.prototype.hasOwnProperty'),
+ // TODO(8540): Remove this work around.
+ // Opera does not support 'getOwnPropertyNames'. Therefore we use
+ // hasOwnProperty instead.
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
- // if (hasOwnProperty.call(finishedClasses, cls)) return;
- js.if_('hasOwnProperty.call(finishedClasses, cls)',
- js.return_()),
+ if (hasOwnProperty.call(finishedClasses, cls)) return;
- js('finishedClasses[cls] = true'),
+ finishedClasses[cls] = true;
- js('var superclass = pendingClasses[cls]'),
+ var superclass = pendingClasses[cls];
- // The superclass is only false (empty string) for Dart's 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.
- js.if_('!superclass || typeof superclass != "string"', js.return_()),
- js('finishClass(superclass)'),
- js('var constructor = allClasses[cls]'),
- js('var superConstructor = allClasses[superclass]'),
+ // 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];
- js.if_(js('!superConstructor'),
- js('superConstructor ='
- 'existingIsolateProperties[superclass]')),
+ if (!superConstructor)
+ superConstructor = existingIsolateProperties[superclass];
- js('var prototype = inheritFrom(constructor, superConstructor)'),
+ var prototype = inheritFrom(constructor, superConstructor);
- optional(!nativeClasses.isEmpty,
+ if (#) { // !nativeClasses.isEmpty,
// The property looks like this:
//
// HtmlElement: {
@@ -490,30 +482,34 @@ class CodeEmitterTask extends CompilerTask {
//
// The information is used to build tables referenced by
// getNativeInterceptor and custom element support.
- js.if_('hasOwnProperty.call(prototype, $specProperty)', [
- js('var nativeSpec = prototype[$specProperty].split(";")'),
- js.if_('nativeSpec[0]', [
- js('var tags = nativeSpec[0].split("|")'),
- js.for_('var i = 0', 'i < tags.length', 'i++', [
- js('init.interceptorsByTag[tags[i]] = constructor'),
- js('init.leafTags[tags[i]] = true')])]),
- js.if_('nativeSpec[1]', [
- js('tags = nativeSpec[1].split("|")'),
- optional(true, // User subclassing of native classes?
- js.if_('nativeSpec[2]', [
- js('var subclasses = nativeSpec[2].split("|")'),
- js.for_('var i = 0', 'i < subclasses.length', 'i++', [
- js('var subclass = allClasses[subclasses[i]]'),
- js('subclass.\$nativeSuperclassTag = '
- 'tags[0]')])])),
- js.for_('i = 0', 'i < tags.length', 'i++', [
- js('init.interceptorsByTag[tags[i]] = constructor'),
- js('init.leafTags[tags[i]] = false')])])]))
- ]);
-
- return new jsAst.FunctionDeclaration(
- new jsAst.VariableDeclaration('finishClass'),
- fun);
+ if (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++) {
+ init.interceptorsByTag[tags[i]] = constructor;
+ init.leafTags[tags[i]] = true;
+ }
+ }
+ 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++) {
+ init.interceptorsByTag[tags[i]] = constructor;
+ init.leafTags[tags[i]] = false;
+ }
+ }
+ }
+ }
+ }
+ }''', [!nativeClasses.isEmpty, true]);
}
jsAst.Fun get finishIsolateConstructorFunction {
@@ -540,80 +536,57 @@ class CodeEmitterTask extends CompilerTask {
Isolate.prototype = oldIsolate.prototype;
Isolate.prototype.constructor = Isolate;
Isolate.${namer.isolatePropertiesName} = isolateProperties;
- #
- #
+ if (#)
+ Isolate.$finishClassesProperty = oldIsolate.$finishClassesProperty;
+ if (#)
+ Isolate.makeConstantList = oldIsolate.makeConstantList;
return Isolate;
}''',
- [ optional(needsDefineClass,
- js('Isolate.$finishClassesProperty ='
- ' oldIsolate.$finishClassesProperty')),
- optional(hasMakeConstantList,
- js('Isolate.makeConstantList = oldIsolate.makeConstantList'))
- ]);
+ [ needsDefineClass, hasMakeConstantList ]);
}
jsAst.Fun get lazyInitializerFunction {
- // function(prototype, staticName, fieldName, getterName, lazyValue) {
- var parameters = <String>['prototype', 'staticName', 'fieldName',
- 'getterName', 'lazyValue'];
- return js.fun(parameters, addLazyInitializerLogic());
- }
-
- List addLazyInitializerLogic() {
String isolate = namer.currentIsolate;
String cyclicThrow = namer.isolateAccess(backend.getCyclicThrowHelper());
- var lazies = [];
- if (backend.rememberLazies) {
- lazies = [
- js.if_('!init.lazies', js('init.lazies = {}')),
- js('init.lazies[fieldName] = getterName')];
- }
- return lazies..addAll([
- js('var sentinelUndefined = {}'),
- js('var sentinelInProgress = {}'),
- js('prototype[fieldName] = sentinelUndefined'),
-
- // prototype[getterName] = function()
- js('prototype[getterName] = #', js.fun([], [
- js('var result = $isolate[fieldName]'),
-
- // try
- js.try_([
- js.if_('result === sentinelUndefined', [
- js('$isolate[fieldName] = sentinelInProgress'),
-
- // try
- js.try_([
- js('result = $isolate[fieldName] = lazyValue()'),
-
- ], finallyPart: [
- // Use try-finally, not try-catch/throw as it destroys the
- // stack trace.
-
- // if (result === sentinelUndefined)
- js.if_('result === sentinelUndefined', [
- // if ($isolate[fieldName] === sentinelInProgress)
- js.if_('$isolate[fieldName] === sentinelInProgress', [
- js('$isolate[fieldName] = null'),
- ])
- ])
- ])
- ], /* else */ [
- js.if_('result === sentinelInProgress',
- js('$cyclicThrow(staticName)')
- )
- ]),
-
- // return result;
- js.return_('result')
-
- ], finallyPart: [
- js('$isolate[getterName] = #',
- js.fun([], [js.return_('this[fieldName]')]))
- ])
- ]))
- ]);
+ return js('''
+ function (prototype, staticName, fieldName, getterName, lazyValue) {
+ if (#) {
+ if (!init.lazies) init.lazies = {};
+ init.lazies[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)
+ if ($isolate[fieldName] === sentinelInProgress)
+ $isolate[fieldName] = null;
+ }
+ } else {
+ if (result === sentinelInProgress)
+ $cyclicThrow(staticName);
+ }
+
+ return result;
+ } finally {
+ $isolate[getterName] = function() { return this[fieldName]; };
+ }
+ }
+ }
+ ''', [backend.rememberLazies]);
}
List buildDefineClassAndFinishClassFunctionsIfNecessary() {
@@ -628,7 +601,7 @@ class CodeEmitterTask extends CompilerTask {
List buildLazyInitializerFunctionIfNecessary() {
if (!needsLazyInitializer) return [];
- return [js('$lazyInitializerName = #', lazyInitializerFunction)];
+ return [js('# = #', [js(lazyInitializerName), lazyInitializerFunction])];
floitsch 2014/04/22 16:11:18 lazyInitializerName is a string. Do you have to ru
sra1 2014/04/23 02:33:50 It is a String, but it is not an identifier: "Isol
}
List buildFinishIsolateConstructor() {
@@ -760,14 +733,14 @@ class CodeEmitterTask extends CompilerTask {
jsAst.FunctionDeclaration buildPrecompiledFunction() {
// TODO(ahe): Compute a hash code.
String name = 'dart_precompiled';
-
- precompiledFunction.add(
- js.return_(
- new jsAst.ArrayInitializer.from(precompiledConstructorNames)));
- precompiledFunction.insert(0, js(r'var $desc'));
- return new jsAst.FunctionDeclaration(
- new jsAst.VariableDeclaration(name),
- js.fun([r'$collectedClasses'], precompiledFunction));
+ return js.statement('''
floitsch 2014/04/22 16:11:18 This should not be cached. Write TODO, that this s
sra1 2014/04/23 02:33:50 The name is dart_precompiled, from the previous li
+ function $name(\$collectedClasses) {
+ var \$desc;
+ #;
+ return #;
+ }''', [
+ precompiledFunction,
+ new jsAst.ArrayInitializer.from(precompiledConstructorNames)]);
}
void generateClass(ClassElement classElement, ClassBuilder properties) {
@@ -858,8 +831,9 @@ class CodeEmitterTask extends CompilerTask {
compiler.withCurrentElement(element, () {
Constant initialValue = handler.getInitialValueFor(element);
jsAst.Expression init =
- js('$isolateProperties.${namer.getNameOfGlobalField(element)} = #',
- constantEmitter.referenceInInitializationContext(initialValue));
+ js('$isolateProperties.# = #',
+ [namer.getNameOfGlobalField(element),
+ constantEmitter.referenceInInitializationContext(initialValue)]);
buffer.write(jsAst.prettyPrint(init, compiler));
buffer.write('$N');
});
@@ -883,17 +857,15 @@ class CodeEmitterTask extends CompilerTask {
// lazyInitializer(prototype, 'name', fieldName, getterName, initial);
// The name is used for error reporting. The 'initial' must be a
// closure that constructs the initial value.
- List<jsAst.Expression> arguments = <jsAst.Expression>[];
- arguments.add(js(isolateProperties));
- arguments.add(js.string(element.name));
- arguments.add(js.string(namer.getNameX(element)));
- arguments.add(js.string(namer.getLazyInitializerName(element)));
- arguments.add(code);
jsAst.Expression getter = buildLazyInitializedGetter(element);
- if (getter != null) {
- arguments.add(getter);
- }
- jsAst.Expression init = js(lazyInitializerName)(arguments);
+ jsAst.Expression init = js('#(#,#,#,#,#,#)',
+ [js(lazyInitializerName),
floitsch 2014/04/22 16:11:18 lazyInitializerName is a String. Why do we need to
sra1 2014/04/23 02:33:50 It is "Isolate.$lazy" Only strings in the form of
+ js(isolateProperties),
+ js.string(element.name),
+ js.string(namer.getNameX(element)),
+ js.string(namer.getLazyInitializerName(element)),
+ code,
+ getter == null ? [] : [getter]]);
buffer.write(jsAst.prettyPrint(init, compiler));
buffer.write("$N");
}
@@ -928,9 +900,9 @@ class CodeEmitterTask extends CompilerTask {
String name = namer.constantName(constant);
if (constant.isList) emitMakeConstantListIfNotEmitted(buffer);
- jsAst.Expression init = js(
- '${namer.globalObjectForConstant(constant)}.$name = #',
- constantInitializerExpression(constant));
+ jsAst.Expression init = js('#.# = #',
+ [namer.globalObjectForConstant(constant), name,
+ constantInitializerExpression(constant)]);
buffer.write(jsAst.prettyPrint(init, compiler));
buffer.write('$N');
}
@@ -1194,15 +1166,15 @@ class CodeEmitterTask extends CompilerTask {
}
void emitInitFunction(CodeBuffer buffer) {
- jsAst.Fun fun = js.fun([], [
- js('$isolateProperties = {}'),
- ]
- ..addAll(buildDefineClassAndFinishClassFunctionsIfNecessary())
- ..addAll(buildLazyInitializerFunctionIfNecessary())
- ..addAll(buildFinishIsolateConstructor())
- );
- jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration(
- new jsAst.VariableDeclaration('init'), fun);
+ jsAst.FunctionDeclaration decl = js.statement('''
+ function init() {
+ $isolateProperties = {};
+ #; #; #;
+ }''', [
+ buildDefineClassAndFinishClassFunctionsIfNecessary(),
+ buildLazyInitializerFunctionIfNecessary(),
+ buildFinishIsolateConstructor()]);
+
buffer.write(jsAst.prettyPrint(decl, compiler).getText());
if (compiler.enableMinification) buffer.write('\n');
}
@@ -1389,7 +1361,7 @@ mainBuffer.add(r'''
var map = new jsAst.ObjectInitializer(properties);
mainBuffer.write(
jsAst.prettyPrint(
- js('init.mangledNames = #', map).toStatement(), compiler));
+ js.statement('init.mangledNames = #', map), compiler));
if (compiler.enableMinification) {
mainBuffer.write(';');
}
@@ -1405,7 +1377,7 @@ mainBuffer.add(r'''
var map = new jsAst.ObjectInitializer(properties);
mainBuffer.write(
jsAst.prettyPrint(
- js('init.mangledGlobalNames = #', map).toStatement(),
+ js.statement('init.mangledGlobalNames = #', map),
compiler));
if (compiler.enableMinification) {
mainBuffer.write(';');

Powered by Google App Engine
This is Rietveld 408576698