Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Generates the code for all used classes in the program. Static fields (even | 8 * Generates the code for all used classes in the program. Static fields (even |
| 9 * in classes) are ignored, since they can be treated as non-class elements. | 9 * in classes) are ignored, since they can be treated as non-class elements. |
| 10 * | 10 * |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 141 const RANGE2_SIZE = RANGE2_LAST - RANGE2_FIRST + 1; | 141 const RANGE2_SIZE = RANGE2_LAST - RANGE2_FIRST + 1; |
| 142 const RANGE1_ADJUST = - (FIRST_FIELD_CODE - RANGE1_FIRST); | 142 const RANGE1_ADJUST = - (FIRST_FIELD_CODE - RANGE1_FIRST); |
| 143 const RANGE2_ADJUST = - (FIRST_FIELD_CODE + RANGE1_SIZE - RANGE2_FIRST); | 143 const RANGE2_ADJUST = - (FIRST_FIELD_CODE + RANGE1_SIZE - RANGE2_FIRST); |
| 144 const RANGE3_ADJUST = | 144 const RANGE3_ADJUST = |
| 145 - (FIRST_FIELD_CODE + RANGE1_SIZE + RANGE2_SIZE - RANGE3_FIRST); | 145 - (FIRST_FIELD_CODE + RANGE1_SIZE + RANGE2_SIZE - RANGE3_FIRST); |
| 146 | 146 |
| 147 String receiverParamName = compiler.enableMinification ? "r" : "receiver"; | 147 String receiverParamName = compiler.enableMinification ? "r" : "receiver"; |
| 148 String valueParamName = compiler.enableMinification ? "v" : "value"; | 148 String valueParamName = compiler.enableMinification ? "v" : "value"; |
| 149 String reflectableField = namer.reflectableField; | 149 String reflectableField = namer.reflectableField; |
| 150 | 150 |
| 151 // function generateAccessor(field, prototype, cls) { | 151 return js.statement(''' |
| 152 jsAst.Fun fun = js.fun(['fieldDescriptor', 'accessors', 'cls'], [ | 152 function generateAccessor(fieldDescriptor, accessors, cls) { |
| 153 js('var fieldInformation = fieldDescriptor.split("-")'), | 153 var fieldInformation = fieldDescriptor.split("-"); |
| 154 js('var field = fieldInformation[0]'), | 154 var field = fieldInformation[0]; |
| 155 js('var len = field.length'), | 155 var len = field.length; |
| 156 js('var code = field.charCodeAt(len - 1)'), | 156 var code = field.charCodeAt(len - 1); |
| 157 js('var reflectable'), | 157 var reflectable; |
| 158 js.if_('fieldInformation.length > 1', js('reflectable = true'), | 158 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
| |
| 159 js('reflectable = false')), | 159 else reflectable = false; |
| 160 js('code = ((code >= $RANGE1_FIRST) && (code <= $RANGE1_LAST))' | 160 code = ((code >= $RANGE1_FIRST) && (code <= $RANGE1_LAST)) |
| 161 ' ? code - $RANGE1_ADJUST' | 161 ? code - $RANGE1_ADJUST |
| 162 ' : ((code >= $RANGE2_FIRST) && (code <= $RANGE2_LAST))' | 162 : ((code >= $RANGE2_FIRST) && (code <= $RANGE2_LAST)) |
| 163 ' ? code - $RANGE2_ADJUST' | 163 ? code - $RANGE2_ADJUST |
| 164 ' : ((code >= $RANGE3_FIRST) && (code <= $RANGE3_LAST))' | 164 : ((code >= $RANGE3_FIRST) && (code <= $RANGE3_LAST)) |
| 165 ' ? code - $RANGE3_ADJUST' | 165 ? code - $RANGE3_ADJUST |
| 166 ' : $NO_FIELD_CODE'), | 166 : $NO_FIELD_CODE; |
| 167 | 167 |
| 168 // if (needsAccessor) { | 168 if (code) { // needsAccessor |
| 169 js.if_('code', [ | 169 var getterCode = code & 3; |
| 170 js('var getterCode = code & 3'), | 170 var setterCode = code >> 2; |
| 171 js('var setterCode = code >> 2'), | 171 var accessorName = field = field.substring(0, len - 1); |
| 172 js('var accessorName = field = field.substring(0, len - 1)'), | |
| 173 | 172 |
| 174 js('var divider = field.indexOf(":")'), | 173 var divider = field.indexOf(":"); |
| 175 js.if_('divider > 0', [ // Colon never in first position. | 174 if (divider > 0) { // Colon never in first position. |
| 176 js('accessorName = field.substring(0, divider)'), | 175 accessorName = field.substring(0, divider); |
| 177 js('field = field.substring(divider + 1)') | 176 field = field.substring(divider + 1); |
| 178 ]), | 177 } |
| 179 | 178 |
| 180 // if (needsGetter) { | 179 if (getterCode) { // needsGetter |
| 181 js.if_('getterCode', [ | 180 var args = (getterCode & 2) ? "$receiverParamName" : ""; |
| 182 js('var args = (getterCode & 2) ? "$receiverParamName" : ""'), | 181 var receiver = (getterCode & 1) ? "this" : "$receiverParamName"; |
| 183 js('var receiver = (getterCode & 1) ? "this" : "$receiverParamName"'), | 182 var body = "return " + receiver + "." + field; |
| 184 js('var body = "return " + receiver + "." + field'), | 183 var property = |
| 185 js('var property =' | 184 cls + ".prototype.${namer.getterPrefix}" + accessorName + "="; |
| 186 ' cls + ".prototype.${namer.getterPrefix}" + accessorName + "="'), | 185 var fn = "function(" + args + "){" + body + "}"; |
| 187 js('var fn = "function(" + args + "){" + body + "}"'), | 186 if (reflectable) |
| 188 js.if_( | 187 accessors.push(property + "\$reflectable(" + fn + ");\\n"); |
| 189 'reflectable', | 188 else |
| 190 js('accessors.push(property + "\$reflectable(" + fn + ");\\n")'), | 189 accessors.push(property + fn + ";\\n"); |
| 191 js('accessors.push(property + fn + ";\\n")')), | 190 } |
| 192 ]), | |
| 193 | 191 |
| 194 // if (needsSetter) { | 192 if (setterCode) { // needsSetter |
| 195 js.if_('setterCode', [ | 193 var args = (setterCode & 2) |
| 196 js('var args = (setterCode & 2)' | 194 ? "$receiverParamName,${_}$valueParamName" |
| 197 ' ? "$receiverParamName,${_}$valueParamName"' | 195 : "$valueParamName"; |
| 198 ' : "$valueParamName"'), | 196 var receiver = (setterCode & 1) ? "this" : "$receiverParamName"; |
| 199 js('var receiver = (setterCode & 1) ? "this" : "$receiverParamName"'), | 197 var body = receiver + "." + field + "$_=$_$valueParamName"; |
| 200 js('var body = receiver + "." + field + "$_=$_$valueParamName"'), | 198 var property = |
| 201 js('var property =' | 199 cls + ".prototype.${namer.setterPrefix}" + accessorName + "="; |
| 202 ' cls + ".prototype.${namer.setterPrefix}" + accessorName + "="'), | 200 var fn = "function(" + args + "){" + body + "}"; |
| 203 js('var fn = "function(" + args + "){" + body + "}"'), | 201 if (reflectable) |
| 204 js.if_( | 202 accessors.push(property + "\$reflectable(" + fn + ");\\n"); |
| 205 'reflectable', | 203 else |
| 206 js('accessors.push(property + "\$reflectable(" + fn + ");\\n")'), | 204 accessors.push(property + fn + ";\\n"); |
| 207 js('accessors.push(property + fn + ";\\n")')), | 205 } |
| 208 ]), | 206 } |
| 209 | 207 |
| 210 ]), | 208 return field; |
| 211 | 209 }'''); |
| 212 // return field; | |
| 213 js.return_('field') | |
| 214 ]); | |
| 215 | |
| 216 return new jsAst.FunctionDeclaration( | |
| 217 new jsAst.VariableDeclaration('generateAccessor'), | |
| 218 fun); | |
| 219 } | 210 } |
| 220 | 211 |
| 221 List get defineClassFunction { | 212 List get defineClassFunction { |
| 222 // First the class name, then the field names in an array and the members | 213 // First the class name, then the field names in an array and the members |
| 223 // (inside an Object literal). | 214 // (inside an Object literal). |
| 224 // The caller can also pass in the constructor as a function if needed. | 215 // The caller can also pass in the constructor as a function if needed. |
| 225 // | 216 // |
| 226 // Example: | 217 // Example: |
| 227 // defineClass("A", ["x", "y"], { | 218 // defineClass("A", ["x", "y"], { |
| 228 // foo$1: function(y) { | 219 // foo$1: function(y) { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 297 // - it contains all (local) members. | 288 // - it contains all (local) members. |
| 298 // - its internal prototype (__proto__) points to the superclass' | 289 // - its internal prototype (__proto__) points to the superclass' |
| 299 // prototype field. | 290 // prototype field. |
| 300 // - the prototype's constructor field points to the JavaScript | 291 // - the prototype's constructor field points to the JavaScript |
| 301 // constructor. | 292 // constructor. |
| 302 // For engines where we have access to the '__proto__' we can manipulate | 293 // For engines where we have access to the '__proto__' we can manipulate |
| 303 // the object literal directly. For other engines we have to create a new | 294 // the object literal directly. For other engines we have to create a new |
| 304 // object and copy over the members. | 295 // object and copy over the members. |
| 305 | 296 |
| 306 String reflectableField = namer.reflectableField; | 297 String reflectableField = namer.reflectableField; |
| 307 List<jsAst.Node> statements = [ | |
| 308 js('var pendingClasses = {}'), | |
| 309 js.if_('!init.allClasses', js('init.allClasses = {}')), | |
| 310 js('var allClasses = init.allClasses'), | |
| 311 | 298 |
| 312 optional( | 299 return js(''' |
| 313 DEBUG_FAST_OBJECTS, | 300 function(collectedClasses, isolateProperties, existingIsolateProperties) { |
| 314 js('print("Number of classes: "' | 301 var pendingClasses = {}; |
| 315 r' + Object.getOwnPropertyNames($$).length)')), | 302 if (!init.allClasses) init.allClasses = {}; |
| 303 var allClasses = init.allClasses; | |
| 316 | 304 |
| 317 js('var hasOwnProperty = Object.prototype.hasOwnProperty'), | 305 if (#) // DEBUG_FAST_OBJECTS |
| 306 print("Number of classes: " + | |
| 307 Object.getOwnPropertyNames(\$\$).length); | |
| 318 | 308 |
| 319 js.if_('typeof dart_precompiled == "function"', | 309 var hasOwnProperty = Object.prototype.hasOwnProperty; |
| 320 [js('var constructors = dart_precompiled(collectedClasses)')], | |
| 321 | 310 |
| 322 [js('var combinedConstructorFunction = "function \$reflectable(fn){' | 311 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
| |
| 323 'fn.$reflectableField=1;return fn};\\n"+ "var \$desc;\\n"'), | 312 var constructors = dart_precompiled(collectedClasses); |
| 324 js('var constructorsList = []')]), | 313 } else { |
| 325 js.forIn('cls', 'collectedClasses', [ | 314 var combinedConstructorFunction = |
| 326 js.if_('hasOwnProperty.call(collectedClasses, cls)', [ | 315 "function \$reflectable(fn){fn.$reflectableField=1;return fn};\\n"+ |
| 327 js('var desc = collectedClasses[cls]'), | 316 "var \$desc;\\n"; |
| 328 js.if_('desc instanceof Array', js('desc = desc[1]')), | 317 var constructorsList = []; |
| 318 } | |
| 329 | 319 |
| 330 /* The 'fields' are either a constructor function or a | 320 for (var cls in collectedClasses) { |
| 331 * string encoding fields, constructor and superclass. Get | 321 if (hasOwnProperty.call(collectedClasses, cls)) { |
| 332 * the superclass and the fields in the format | 322 var desc = collectedClasses[cls]; |
| 333 * '[name/]Super;field1,field2' | 323 if (desc instanceof Array) desc = desc[1]; |
| 334 * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor. | |
| 335 * The 'name/' is optional and contains the name that should be used | |
| 336 * when printing the runtime type string. It is used, for example, to | |
| 337 * print the runtime type JSInt as 'int'. | |
| 338 */ | |
| 339 js('var classData = desc["${namer.classDescriptorProperty}"], ' | |
| 340 'supr, name = cls, fields = classData'), | |
| 341 optional( | |
| 342 backend.hasRetainedMetadata, | |
| 343 js.if_('typeof classData == "object" && ' | |
| 344 'classData instanceof Array', | |
| 345 [js('classData = fields = classData[0]')])), | |
| 346 | 324 |
| 347 js.if_('typeof classData == "string"', [ | 325 /* The 'fields' are either a constructor function or a |
| 348 js('var split = classData.split("/")'), | 326 * string encoding fields, constructor and superclass. Get |
| 349 js.if_('split.length == 2', [ | 327 * the superclass and the fields in the format |
| 350 js('name = split[0]'), | 328 * '[name/]Super;field1,field2' |
| 351 js('fields = split[1]') | 329 * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor. |
| 352 ]) | 330 * The 'name/' is optional and contains the name that should be used |
| 353 ]), | 331 * when printing the runtime type string. It is used, for example, |
| 332 * to print the runtime type JSInt as 'int'. | |
| 333 */ | |
| 334 var classData = desc["${namer.classDescriptorProperty}"], | |
| 335 supr, name = cls, fields = classData; | |
| 336 if (#) // backend.hasRetainedMetadata | |
| 337 if (typeof classData == "object" && | |
| 338 classData instanceof Array) { | |
| 339 classData = fields = classData[0]; | |
| 340 } | |
| 341 if (typeof classData == "string") { | |
| 342 var split = classData.split("/"); | |
| 343 if (split.length == 2) { | |
| 344 name = split[0]; | |
| 345 fields = split[1]; | |
| 346 } | |
| 347 } | |
| 354 | 348 |
| 355 js('var s = fields.split(";")'), | 349 var s = fields.split(";"); |
| 356 js('fields = s[1] == "" ? [] : s[1].split(",")'), | 350 fields = s[1] == "" ? [] : s[1].split(","); |
| 357 js('supr = s[0]'), | 351 supr = s[0]; |
| 358 js('split = supr.split(":")'), | 352 split = supr.split(":"); |
| 359 js.if_('split.length == 2', [ | 353 if (split.length == 2) { |
| 360 js('supr = split[0]'), | 354 supr = split[0]; |
| 361 js('var functionSignature = split[1]'), | 355 var functionSignature = split[1]; |
| 362 js.if_('functionSignature', | 356 if (functionSignature) |
| 363 js('desc.\$signature = #', | 357 desc.\$signature = (function(s) { |
| 364 js.fun('s', | 358 return function(){ return init.metadata[s]; }; |
| 365 js.return_(js.fun([], js.return_('init.metadata[s]'))))( | 359 })(functionSignature); |
| 366 js('functionSignature')))) | 360 } |
| 367 ]), | |
| 368 | 361 |
| 369 optional(needsMixinSupport, js.if_('supr && supr.indexOf("+") > 0', [ | 362 if (#) // needsMixinSupport |
| 370 js('s = supr.split("+")'), | 363 if (supr && supr.indexOf("+") > 0) { |
| 371 js('supr = s[0]'), | 364 s = supr.split("+"); |
| 372 js('var mixin = collectedClasses[s[1]]'), | 365 supr = s[0]; |
| 373 js.if_('mixin instanceof Array', js('mixin = mixin[1]')), | 366 var mixin = collectedClasses[s[1]]; |
| 374 js.forIn('d', 'mixin', [ | 367 if (mixin instanceof Array) mixin = mixin[1]; |
| 375 js.if_('hasOwnProperty.call(mixin, d)' | 368 for(var d in mixin) { |
| 376 '&& !hasOwnProperty.call(desc, d)', | 369 if (hasOwnProperty.call(mixin, d) && |
| 377 js('desc[d] = mixin[d]')) | 370 !hasOwnProperty.call(desc, d)) |
| 378 ]), | 371 desc[d] = mixin[d]; |
| 379 ])), | 372 } |
| 373 } | |
| 380 | 374 |
| 381 js.if_('typeof dart_precompiled != "function"', | 375 if (typeof dart_precompiled != "function") { |
| 382 [js('combinedConstructorFunction +=' | 376 combinedConstructorFunction += defineClass(name, cls, fields); |
| 383 ' defineClass(name, cls, fields)'), | 377 constructorsList.push(cls); |
| 384 js('constructorsList.push(cls)')]), | 378 } |
| 385 js.if_('supr', js('pendingClasses[cls] = supr')) | 379 if (supr) pendingClasses[cls] = supr; |
| 386 ]) | 380 } |
| 387 ]), | 381 } |
| 388 js.statement(''' | |
| 389 if (typeof dart_precompiled != "function") { | |
| 390 combinedConstructorFunction += | |
| 391 "return [\\n " + constructorsList.join(",\\n ") + "\\n]"; | |
| 392 var constructors = | |
| 393 new Function("\$collectedClasses", combinedConstructorFunction) | |
| 394 (collectedClasses); | |
| 395 combinedConstructorFunction = null; | |
| 396 }'''), | |
| 397 js.for_('var i = 0', 'i < constructors.length', 'i++', [ | |
| 398 js('var constructor = constructors[i]'), | |
| 399 js('var cls = constructor.name'), | |
| 400 js('var desc = collectedClasses[cls]'), | |
| 401 js('var globalObject = isolateProperties'), | |
| 402 js.if_('desc instanceof Array', [ | |
| 403 js('globalObject = desc[0] || isolateProperties'), | |
| 404 js('desc = desc[1]') | |
| 405 ]), | |
| 406 optional(backend.isTreeShakingDisabled, | |
| 407 js('constructor["${namer.metadataField}"] = desc')), | |
| 408 js('allClasses[cls] = constructor'), | |
| 409 js('globalObject[cls] = constructor'), | |
| 410 ]), | |
| 411 js('constructors = null'), | |
| 412 | 382 |
| 413 js('var finishedClasses = {}'), | 383 if (typeof dart_precompiled != "function") { |
| 414 js('init.interceptorsByTag = Object.create(null)'), | 384 combinedConstructorFunction += |
| 415 js('init.leafTags = {}'), | 385 "return [\\n " + constructorsList.join(",\\n ") + "\\n]"; |
| 386 var constructors = | |
| 387 new Function("\$collectedClasses", combinedConstructorFunction) | |
| 388 (collectedClasses); | |
| 389 combinedConstructorFunction = null; | |
| 390 } | |
| 416 | 391 |
| 417 buildFinishClass(), | 392 for (var i = 0; i < constructors.length; i++) { |
| 418 ]; | 393 var constructor = constructors[i]; |
| 394 var cls = constructor.name; | |
| 395 var desc = collectedClasses[cls]; | |
| 396 var globalObject = isolateProperties; | |
| 397 if (desc instanceof Array) { | |
| 398 globalObject = desc[0] || isolateProperties; | |
| 399 desc = desc[1]; | |
| 400 } | |
| 401 if (#) //backend.isTreeShakingDisabled, | |
| 402 constructor["${namer.metadataField}"] = desc; | |
| 403 allClasses[cls] = constructor; | |
| 404 globalObject[cls] = constructor; | |
| 405 } | |
| 419 | 406 |
| 420 nsmEmitter.addTrivialNsmHandlers(statements); | 407 constructors = null; |
| 421 | 408 |
| 422 statements.add( | 409 var finishedClasses = {}; |
| 423 js.statement('for (var cls in pendingClasses) finishClass(cls);') | 410 init.interceptorsByTag = Object.create(null); |
| 424 ); | 411 init.leafTags = {}; |
| 425 | 412 |
| 426 // function(collectedClasses, | 413 #; // buildFinishClass(), |
| 427 // isolateProperties, | 414 |
| 428 // existingIsolateProperties) | 415 #; // buildTrivialNsmHandlers() |
| 429 return js.fun(['collectedClasses', 'isolateProperties', | 416 |
| 430 'existingIsolateProperties'], statements); | 417 for (var cls in pendingClasses) finishClass(cls); |
| 418 }''', [ | |
| 419 DEBUG_FAST_OBJECTS, | |
| 420 backend.hasRetainedMetadata, | |
| 421 needsMixinSupport, | |
| 422 backend.isTreeShakingDisabled, | |
| 423 buildFinishClass(), | |
| 424 nsmEmitter.buildTrivialNsmHandlers()]); | |
| 425 | |
| 431 } | 426 } |
| 432 | 427 |
| 433 jsAst.Node optional(bool condition, jsAst.Node node) { | 428 jsAst.Node optional(bool condition, jsAst.Node node) { |
| 434 return condition ? node : new jsAst.EmptyStatement(); | 429 return condition ? node : new jsAst.EmptyStatement(); |
| 435 } | 430 } |
| 436 | 431 |
| 437 jsAst.FunctionDeclaration buildFinishClass() { | 432 jsAst.FunctionDeclaration buildFinishClass() { |
| 438 String specProperty = '"${namer.nativeSpecProperty}"'; // "%" | 433 String specProperty = '"${namer.nativeSpecProperty}"'; // "%" |
| 439 | 434 |
| 440 // function finishClass(cls) { | 435 return js.statement(''' |
| 441 jsAst.Fun fun = js.fun(['cls'], [ | 436 function finishClass(cls) { |
| 442 | 437 |
| 443 // TODO(8540): Remove this work around. | 438 // TODO(8540): Remove this work around. |
| 444 /* Opera does not support 'getOwnPropertyNames'. Therefore we use | 439 // Opera does not support 'getOwnPropertyNames'. Therefore we use |
| 445 hasOwnProperty instead. */ | 440 // hasOwnProperty instead. |
| 446 js('var hasOwnProperty = Object.prototype.hasOwnProperty'), | 441 var hasOwnProperty = Object.prototype.hasOwnProperty; |
| 447 | 442 |
| 448 // if (hasOwnProperty.call(finishedClasses, cls)) return; | 443 if (hasOwnProperty.call(finishedClasses, cls)) return; |
| 449 js.if_('hasOwnProperty.call(finishedClasses, cls)', | |
| 450 js.return_()), | |
| 451 | 444 |
| 452 js('finishedClasses[cls] = true'), | 445 finishedClasses[cls] = true; |
| 453 | 446 |
| 454 js('var superclass = pendingClasses[cls]'), | 447 var superclass = pendingClasses[cls]; |
| 455 | 448 |
| 456 // The superclass is only false (empty string) for Dart's Object class. | 449 // The superclass is only false (empty string) for the Dart Object |
| 457 // The minifier together with noSuchMethod can put methods on the | 450 // class. The minifier together with noSuchMethod can put methods on |
| 458 // Object.prototype object, and they show through here, so we check that | 451 // the Object.prototype object, and they show through here, so we check |
| 459 // we have a string. | 452 // that we have a string. |
| 460 js.if_('!superclass || typeof superclass != "string"', js.return_()), | 453 if (!superclass || typeof superclass != "string") return; |
| 461 js('finishClass(superclass)'), | 454 finishClass(superclass); |
| 462 js('var constructor = allClasses[cls]'), | 455 var constructor = allClasses[cls]; |
| 463 js('var superConstructor = allClasses[superclass]'), | 456 var superConstructor = allClasses[superclass]; |
| 464 | 457 |
| 465 js.if_(js('!superConstructor'), | 458 if (!superConstructor) |
| 466 js('superConstructor =' | 459 superConstructor = existingIsolateProperties[superclass]; |
| 467 'existingIsolateProperties[superclass]')), | |
| 468 | 460 |
| 469 js('var prototype = inheritFrom(constructor, superConstructor)'), | 461 var prototype = inheritFrom(constructor, superConstructor); |
| 470 | 462 |
| 471 optional(!nativeClasses.isEmpty, | 463 if (#) { // !nativeClasses.isEmpty, |
| 472 // The property looks like this: | 464 // The property looks like this: |
| 473 // | 465 // |
| 474 // HtmlElement: { | 466 // HtmlElement: { |
| 475 // "%": "HTMLDivElement|HTMLAnchorElement;HTMLElement;FancyButton" | 467 // "%": "HTMLDivElement|HTMLAnchorElement;HTMLElement;FancyButton" |
| 476 // | 468 // |
| 477 // The first two semicolon-separated parts contain dispatch tags, the | 469 // The first two semicolon-separated parts contain dispatch tags, the |
| 478 // third contains the JavaScript names for classes. | 470 // third contains the JavaScript names for classes. |
| 479 // | 471 // |
| 480 // The tags indicate that JavaScript objects with the dispatch tags | 472 // The tags indicate that JavaScript objects with the dispatch tags |
| 481 // (usually constructor names) HTMLDivElement, HTMLAnchorElement and | 473 // (usually constructor names) HTMLDivElement, HTMLAnchorElement and |
| 482 // HTMLElement all map to the Dart native class named HtmlElement. | 474 // HTMLElement all map to the Dart native class named HtmlElement. |
| 483 // The first set is for effective leaf nodes in the hierarchy, the | 475 // The first set is for effective leaf nodes in the hierarchy, the |
| 484 // second set is non-leaf nodes. | 476 // second set is non-leaf nodes. |
| 485 // | 477 // |
| 486 // The third part contains the JavaScript names of Dart classes that | 478 // The third part contains the JavaScript names of Dart classes that |
| 487 // extend the native class. Here, FancyButton extends HtmlElement, so | 479 // extend the native class. Here, FancyButton extends HtmlElement, so |
| 488 // the runtime needs to know that window.HTMLElement.prototype is the | 480 // the runtime needs to know that window.HTMLElement.prototype is the |
| 489 // prototype that needs to be extended in creating the custom element. | 481 // prototype that needs to be extended in creating the custom element. |
| 490 // | 482 // |
| 491 // The information is used to build tables referenced by | 483 // The information is used to build tables referenced by |
| 492 // getNativeInterceptor and custom element support. | 484 // getNativeInterceptor and custom element support. |
| 493 js.if_('hasOwnProperty.call(prototype, $specProperty)', [ | 485 if (hasOwnProperty.call(prototype, $specProperty)) { |
| 494 js('var nativeSpec = prototype[$specProperty].split(";")'), | 486 var nativeSpec = prototype[$specProperty].split(";"); |
| 495 js.if_('nativeSpec[0]', [ | 487 if (nativeSpec[0]) { |
| 496 js('var tags = nativeSpec[0].split("|")'), | 488 var tags = nativeSpec[0].split("|"); |
| 497 js.for_('var i = 0', 'i < tags.length', 'i++', [ | 489 for (var i = 0; i < tags.length; i++) { |
| 498 js('init.interceptorsByTag[tags[i]] = constructor'), | 490 init.interceptorsByTag[tags[i]] = constructor; |
| 499 js('init.leafTags[tags[i]] = true')])]), | 491 init.leafTags[tags[i]] = true; |
| 500 js.if_('nativeSpec[1]', [ | 492 } |
| 501 js('tags = nativeSpec[1].split("|")'), | 493 } |
| 502 optional(true, // User subclassing of native classes? | 494 if (nativeSpec[1]) { |
| 503 js.if_('nativeSpec[2]', [ | 495 tags = nativeSpec[1].split("|"); |
| 504 js('var subclasses = nativeSpec[2].split("|")'), | 496 if (#) { // User subclassing of native classes? |
| 505 js.for_('var i = 0', 'i < subclasses.length', 'i++', [ | 497 if (nativeSpec[2]) { |
| 506 js('var subclass = allClasses[subclasses[i]]'), | 498 var subclasses = nativeSpec[2].split("|"); |
| 507 js('subclass.\$nativeSuperclassTag = ' | 499 for (var i = 0; i < subclasses.length; i++) { |
| 508 'tags[0]')])])), | 500 var subclass = allClasses[subclasses[i]]; |
| 509 js.for_('i = 0', 'i < tags.length', 'i++', [ | 501 subclass.\$nativeSuperclassTag = tags[0]; |
| 510 js('init.interceptorsByTag[tags[i]] = constructor'), | 502 } |
| 511 js('init.leafTags[tags[i]] = false')])])])) | 503 } |
| 512 ]); | 504 for (i = 0; i < tags.length; i++) { |
| 513 | 505 init.interceptorsByTag[tags[i]] = constructor; |
| 514 return new jsAst.FunctionDeclaration( | 506 init.leafTags[tags[i]] = false; |
| 515 new jsAst.VariableDeclaration('finishClass'), | 507 } |
| 516 fun); | 508 } |
| 509 } | |
| 510 } | |
| 511 } | |
| 512 }''', [!nativeClasses.isEmpty, true]); | |
| 517 } | 513 } |
| 518 | 514 |
| 519 jsAst.Fun get finishIsolateConstructorFunction { | 515 jsAst.Fun get finishIsolateConstructorFunction { |
| 520 // We replace the old Isolate function with a new one that initializes | 516 // We replace the old Isolate function with a new one that initializes |
| 521 // all its fields with the initial (and often final) value of all globals. | 517 // all its fields with the initial (and often final) value of all globals. |
| 522 // | 518 // |
| 523 // We also copy over old values like the prototype, and the | 519 // We also copy over old values like the prototype, and the |
| 524 // isolateProperties themselves. | 520 // isolateProperties themselves. |
| 525 return js(''' | 521 return js(''' |
| 526 function (oldIsolate) { | 522 function (oldIsolate) { |
| 527 var isolateProperties = oldIsolate.${namer.isolatePropertiesName}; | 523 var isolateProperties = oldIsolate.${namer.isolatePropertiesName}; |
| 528 function Isolate() { | 524 function Isolate() { |
| 529 var hasOwnProperty = Object.prototype.hasOwnProperty; | 525 var hasOwnProperty = Object.prototype.hasOwnProperty; |
| 530 for (var staticName in isolateProperties) | 526 for (var staticName in isolateProperties) |
| 531 if (hasOwnProperty.call(isolateProperties, staticName)) | 527 if (hasOwnProperty.call(isolateProperties, staticName)) |
| 532 this[staticName] = isolateProperties[staticName]; | 528 this[staticName] = isolateProperties[staticName]; |
| 533 // Use the newly created object as prototype. In Chrome, | 529 // Use the newly created object as prototype. In Chrome, |
| 534 // this creates a hidden class for the object and makes | 530 // this creates a hidden class for the object and makes |
| 535 // sure it is fast to access. | 531 // sure it is fast to access. |
| 536 function ForceEfficientMap() {} | 532 function ForceEfficientMap() {} |
| 537 ForceEfficientMap.prototype = this; | 533 ForceEfficientMap.prototype = this; |
| 538 new ForceEfficientMap(); | 534 new ForceEfficientMap(); |
| 539 } | 535 } |
| 540 Isolate.prototype = oldIsolate.prototype; | 536 Isolate.prototype = oldIsolate.prototype; |
| 541 Isolate.prototype.constructor = Isolate; | 537 Isolate.prototype.constructor = Isolate; |
| 542 Isolate.${namer.isolatePropertiesName} = isolateProperties; | 538 Isolate.${namer.isolatePropertiesName} = isolateProperties; |
| 543 # | 539 if (#) |
| 544 # | 540 Isolate.$finishClassesProperty = oldIsolate.$finishClassesProperty; |
| 541 if (#) | |
| 542 Isolate.makeConstantList = oldIsolate.makeConstantList; | |
| 545 return Isolate; | 543 return Isolate; |
| 546 }''', | 544 }''', |
| 547 [ optional(needsDefineClass, | 545 [ needsDefineClass, hasMakeConstantList ]); |
| 548 js('Isolate.$finishClassesProperty =' | |
| 549 ' oldIsolate.$finishClassesProperty')), | |
| 550 optional(hasMakeConstantList, | |
| 551 js('Isolate.makeConstantList = oldIsolate.makeConstantList')) | |
| 552 ]); | |
| 553 } | 546 } |
| 554 | 547 |
| 555 jsAst.Fun get lazyInitializerFunction { | 548 jsAst.Fun get lazyInitializerFunction { |
| 556 // function(prototype, staticName, fieldName, getterName, lazyValue) { | |
| 557 var parameters = <String>['prototype', 'staticName', 'fieldName', | |
| 558 'getterName', 'lazyValue']; | |
| 559 return js.fun(parameters, addLazyInitializerLogic()); | |
| 560 } | |
| 561 | |
| 562 List addLazyInitializerLogic() { | |
| 563 String isolate = namer.currentIsolate; | 549 String isolate = namer.currentIsolate; |
| 564 String cyclicThrow = namer.isolateAccess(backend.getCyclicThrowHelper()); | 550 String cyclicThrow = namer.isolateAccess(backend.getCyclicThrowHelper()); |
| 565 var lazies = []; | |
| 566 if (backend.rememberLazies) { | |
| 567 lazies = [ | |
| 568 js.if_('!init.lazies', js('init.lazies = {}')), | |
| 569 js('init.lazies[fieldName] = getterName')]; | |
| 570 } | |
| 571 | 551 |
| 572 return lazies..addAll([ | 552 return js(''' |
| 573 js('var sentinelUndefined = {}'), | 553 function (prototype, staticName, fieldName, getterName, lazyValue) { |
| 574 js('var sentinelInProgress = {}'), | 554 if (#) { |
| 575 js('prototype[fieldName] = sentinelUndefined'), | 555 if (!init.lazies) init.lazies = {}; |
| 556 init.lazies[fieldName] = getterName; | |
| 557 } | |
| 576 | 558 |
| 577 // prototype[getterName] = function() | 559 var sentinelUndefined = {}; |
| 578 js('prototype[getterName] = #', js.fun([], [ | 560 var sentinelInProgress = {}; |
| 579 js('var result = $isolate[fieldName]'), | 561 prototype[fieldName] = sentinelUndefined; |
| 580 | 562 |
| 581 // try | 563 prototype[getterName] = function () { |
| 582 js.try_([ | 564 var result = $isolate[fieldName]; |
| 583 js.if_('result === sentinelUndefined', [ | 565 try { |
| 584 js('$isolate[fieldName] = sentinelInProgress'), | 566 if (result === sentinelUndefined) { |
| 567 $isolate[fieldName] = sentinelInProgress; | |
| 585 | 568 |
| 586 // try | 569 try { |
| 587 js.try_([ | 570 result = $isolate[fieldName] = lazyValue(); |
| 588 js('result = $isolate[fieldName] = lazyValue()'), | 571 } finally { |
| 572 // Use try-finally, not try-catch/throw as it destroys the | |
| 573 // stack trace. | |
| 574 if (result === sentinelUndefined) | |
| 575 if ($isolate[fieldName] === sentinelInProgress) | |
| 576 $isolate[fieldName] = null; | |
| 577 } | |
| 578 } else { | |
| 579 if (result === sentinelInProgress) | |
| 580 $cyclicThrow(staticName); | |
| 581 } | |
| 589 | 582 |
| 590 ], finallyPart: [ | 583 return result; |
| 591 // Use try-finally, not try-catch/throw as it destroys the | 584 } finally { |
| 592 // stack trace. | 585 $isolate[getterName] = function() { return this[fieldName]; }; |
| 593 | 586 } |
| 594 // if (result === sentinelUndefined) | 587 } |
| 595 js.if_('result === sentinelUndefined', [ | 588 } |
| 596 // if ($isolate[fieldName] === sentinelInProgress) | 589 ''', [backend.rememberLazies]); |
| 597 js.if_('$isolate[fieldName] === sentinelInProgress', [ | |
| 598 js('$isolate[fieldName] = null'), | |
| 599 ]) | |
| 600 ]) | |
| 601 ]) | |
| 602 ], /* else */ [ | |
| 603 js.if_('result === sentinelInProgress', | |
| 604 js('$cyclicThrow(staticName)') | |
| 605 ) | |
| 606 ]), | |
| 607 | |
| 608 // return result; | |
| 609 js.return_('result') | |
| 610 | |
| 611 ], finallyPart: [ | |
| 612 js('$isolate[getterName] = #', | |
| 613 js.fun([], [js.return_('this[fieldName]')])) | |
| 614 ]) | |
| 615 ])) | |
| 616 ]); | |
| 617 } | 590 } |
| 618 | 591 |
| 619 List buildDefineClassAndFinishClassFunctionsIfNecessary() { | 592 List buildDefineClassAndFinishClassFunctionsIfNecessary() { |
| 620 if (!needsDefineClass) return []; | 593 if (!needsDefineClass) return []; |
| 621 return defineClassFunction | 594 return defineClassFunction |
| 622 ..addAll(buildInheritFrom()) | 595 ..addAll(buildInheritFrom()) |
| 623 ..addAll([ | 596 ..addAll([ |
| 624 js('$finishClassesName = #', finishClassesFunction) | 597 js('$finishClassesName = #', finishClassesFunction) |
| 625 ]); | 598 ]); |
| 626 } | 599 } |
| 627 | 600 |
| 628 List buildLazyInitializerFunctionIfNecessary() { | 601 List buildLazyInitializerFunctionIfNecessary() { |
| 629 if (!needsLazyInitializer) return []; | 602 if (!needsLazyInitializer) return []; |
| 630 | 603 |
| 631 return [js('$lazyInitializerName = #', lazyInitializerFunction)]; | 604 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
| |
| 632 } | 605 } |
| 633 | 606 |
| 634 List buildFinishIsolateConstructor() { | 607 List buildFinishIsolateConstructor() { |
| 635 return [ | 608 return [ |
| 636 js('$finishIsolateConstructorName = #', finishIsolateConstructorFunction) | 609 js('$finishIsolateConstructorName = #', finishIsolateConstructorFunction) |
| 637 ]; | 610 ]; |
| 638 } | 611 } |
| 639 | 612 |
| 640 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { | 613 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { |
| 641 String isolate = namer.isolateName; | 614 String isolate = namer.isolateName; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 753 | 726 |
| 754 String namedParametersAsReflectionNames(Selector selector) { | 727 String namedParametersAsReflectionNames(Selector selector) { |
| 755 if (selector.getOrderedNamedArguments().isEmpty) return ''; | 728 if (selector.getOrderedNamedArguments().isEmpty) return ''; |
| 756 String names = selector.getOrderedNamedArguments().join(':'); | 729 String names = selector.getOrderedNamedArguments().join(':'); |
| 757 return ':$names'; | 730 return ':$names'; |
| 758 } | 731 } |
| 759 | 732 |
| 760 jsAst.FunctionDeclaration buildPrecompiledFunction() { | 733 jsAst.FunctionDeclaration buildPrecompiledFunction() { |
| 761 // TODO(ahe): Compute a hash code. | 734 // TODO(ahe): Compute a hash code. |
| 762 String name = 'dart_precompiled'; | 735 String name = 'dart_precompiled'; |
| 763 | 736 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
| |
| 764 precompiledFunction.add( | 737 function $name(\$collectedClasses) { |
| 765 js.return_( | 738 var \$desc; |
| 766 new jsAst.ArrayInitializer.from(precompiledConstructorNames))); | 739 #; |
| 767 precompiledFunction.insert(0, js(r'var $desc')); | 740 return #; |
| 768 return new jsAst.FunctionDeclaration( | 741 }''', [ |
| 769 new jsAst.VariableDeclaration(name), | 742 precompiledFunction, |
| 770 js.fun([r'$collectedClasses'], precompiledFunction)); | 743 new jsAst.ArrayInitializer.from(precompiledConstructorNames)]); |
| 771 } | 744 } |
| 772 | 745 |
| 773 void generateClass(ClassElement classElement, ClassBuilder properties) { | 746 void generateClass(ClassElement classElement, ClassBuilder properties) { |
| 774 compiler.withCurrentElement(classElement, () { | 747 compiler.withCurrentElement(classElement, () { |
| 775 classEmitter.generateClass( | 748 classEmitter.generateClass( |
| 776 classElement, properties, additionalProperties[classElement]); | 749 classElement, properties, additionalProperties[classElement]); |
| 777 }); | 750 }); |
| 778 } | 751 } |
| 779 | 752 |
| 780 /** | 753 /** |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 851 Iterable<VariableElement> staticNonFinalFields = | 824 Iterable<VariableElement> staticNonFinalFields = |
| 852 handler.getStaticNonFinalFieldsForEmission(); | 825 handler.getStaticNonFinalFieldsForEmission(); |
| 853 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { | 826 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { |
| 854 // [:interceptedNames:] is handled in [emitInterceptedNames]. | 827 // [:interceptedNames:] is handled in [emitInterceptedNames]. |
| 855 if (element == backend.interceptedNames) continue; | 828 if (element == backend.interceptedNames) continue; |
| 856 // `mapTypeToInterceptor` is handled in [emitMapTypeToInterceptor]. | 829 // `mapTypeToInterceptor` is handled in [emitMapTypeToInterceptor]. |
| 857 if (element == backend.mapTypeToInterceptor) continue; | 830 if (element == backend.mapTypeToInterceptor) continue; |
| 858 compiler.withCurrentElement(element, () { | 831 compiler.withCurrentElement(element, () { |
| 859 Constant initialValue = handler.getInitialValueFor(element); | 832 Constant initialValue = handler.getInitialValueFor(element); |
| 860 jsAst.Expression init = | 833 jsAst.Expression init = |
| 861 js('$isolateProperties.${namer.getNameOfGlobalField(element)} = #', | 834 js('$isolateProperties.# = #', |
| 862 constantEmitter.referenceInInitializationContext(initialValue)); | 835 [namer.getNameOfGlobalField(element), |
| 836 constantEmitter.referenceInInitializationContext(initialValue)]); | |
| 863 buffer.write(jsAst.prettyPrint(init, compiler)); | 837 buffer.write(jsAst.prettyPrint(init, compiler)); |
| 864 buffer.write('$N'); | 838 buffer.write('$N'); |
| 865 }); | 839 }); |
| 866 } | 840 } |
| 867 } | 841 } |
| 868 | 842 |
| 869 void emitLazilyInitializedStaticFields(CodeBuffer buffer) { | 843 void emitLazilyInitializedStaticFields(CodeBuffer buffer) { |
| 870 JavaScriptConstantCompiler handler = backend.constants; | 844 JavaScriptConstantCompiler handler = backend.constants; |
| 871 List<VariableElement> lazyFields = | 845 List<VariableElement> lazyFields = |
| 872 handler.getLazilyInitializedFieldsForEmission(); | 846 handler.getLazilyInitializedFieldsForEmission(); |
| 873 if (!lazyFields.isEmpty) { | 847 if (!lazyFields.isEmpty) { |
| 874 needsLazyInitializer = true; | 848 needsLazyInitializer = true; |
| 875 for (VariableElement element in Elements.sortedByPosition(lazyFields)) { | 849 for (VariableElement element in Elements.sortedByPosition(lazyFields)) { |
| 876 jsAst.Expression code = backend.generatedCode[element]; | 850 jsAst.Expression code = backend.generatedCode[element]; |
| 877 // The code is null if we ended up not needing the lazily | 851 // The code is null if we ended up not needing the lazily |
| 878 // initialized field after all because of constant folding | 852 // initialized field after all because of constant folding |
| 879 // before code generation. | 853 // before code generation. |
| 880 if (code == null) continue; | 854 if (code == null) continue; |
| 881 // The code only computes the initial value. We build the lazy-check | 855 // The code only computes the initial value. We build the lazy-check |
| 882 // here: | 856 // here: |
| 883 // lazyInitializer(prototype, 'name', fieldName, getterName, initial); | 857 // lazyInitializer(prototype, 'name', fieldName, getterName, initial); |
| 884 // The name is used for error reporting. The 'initial' must be a | 858 // The name is used for error reporting. The 'initial' must be a |
| 885 // closure that constructs the initial value. | 859 // closure that constructs the initial value. |
| 886 List<jsAst.Expression> arguments = <jsAst.Expression>[]; | |
| 887 arguments.add(js(isolateProperties)); | |
| 888 arguments.add(js.string(element.name)); | |
| 889 arguments.add(js.string(namer.getNameX(element))); | |
| 890 arguments.add(js.string(namer.getLazyInitializerName(element))); | |
| 891 arguments.add(code); | |
| 892 jsAst.Expression getter = buildLazyInitializedGetter(element); | 860 jsAst.Expression getter = buildLazyInitializedGetter(element); |
| 893 if (getter != null) { | 861 jsAst.Expression init = js('#(#,#,#,#,#,#)', |
| 894 arguments.add(getter); | 862 [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
| |
| 895 } | 863 js(isolateProperties), |
| 896 jsAst.Expression init = js(lazyInitializerName)(arguments); | 864 js.string(element.name), |
| 865 js.string(namer.getNameX(element)), | |
| 866 js.string(namer.getLazyInitializerName(element)), | |
| 867 code, | |
| 868 getter == null ? [] : [getter]]); | |
| 897 buffer.write(jsAst.prettyPrint(init, compiler)); | 869 buffer.write(jsAst.prettyPrint(init, compiler)); |
| 898 buffer.write("$N"); | 870 buffer.write("$N"); |
| 899 } | 871 } |
| 900 } | 872 } |
| 901 } | 873 } |
| 902 | 874 |
| 903 jsAst.Expression buildLazyInitializedGetter(VariableElement element) { | 875 jsAst.Expression buildLazyInitializedGetter(VariableElement element) { |
| 904 // Nothing to do, the 'lazy' function will create the getter. | 876 // Nothing to do, the 'lazy' function will create the getter. |
| 905 return null; | 877 return null; |
| 906 } | 878 } |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 921 && constantUnit == null) { | 893 && constantUnit == null) { |
| 922 // The back-end introduces some constants, like "InterceptorConstant" or | 894 // The back-end introduces some constants, like "InterceptorConstant" or |
| 923 // some list constants. They are emitted in the main output-unit, and | 895 // some list constants. They are emitted in the main output-unit, and |
| 924 // ignored otherwise. | 896 // ignored otherwise. |
| 925 // TODO(sigurdm): We should track those constants. | 897 // TODO(sigurdm): We should track those constants. |
| 926 continue; | 898 continue; |
| 927 } | 899 } |
| 928 | 900 |
| 929 String name = namer.constantName(constant); | 901 String name = namer.constantName(constant); |
| 930 if (constant.isList) emitMakeConstantListIfNotEmitted(buffer); | 902 if (constant.isList) emitMakeConstantListIfNotEmitted(buffer); |
| 931 jsAst.Expression init = js( | 903 jsAst.Expression init = js('#.# = #', |
| 932 '${namer.globalObjectForConstant(constant)}.$name = #', | 904 [namer.globalObjectForConstant(constant), name, |
| 933 constantInitializerExpression(constant)); | 905 constantInitializerExpression(constant)]); |
| 934 buffer.write(jsAst.prettyPrint(init, compiler)); | 906 buffer.write(jsAst.prettyPrint(init, compiler)); |
| 935 buffer.write('$N'); | 907 buffer.write('$N'); |
| 936 } | 908 } |
| 937 } | 909 } |
| 938 | 910 |
| 939 bool isConstantInlinedOrAlreadyEmitted(Constant constant) { | 911 bool isConstantInlinedOrAlreadyEmitted(Constant constant) { |
| 940 if (constant.isFunction) return true; // Already emitted. | 912 if (constant.isFunction) return true; // Already emitted. |
| 941 if (constant.isPrimitive) return true; // Inlined. | 913 if (constant.isPrimitive) return true; // Inlined. |
| 942 if (constant.isDummy) return true; // Inlined. | 914 if (constant.isDummy) return true; // Inlined. |
| 943 // The name is null when the constant is already a JS constant. | 915 // The name is null when the constant is already a JS constant. |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1187 } else { | 1159 } else { |
| 1188 outputClassLists.putIfAbsent( | 1160 outputClassLists.putIfAbsent( |
| 1189 compiler.deferredLoadTask.outputUnitForElement(element), | 1161 compiler.deferredLoadTask.outputUnitForElement(element), |
| 1190 () => new List<ClassElement>()) | 1162 () => new List<ClassElement>()) |
| 1191 .add(element); | 1163 .add(element); |
| 1192 } | 1164 } |
| 1193 } | 1165 } |
| 1194 } | 1166 } |
| 1195 | 1167 |
| 1196 void emitInitFunction(CodeBuffer buffer) { | 1168 void emitInitFunction(CodeBuffer buffer) { |
| 1197 jsAst.Fun fun = js.fun([], [ | 1169 jsAst.FunctionDeclaration decl = js.statement(''' |
| 1198 js('$isolateProperties = {}'), | 1170 function init() { |
| 1199 ] | 1171 $isolateProperties = {}; |
| 1200 ..addAll(buildDefineClassAndFinishClassFunctionsIfNecessary()) | 1172 #; #; #; |
| 1201 ..addAll(buildLazyInitializerFunctionIfNecessary()) | 1173 }''', [ |
| 1202 ..addAll(buildFinishIsolateConstructor()) | 1174 buildDefineClassAndFinishClassFunctionsIfNecessary(), |
| 1203 ); | 1175 buildLazyInitializerFunctionIfNecessary(), |
| 1204 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( | 1176 buildFinishIsolateConstructor()]); |
| 1205 new jsAst.VariableDeclaration('init'), fun); | 1177 |
| 1206 buffer.write(jsAst.prettyPrint(decl, compiler).getText()); | 1178 buffer.write(jsAst.prettyPrint(decl, compiler).getText()); |
| 1207 if (compiler.enableMinification) buffer.write('\n'); | 1179 if (compiler.enableMinification) buffer.write('\n'); |
| 1208 } | 1180 } |
| 1209 | 1181 |
| 1210 void emitConvertToFastObjectFunction() { | 1182 void emitConvertToFastObjectFunction() { |
| 1211 // Create an instance that uses 'properties' as prototype. This should make | 1183 // Create an instance that uses 'properties' as prototype. This should make |
| 1212 // 'properties' a fast object. | 1184 // 'properties' a fast object. |
| 1213 mainBuffer.add(r'''function convertToFastObject(properties) { | 1185 mainBuffer.add(r'''function convertToFastObject(properties) { |
| 1214 function MyClass() {}; | 1186 function MyClass() {}; |
| 1215 MyClass.prototype = properties; | 1187 MyClass.prototype = properties; |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1382 var keys = mangledFieldNames.keys.toList(); | 1354 var keys = mangledFieldNames.keys.toList(); |
| 1383 keys.sort(); | 1355 keys.sort(); |
| 1384 var properties = []; | 1356 var properties = []; |
| 1385 for (String key in keys) { | 1357 for (String key in keys) { |
| 1386 var value = js.string('${mangledFieldNames[key]}'); | 1358 var value = js.string('${mangledFieldNames[key]}'); |
| 1387 properties.add(new jsAst.Property(js.string(key), value)); | 1359 properties.add(new jsAst.Property(js.string(key), value)); |
| 1388 } | 1360 } |
| 1389 var map = new jsAst.ObjectInitializer(properties); | 1361 var map = new jsAst.ObjectInitializer(properties); |
| 1390 mainBuffer.write( | 1362 mainBuffer.write( |
| 1391 jsAst.prettyPrint( | 1363 jsAst.prettyPrint( |
| 1392 js('init.mangledNames = #', map).toStatement(), compiler)); | 1364 js.statement('init.mangledNames = #', map), compiler)); |
| 1393 if (compiler.enableMinification) { | 1365 if (compiler.enableMinification) { |
| 1394 mainBuffer.write(';'); | 1366 mainBuffer.write(';'); |
| 1395 } | 1367 } |
| 1396 } | 1368 } |
| 1397 if (!mangledGlobalFieldNames.isEmpty) { | 1369 if (!mangledGlobalFieldNames.isEmpty) { |
| 1398 var keys = mangledGlobalFieldNames.keys.toList(); | 1370 var keys = mangledGlobalFieldNames.keys.toList(); |
| 1399 keys.sort(); | 1371 keys.sort(); |
| 1400 var properties = []; | 1372 var properties = []; |
| 1401 for (String key in keys) { | 1373 for (String key in keys) { |
| 1402 var value = js.string('${mangledGlobalFieldNames[key]}'); | 1374 var value = js.string('${mangledGlobalFieldNames[key]}'); |
| 1403 properties.add(new jsAst.Property(js.string(key), value)); | 1375 properties.add(new jsAst.Property(js.string(key), value)); |
| 1404 } | 1376 } |
| 1405 var map = new jsAst.ObjectInitializer(properties); | 1377 var map = new jsAst.ObjectInitializer(properties); |
| 1406 mainBuffer.write( | 1378 mainBuffer.write( |
| 1407 jsAst.prettyPrint( | 1379 jsAst.prettyPrint( |
| 1408 js('init.mangledGlobalNames = #', map).toStatement(), | 1380 js.statement('init.mangledGlobalNames = #', map), |
| 1409 compiler)); | 1381 compiler)); |
| 1410 if (compiler.enableMinification) { | 1382 if (compiler.enableMinification) { |
| 1411 mainBuffer.write(';'); | 1383 mainBuffer.write(';'); |
| 1412 } | 1384 } |
| 1413 } | 1385 } |
| 1414 mainBuffer | 1386 mainBuffer |
| 1415 ..write('(') | 1387 ..write('(') |
| 1416 ..write( | 1388 ..write( |
| 1417 jsAst.prettyPrint( | 1389 jsAst.prettyPrint( |
| 1418 getReflectionDataParser(classesCollector, backend), | 1390 getReflectionDataParser(classesCollector, backend), |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1729 String sourceMap = sourceMapBuilder.build(); | 1701 String sourceMap = sourceMapBuilder.build(); |
| 1730 compiler.outputProvider(name, 'js.map') | 1702 compiler.outputProvider(name, 'js.map') |
| 1731 ..add(sourceMap) | 1703 ..add(sourceMap) |
| 1732 ..close(); | 1704 ..close(); |
| 1733 } | 1705 } |
| 1734 | 1706 |
| 1735 void registerReadTypeVariable(TypeVariableElement element) { | 1707 void registerReadTypeVariable(TypeVariableElement element) { |
| 1736 readTypeVariables.add(element); | 1708 readTypeVariables.add(element); |
| 1737 } | 1709 } |
| 1738 } | 1710 } |
| OLD | NEW |