| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 // TODO(ahe): Share these with js_helper.dart. | 7 // TODO(ahe): Share these with js_helper.dart. |
| 8 const FUNCTION_INDEX = 0; | 8 const FUNCTION_INDEX = 0; |
| 9 const NAME_INDEX = 1; | 9 const NAME_INDEX = 1; |
| 10 const CALL_NAME_INDEX = 2; | 10 const CALL_NAME_INDEX = 2; |
| 11 const REQUIRED_PARAMETER_INDEX = 3; | 11 const REQUIRED_PARAMETER_INDEX = 3; |
| 12 const OPTIONAL_PARAMETER_INDEX = 4; | 12 const OPTIONAL_PARAMETER_INDEX = 4; |
| 13 const DEFAULT_ARGUMENTS_INDEX = 5; | 13 const DEFAULT_ARGUMENTS_INDEX = 5; |
| 14 | 14 |
| 15 const bool VALIDATE_DATA = false; | 15 const bool VALIDATE_DATA = false; |
| 16 | 16 |
| 17 jsAst.Expression getReflectionDataParser(OldEmitter oldEmitter, | 17 // TODO(ahe): This code should be integrated in CodeEmitterTask.finishClasses. |
| 18 JavaScriptBackend backend) { | 18 jsAst.Expression getReflectionDataParser(String classesCollector, |
| 19 JavaScriptBackend backend) { |
| 19 Namer namer = backend.namer; | 20 Namer namer = backend.namer; |
| 20 Compiler compiler = backend.compiler; | 21 Compiler compiler = backend.compiler; |
| 21 CodeEmitterTask emitter = backend.emitter; | 22 CodeEmitterTask emitter = backend.emitter; |
| 22 | 23 |
| 23 String metadataField = '"${namer.metadataField}"'; | 24 String metadataField = '"${namer.metadataField}"'; |
| 24 String reflectableField = namer.reflectableField; | 25 String reflectableField = namer.reflectableField; |
| 25 String reflectionInfoField = namer.reflectionInfoField; | 26 String reflectionInfoField = namer.reflectionInfoField; |
| 26 String reflectionNameField = namer.reflectionNameField; | 27 String reflectionNameField = namer.reflectionNameField; |
| 27 String metadataIndexField = namer.metadataIndexField; | 28 String metadataIndexField = namer.metadataIndexField; |
| 28 String defaultValuesField = namer.defaultValuesField; | 29 String defaultValuesField = namer.defaultValuesField; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 40 jsAst.Expression staticsAccess = | 41 jsAst.Expression staticsAccess = |
| 41 emitter.generateEmbeddedGlobalAccess(embeddedNames.STATICS); | 42 emitter.generateEmbeddedGlobalAccess(embeddedNames.STATICS); |
| 42 jsAst.Expression interceptedNamesAccess = | 43 jsAst.Expression interceptedNamesAccess = |
| 43 emitter.generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTED_NAMES); | 44 emitter.generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTED_NAMES); |
| 44 jsAst.Expression mangledGlobalNamesAccess = | 45 jsAst.Expression mangledGlobalNamesAccess = |
| 45 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); | 46 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); |
| 46 jsAst.Expression mangledNamesAccess = | 47 jsAst.Expression mangledNamesAccess = |
| 47 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES); | 48 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES); |
| 48 jsAst.Expression librariesAccess = | 49 jsAst.Expression librariesAccess = |
| 49 emitter.generateEmbeddedGlobalAccess(embeddedNames.LIBRARIES); | 50 emitter.generateEmbeddedGlobalAccess(embeddedNames.LIBRARIES); |
| 50 jsAst.Expression metadataAccess = | |
| 51 emitter.generateEmbeddedGlobalAccess(embeddedNames.METADATA); | |
| 52 | 51 |
| 53 jsAst.Statement header = js.statement(''' | 52 jsAst.Statement header = js.statement(''' |
| 54 // [map] returns an object literal that V8 shouldn not try to optimize with a | 53 // [map] returns an object literal that V8 shouldn not try to optimize with a |
| 55 // hidden class. This prevents a potential performance problem where V8 tries | 54 // hidden class. This prevents a potential performance problem where V8 tries |
| 56 // to build a hidden class for an object used as a hashMap. | 55 // to build a hidden class for an object used as a hashMap. |
| 57 // It requires fewer characters to declare a variable as a parameter than | 56 // It requires fewer characters to declare a variable as a parameter than |
| 58 // with `var`. | 57 // with `var`. |
| 59 function map(x){x=Object.create(null);x.x=0;delete x.x;return x} | 58 function map(x){x=Object.create(null);x.x=0;delete x.x;return x} |
| 60 '''); | 59 '''); |
| 61 | 60 |
| 62 jsAst.Statement processClassData = js.statement('''{ | |
| 63 function processClassData(cls, descriptor, processedClasses) { | |
| 64 var newDesc = {}; | |
| 65 var previousProperty; | |
| 66 for (var property in descriptor) { | |
| 67 if (!hasOwnProperty.call(descriptor, property)) continue; | |
| 68 var firstChar = property.substring(0, 1); | |
| 69 if (property === "static") { | |
| 70 processStatics(#embeddedStatics[cls] = descriptor[property], | |
| 71 processedClasses); | |
| 72 } else if (firstChar === "+") { | |
| 73 mangledNames[previousProperty] = property.substring(1); | |
| 74 var flag = descriptor[property]; | |
| 75 if (flag > 0) | |
| 76 descriptor[previousProperty].$reflectableField = flag; | |
| 77 } else if (firstChar === "@" && property !== "@") { | |
| 78 newDesc[property.substring(1)][$metadataField] = descriptor[property]; | |
| 79 } else if (firstChar === "*") { | |
| 80 newDesc[previousProperty].$defaultValuesField = descriptor[property]; | |
| 81 var optionalMethods = newDesc.$methodsWithOptionalArgumentsField; | |
| 82 if (!optionalMethods) { | |
| 83 newDesc.$methodsWithOptionalArgumentsField = optionalMethods={} | |
| 84 } | |
| 85 optionalMethods[property] = previousProperty; | |
| 86 } else { | |
| 87 var elem = descriptor[property]; | |
| 88 if (property !== "${namer.classDescriptorProperty}" && | |
| 89 elem != null && | |
| 90 elem.constructor === Array && | |
| 91 property !== "<>") { | |
| 92 addStubs(newDesc, elem, property, false, descriptor, []); | |
| 93 } else { | |
| 94 newDesc[previousProperty = property] = elem; | |
| 95 } | |
| 96 } | |
| 97 } | |
| 98 | |
| 99 /* The 'fields' are either a constructor function or a | |
| 100 * string encoding fields, constructor and superclass. Gets the | |
| 101 * superclass and fields in the format | |
| 102 * 'Super;field1,field2' | |
| 103 * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor. | |
| 104 */ | |
| 105 var classData = newDesc["${namer.classDescriptorProperty}"], | |
| 106 split, supr, fields = classData; | |
| 107 | |
| 108 if (#hasRetainedMetadata) | |
| 109 if (typeof classData == "object" && | |
| 110 classData instanceof Array) { | |
| 111 classData = fields = classData[0]; | |
| 112 } | |
| 113 // ${ClassBuilder.fieldEncodingDescription}. | |
| 114 var s = fields.split(";"); | |
| 115 fields = s[1] == "" ? [] : s[1].split(","); | |
| 116 supr = s[0]; | |
| 117 // ${ClassBuilder.functionTypeEncodingDescription}. | |
| 118 split = supr.split(":"); | |
| 119 if (split.length == 2) { | |
| 120 supr = split[0]; | |
| 121 var functionSignature = split[1]; | |
| 122 if (functionSignature) | |
| 123 newDesc.${namer.operatorSignature} = function(s) { | |
| 124 return function() { | |
| 125 return #metadata[s]; | |
| 126 }; | |
| 127 }(functionSignature); | |
| 128 } | |
| 129 | |
| 130 if (supr) processedClasses.pending[cls] = supr; | |
| 131 if (#notInCspMode) { | |
| 132 processedClasses.combinedConstructorFunction += defineClass(cls, fields); | |
| 133 processedClasses.constructorsList.push(cls); | |
| 134 } | |
| 135 processedClasses.collected[cls] = [globalObject, newDesc]; | |
| 136 classes.push(cls); | |
| 137 } | |
| 138 }''', {'embeddedStatics': staticsAccess, | |
| 139 'hasRetainedMetadata': backend.hasRetainedMetadata, | |
| 140 'metadata': metadataAccess, | |
| 141 'notInCspMode': !compiler.useContentSecurityPolicy}); | |
| 142 | |
| 143 jsAst.Statement processStatics = js.statement(''' | 61 jsAst.Statement processStatics = js.statement(''' |
| 144 function processStatics(descriptor, processedClasses) { | 62 function processStatics(descriptor) { |
| 145 for (var property in descriptor) { | 63 for (var property in descriptor) { |
| 146 if (!hasOwnProperty.call(descriptor, property)) continue; | 64 if (!hasOwnProperty.call(descriptor, property)) continue; |
| 147 if (property === "${namer.classDescriptorProperty}") continue; | 65 if (property === "${namer.classDescriptorProperty}") continue; |
| 148 var element = descriptor[property]; | 66 var element = descriptor[property]; |
| 149 var firstChar = property.substring(0, 1); | 67 var firstChar = property.substring(0, 1); |
| 150 var previousProperty; | 68 var previousProperty; |
| 151 if (firstChar === "+") { | 69 if (firstChar === "+") { |
| 152 mangledGlobalNames[previousProperty] = property.substring(1); | 70 mangledGlobalNames[previousProperty] = property.substring(1); |
| 153 var flag = descriptor[property]; | 71 var flag = descriptor[property]; |
| 154 if (flag > 0) | 72 if (flag > 0) |
| 155 descriptor[previousProperty].$reflectableField = flag; | 73 descriptor[previousProperty].$reflectableField = flag; |
| 156 if (element && element.length) | 74 if (element && element.length) |
| 157 #typeInformation[previousProperty] = element; | 75 #[previousProperty] = element; // embedded typeInformation. |
| 158 } else if (firstChar === "@") { | 76 } else if (firstChar === "@") { |
| 159 property = property.substring(1); | 77 property = property.substring(1); |
| 160 ${namer.currentIsolate}[property][$metadataField] = element; | 78 ${namer.currentIsolate}[property][$metadataField] = element; |
| 161 } else if (firstChar === "*") { | 79 } else if (firstChar === "*") { |
| 162 globalObject[previousProperty].$defaultValuesField = element; | 80 globalObject[previousProperty].$defaultValuesField = element; |
| 163 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField; | 81 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField; |
| 164 if (!optionalMethods) { | 82 if (!optionalMethods) { |
| 165 descriptor.$methodsWithOptionalArgumentsField = optionalMethods = {} | 83 descriptor.$methodsWithOptionalArgumentsField = optionalMethods = {} |
| 166 } | 84 } |
| 167 optionalMethods[property] = previousProperty; | 85 optionalMethods[property] = previousProperty; |
| 168 } else if (typeof element === "function") { | 86 } else if (typeof element === "function") { |
| 169 globalObject[previousProperty = property] = element; | 87 globalObject[previousProperty = property] = element; |
| 170 functions.push(property); | 88 functions.push(property); |
| 171 #globalFunctions[property] = element; | 89 #[property] = element; // embedded globalFunctions. |
| 172 } else if (element.constructor === Array) { | 90 } else if (element.constructor === Array) { |
| 173 addStubs(globalObject, element, property, | 91 addStubs(globalObject, element, property, |
| 174 true, descriptor, functions); | 92 true, descriptor, functions); |
| 175 } else { | 93 } else { |
| 176 // We will not enter this case if no classes are defined. | 94 previousProperty = property; |
| 177 if (#hasClasses) { | 95 var newDesc = {}; |
| 178 previousProperty = property; | 96 var previousProp; |
| 179 processClassData(property, element, processedClasses); | 97 for (var prop in element) { |
| 98 if (!hasOwnProperty.call(element, prop)) continue; |
| 99 firstChar = prop.substring(0, 1); |
| 100 if (prop === "static") { |
| 101 processStatics(#[property] = element[prop]); // embedded statics. |
| 102 } else if (firstChar === "+") { |
| 103 mangledNames[previousProp] = prop.substring(1); |
| 104 var flag = element[prop]; |
| 105 if (flag > 0) |
| 106 element[previousProp].$reflectableField = flag; |
| 107 } else if (firstChar === "@" && prop !== "@") { |
| 108 newDesc[prop.substring(1)][$metadataField] = element[prop]; |
| 109 } else if (firstChar === "*") { |
| 110 newDesc[previousProp].$defaultValuesField = element[prop]; |
| 111 var optionalMethods = newDesc.$methodsWithOptionalArgumentsField; |
| 112 if (!optionalMethods) { |
| 113 newDesc.$methodsWithOptionalArgumentsField = optionalMethods={} |
| 114 } |
| 115 optionalMethods[prop] = previousProp; |
| 116 } else { |
| 117 var elem = element[prop]; |
| 118 if (prop !== "${namer.classDescriptorProperty}" && |
| 119 elem != null && |
| 120 elem.constructor === Array && |
| 121 prop !== "<>") { |
| 122 addStubs(newDesc, elem, prop, false, element, []); |
| 123 } else { |
| 124 newDesc[previousProp = prop] = elem; |
| 125 } |
| 126 } |
| 180 } | 127 } |
| 128 $classesCollector[property] = [globalObject, newDesc]; |
| 129 classes.push(property); |
| 181 } | 130 } |
| 182 } | 131 } |
| 183 } | 132 } |
| 184 ''', {'typeInformation': typeInformationAccess, | 133 ''', [typeInformationAccess, globalFunctionsAccess, staticsAccess]); |
| 185 'globalFunctions': globalFunctionsAccess, | |
| 186 'hasClasses': oldEmitter.needsClassSupport}); | |
| 187 | 134 |
| 188 | 135 |
| 189 /** | 136 /** |
| 190 * See [dart2js.js_emitter.ContainerBuilder.addMemberMethod] for format of | 137 * See [dart2js.js_emitter.ContainerBuilder.addMemberMethod] for format of |
| 191 * [array]. | 138 * [array]. |
| 192 */ | 139 */ |
| 193 jsAst.Statement addStubs = js.statement(''' | 140 jsAst.Statement addStubs = js.statement(''' |
| 194 function addStubs(descriptor, array, name, isStatic, | 141 function addStubs(descriptor, array, name, isStatic, |
| 195 originalDescriptor, functions) { | 142 originalDescriptor, functions) { |
| 196 var index = $FUNCTION_INDEX, alias = array[index], f; | 143 var index = $FUNCTION_INDEX, alias = array[index], f; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 } | 219 } |
| 273 ''', {'globalFunctions' : globalFunctionsAccess, | 220 ''', {'globalFunctions' : globalFunctionsAccess, |
| 274 'interceptedNames': interceptedNamesAccess, | 221 'interceptedNames': interceptedNamesAccess, |
| 275 'mangledGlobalNames': mangledGlobalNamesAccess, | 222 'mangledGlobalNames': mangledGlobalNamesAccess, |
| 276 'mangledNames': mangledNamesAccess}); | 223 'mangledNames': mangledNamesAccess}); |
| 277 | 224 |
| 278 List<jsAst.Statement> tearOffCode = buildTearOffCode(backend); | 225 List<jsAst.Statement> tearOffCode = buildTearOffCode(backend); |
| 279 | 226 |
| 280 jsAst.Statement init = js.statement('''{ | 227 jsAst.Statement init = js.statement('''{ |
| 281 var functionCounter = 0; | 228 var functionCounter = 0; |
| 282 if (!#libraries) #libraries = []; | 229 if (!#) # = []; // embedded libraries. |
| 283 if (!#mangledNames) #mangledNames = map(); | 230 if (!#) # = map(); // embedded mangledNames. |
| 284 if (!#mangledGlobalNames) #mangledGlobalNames = map(); | 231 if (!#) # = map(); // embedded mangledGlobalNames. |
| 285 if (!#statics) #statics = map(); | 232 if (!#) # = map(); // embedded statics. |
| 286 if (!#typeInformation) #typeInformation = map(); | 233 if (!#) # = map(); // embedded typeInformation. |
| 287 if (!#globalFunctions) #globalFunctions = map(); | 234 if (!#) # = map(); // embedded globalFunctions. |
| 288 if (!#interceptedNames) #interceptedNames = map(); | 235 if (!#) # = map(); // embedded interceptedNames. |
| 289 var libraries = #libraries; | 236 var libraries = #; // embeded libraries. |
| 290 var mangledNames = #mangledNames; | 237 var mangledNames = #; // embedded mangledNames. |
| 291 var mangledGlobalNames = #mangledGlobalNames; | 238 var mangledGlobalNames = #; // embedded mangledGlobalNames. |
| 292 var hasOwnProperty = Object.prototype.hasOwnProperty; | 239 var hasOwnProperty = Object.prototype.hasOwnProperty; |
| 293 var length = reflectionData.length; | 240 var length = reflectionData.length; |
| 294 var processedClasses = Object.create(null); | |
| 295 processedClasses.collected = Object.create(null); | |
| 296 processedClasses.pending = Object.create(null); | |
| 297 if (#notInCspMode) { | |
| 298 processedClasses.constructorsList = []; | |
| 299 // For every class processed [processedClasses.combinedConstructorFunction] | |
| 300 // will be updated with the corresponding constructor function. | |
| 301 processedClasses.combinedConstructorFunction = | |
| 302 "function \$reflectable(fn){fn.$reflectableField=1;return fn};\\n"+ | |
| 303 "var \$desc;\\n"; | |
| 304 } | |
| 305 for (var i = 0; i < length; i++) { | 241 for (var i = 0; i < length; i++) { |
| 306 var data = reflectionData[i]; | 242 var data = reflectionData[i]; |
| 307 | 243 |
| 308 // [data] contains these elements: | 244 // [data] contains these elements: |
| 309 // 0. The library name (not unique). | 245 // 0. The library name (not unique). |
| 310 // 1. The library URI (unique). | 246 // 1. The library URI (unique). |
| 311 // 2. A function returning the metadata associated with this library. | 247 // 2. A function returning the metadata associated with this library. |
| 312 // 3. The global object to use for this library. | 248 // 3. The global object to use for this library. |
| 313 // 4. An object literal listing the members of the library. | 249 // 4. An object literal listing the members of the library. |
| 314 // 5. This element is optional and if present it is true and signals that this | 250 // 5. This element is optional and if present it is true and signals that this |
| 315 // library is the root library (see dart:mirrors IsolateMirror.rootLibrary). | 251 // library is the root library (see dart:mirrors IsolateMirror.rootLibrary). |
| 316 // | 252 // |
| 317 // The entries of [data] are built in [assembleProgram] above. | 253 // The entries of [data] are built in [assembleProgram] above. |
| 318 | 254 |
| 319 var name = data[0]; | 255 var name = data[0]; |
| 320 var uri = data[1]; | 256 var uri = data[1]; |
| 321 var metadata = data[2]; | 257 var metadata = data[2]; |
| 322 var globalObject = data[3]; | 258 var globalObject = data[3]; |
| 323 var descriptor = data[4]; | 259 var descriptor = data[4]; |
| 324 var isRoot = !!data[5]; | 260 var isRoot = !!data[5]; |
| 325 var fields = descriptor && descriptor["${namer.classDescriptorProperty}"]; | 261 var fields = descriptor && descriptor["${namer.classDescriptorProperty}"]; |
| 326 if (fields instanceof Array) fields = fields[0]; | 262 if (fields instanceof Array) fields = fields[0]; |
| 327 var classes = []; | 263 var classes = []; |
| 328 var functions = []; | 264 var functions = []; |
| 329 processStatics(descriptor, processedClasses); | 265 processStatics(descriptor); |
| 330 libraries.push([name, uri, classes, functions, metadata, fields, isRoot, | 266 libraries.push([name, uri, classes, functions, metadata, fields, isRoot, |
| 331 globalObject]); | 267 globalObject]); |
| 332 } | 268 } |
| 333 if (#needsClassSupport) finishClasses(processedClasses); | 269 }''', [librariesAccess, librariesAccess, |
| 334 }''', {'libraries': librariesAccess, | 270 mangledNamesAccess, mangledNamesAccess, |
| 335 'mangledNames': mangledNamesAccess, | 271 mangledGlobalNamesAccess, mangledGlobalNamesAccess, |
| 336 'mangledGlobalNames': mangledGlobalNamesAccess, | 272 staticsAccess, staticsAccess, |
| 337 'statics': staticsAccess, | 273 typeInformationAccess, typeInformationAccess, |
| 338 'typeInformation': typeInformationAccess, | 274 globalFunctionsAccess, globalFunctionsAccess, |
| 339 'globalFunctions': globalFunctionsAccess, | 275 interceptedNamesAccess, interceptedNamesAccess, |
| 340 'interceptedNames': interceptedNamesAccess, | 276 librariesAccess, |
| 341 'notInCspMode': !compiler.useContentSecurityPolicy, | 277 mangledNamesAccess, |
| 342 'needsClassSupport': oldEmitter.needsClassSupport}); | 278 mangledGlobalNamesAccess]); |
| 343 | |
| 344 jsAst.Expression allClassesAccess = | |
| 345 emitter.generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); | |
| 346 | |
| 347 String specProperty = '"${namer.nativeSpecProperty}"'; // "%" | |
| 348 | |
| 349 // Class descriptions are collected in a JS object. | |
| 350 // 'finishClasses' takes all collected descriptions and sets up | |
| 351 // the prototype. | |
| 352 // Once set up, the constructors prototype field satisfy: | |
| 353 // - it contains all (local) members. | |
| 354 // - its internal prototype (__proto__) points to the superclass' | |
| 355 // prototype field. | |
| 356 // - the prototype's constructor field points to the JavaScript | |
| 357 // constructor. | |
| 358 // For engines where we have access to the '__proto__' we can manipulate | |
| 359 // the object literal directly. For other engines we have to create a new | |
| 360 // object and copy over the members. | |
| 361 jsAst.Statement finishClasses = js.statement('''{ | |
| 362 function finishClasses(processedClasses) { | |
| 363 if (#debugFastObjects) | |
| 364 print("Number of classes: " + | |
| 365 Object.getOwnPropertyNames(processedClasses.collected).length); | |
| 366 | |
| 367 var allClasses = #allClasses; | |
| 368 | |
| 369 if (#inCspMode) { | |
| 370 constructors = dart_precompiled(processedClasses.collected); | |
| 371 } | |
| 372 | |
| 373 if (#notInCspMode) { | |
| 374 processedClasses.combinedConstructorFunction += | |
| 375 "return [\\n" + processedClasses.constructorsList.join(",\\n ") + | |
| 376 "\\n]"; | |
| 377 var constructors = | |
| 378 new Function("\$collectedClasses", | |
| 379 processedClasses.combinedConstructorFunction) | |
| 380 (processedClasses.collected); | |
| 381 processedClasses.combinedConstructorFunction = null; | |
| 382 } | |
| 383 | |
| 384 for (var i = 0; i < constructors.length; i++) { | |
| 385 var constructor = constructors[i]; | |
| 386 var cls = constructor.name; | |
| 387 var desc = processedClasses.collected[cls]; | |
| 388 var globalObject = \$; | |
| 389 if (desc instanceof Array) { | |
| 390 globalObject = desc[0] || \$; | |
| 391 desc = desc[1]; | |
| 392 } | |
| 393 if (#isTreeShakingDisabled) | |
| 394 constructor["${namer.metadataField}"] = desc; | |
| 395 allClasses[cls] = constructor; | |
| 396 globalObject[cls] = constructor; | |
| 397 } | |
| 398 constructors = null; | |
| 399 | |
| 400 #finishClassFunction; | |
| 401 | |
| 402 #trivialNsmHandlers; | |
| 403 | |
| 404 for (var cls in processedClasses.pending) finishClass(cls); | |
| 405 } | |
| 406 }''', {'allClasses': allClassesAccess, | |
| 407 'debugFastObjects': DEBUG_FAST_OBJECTS, | |
| 408 'isTreeShakingDisabled': backend.isTreeShakingDisabled, | |
| 409 'finishClassFunction': oldEmitter.buildFinishClass(), | |
| 410 'trivialNsmHandlers': oldEmitter.buildTrivialNsmHandlers(), | |
| 411 'inCspMode': compiler.useContentSecurityPolicy, | |
| 412 'notInCspMode': !compiler.useContentSecurityPolicy}); | |
| 413 | 279 |
| 414 List<jsAst.Statement> incrementalSupport = <jsAst.Statement>[]; | 280 List<jsAst.Statement> incrementalSupport = <jsAst.Statement>[]; |
| 415 if (compiler.hasIncrementalSupport) { | 281 if (compiler.hasIncrementalSupport) { |
| 416 incrementalSupport.add( | 282 incrementalSupport.add( |
| 417 js.statement( | 283 js.statement( |
| 418 r'self.$dart_unsafe_eval.addStubs = addStubs;')); | 284 r'self.$dart_unsafe_eval.addStubs = addStubs;')); |
| 419 } | 285 } |
| 420 | 286 |
| 421 return js(''' | 287 return js(''' |
| 422 (function (reflectionData) { | 288 (function (reflectionData) { |
| 423 "use strict"; | 289 "use strict"; |
| 424 #header; | 290 #header; |
| 425 if (#needsClassSupport) { | |
| 426 #defineClass; | |
| 427 #inheritFrom; | |
| 428 #finishClasses; | |
| 429 #processClassData; | |
| 430 } | |
| 431 #processStatics; | 291 #processStatics; |
| 432 #addStubs; | 292 #addStubs; |
| 433 #tearOffCode; | 293 #tearOffCode; |
| 434 #incrementalSupport; | 294 #incrementalSupport; |
| 435 #init; | 295 #init; |
| 436 })''', { | 296 })''', { |
| 437 'header': header, | 297 'header': header, |
| 438 'defineClass': oldEmitter.defineClassFunction, | |
| 439 'inheritFrom': oldEmitter.buildInheritFrom(), | |
| 440 'processClassData': processClassData, | |
| 441 'processStatics': processStatics, | 298 'processStatics': processStatics, |
| 442 'incrementalSupport': incrementalSupport, | 299 'incrementalSupport': incrementalSupport, |
| 443 'addStubs': addStubs, | 300 'addStubs': addStubs, |
| 444 'tearOffCode': tearOffCode, | 301 'tearOffCode': tearOffCode, |
| 445 'init': init, | 302 'init': init}); |
| 446 'finishClasses': finishClasses, | |
| 447 'needsClassSupport': oldEmitter.needsClassSupport}); | |
| 448 } | 303 } |
| 449 | 304 |
| 450 | 305 |
| 451 List<jsAst.Statement> buildTearOffCode(JavaScriptBackend backend) { | 306 List<jsAst.Statement> buildTearOffCode(JavaScriptBackend backend) { |
| 452 Namer namer = backend.namer; | 307 Namer namer = backend.namer; |
| 453 Compiler compiler = backend.compiler; | 308 Compiler compiler = backend.compiler; |
| 454 | 309 |
| 455 Element closureFromTearOff = backend.findHelper('closureFromTearOff'); | 310 Element closureFromTearOff = backend.findHelper('closureFromTearOff'); |
| 456 String tearOffAccessText; | 311 String tearOffAccessText; |
| 457 jsAst.Expression tearOffAccessExpression; | 312 jsAst.Expression tearOffAccessExpression; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 (function() { | 414 (function() { |
| 560 var result = $array[$index]; | 415 var result = $array[$index]; |
| 561 if ($check) { | 416 if ($check) { |
| 562 throw new Error( | 417 throw new Error( |
| 563 name + ": expected value of type \'$type\' at index " + ($index) + | 418 name + ": expected value of type \'$type\' at index " + ($index) + |
| 564 " but got " + (typeof result)); | 419 " but got " + (typeof result)); |
| 565 } | 420 } |
| 566 return result; | 421 return result; |
| 567 })()'''; | 422 })()'''; |
| 568 } | 423 } |
| OLD | NEW |