| 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 // TODO(ahe): This code should be integrated in CodeEmitterTask.finishClasses. | 17 jsAst.Expression getReflectionDataParser(OldEmitter oldEmitter, |
| 18 jsAst.Expression getReflectionDataParser(String classesCollector, | 18 JavaScriptBackend backend) { |
| 19 JavaScriptBackend backend) { | |
| 20 Namer namer = backend.namer; | 19 Namer namer = backend.namer; |
| 21 Compiler compiler = backend.compiler; | 20 Compiler compiler = backend.compiler; |
| 22 CodeEmitterTask emitter = backend.emitter; | 21 CodeEmitterTask emitter = backend.emitter; |
| 23 | 22 |
| 24 String metadataField = '"${namer.metadataField}"'; | 23 String metadataField = '"${namer.metadataField}"'; |
| 25 String reflectableField = namer.reflectableField; | 24 String reflectableField = namer.reflectableField; |
| 26 String reflectionInfoField = namer.reflectionInfoField; | 25 String reflectionInfoField = namer.reflectionInfoField; |
| 27 String reflectionNameField = namer.reflectionNameField; | 26 String reflectionNameField = namer.reflectionNameField; |
| 28 String metadataIndexField = namer.metadataIndexField; | 27 String metadataIndexField = namer.metadataIndexField; |
| 29 String defaultValuesField = namer.defaultValuesField; | 28 String defaultValuesField = namer.defaultValuesField; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 41 jsAst.Expression staticsAccess = | 40 jsAst.Expression staticsAccess = |
| 42 emitter.generateEmbeddedGlobalAccess(embeddedNames.STATICS); | 41 emitter.generateEmbeddedGlobalAccess(embeddedNames.STATICS); |
| 43 jsAst.Expression interceptedNamesAccess = | 42 jsAst.Expression interceptedNamesAccess = |
| 44 emitter.generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTED_NAMES); | 43 emitter.generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTED_NAMES); |
| 45 jsAst.Expression mangledGlobalNamesAccess = | 44 jsAst.Expression mangledGlobalNamesAccess = |
| 46 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); | 45 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); |
| 47 jsAst.Expression mangledNamesAccess = | 46 jsAst.Expression mangledNamesAccess = |
| 48 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES); | 47 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES); |
| 49 jsAst.Expression librariesAccess = | 48 jsAst.Expression librariesAccess = |
| 50 emitter.generateEmbeddedGlobalAccess(embeddedNames.LIBRARIES); | 49 emitter.generateEmbeddedGlobalAccess(embeddedNames.LIBRARIES); |
| 50 jsAst.Expression metadataAccess = |
| 51 emitter.generateEmbeddedGlobalAccess(embeddedNames.METADATA); |
| 51 | 52 |
| 52 jsAst.Statement header = js.statement(''' | 53 jsAst.Statement header = js.statement(''' |
| 53 // [map] returns an object literal that V8 shouldn not try to optimize with a | 54 // [map] returns an object literal that V8 shouldn not try to optimize with a |
| 54 // hidden class. This prevents a potential performance problem where V8 tries | 55 // hidden class. This prevents a potential performance problem where V8 tries |
| 55 // to build a hidden class for an object used as a hashMap. | 56 // to build a hidden class for an object used as a hashMap. |
| 56 // It requires fewer characters to declare a variable as a parameter than | 57 // It requires fewer characters to declare a variable as a parameter than |
| 57 // with `var`. | 58 // with `var`. |
| 58 function map(x){x=Object.create(null);x.x=0;delete x.x;return x} | 59 function map(x){x=Object.create(null);x.x=0;delete x.x;return x} |
| 59 '''); | 60 '''); |
| 60 | 61 |
| 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 |
| 61 jsAst.Statement processStatics = js.statement(''' | 143 jsAst.Statement processStatics = js.statement(''' |
| 62 function processStatics(descriptor) { | 144 function processStatics(descriptor, processedClasses) { |
| 63 for (var property in descriptor) { | 145 for (var property in descriptor) { |
| 64 if (!hasOwnProperty.call(descriptor, property)) continue; | 146 if (!hasOwnProperty.call(descriptor, property)) continue; |
| 65 if (property === "${namer.classDescriptorProperty}") continue; | 147 if (property === "${namer.classDescriptorProperty}") continue; |
| 66 var element = descriptor[property]; | 148 var element = descriptor[property]; |
| 67 var firstChar = property.substring(0, 1); | 149 var firstChar = property.substring(0, 1); |
| 68 var previousProperty; | 150 var previousProperty; |
| 69 if (firstChar === "+") { | 151 if (firstChar === "+") { |
| 70 mangledGlobalNames[previousProperty] = property.substring(1); | 152 mangledGlobalNames[previousProperty] = property.substring(1); |
| 71 var flag = descriptor[property]; | 153 var flag = descriptor[property]; |
| 72 if (flag > 0) | 154 if (flag > 0) |
| 73 descriptor[previousProperty].$reflectableField = flag; | 155 descriptor[previousProperty].$reflectableField = flag; |
| 74 if (element && element.length) | 156 if (element && element.length) |
| 75 #[previousProperty] = element; // embedded typeInformation. | 157 #typeInformation[previousProperty] = element; |
| 76 } else if (firstChar === "@") { | 158 } else if (firstChar === "@") { |
| 77 property = property.substring(1); | 159 property = property.substring(1); |
| 78 ${namer.currentIsolate}[property][$metadataField] = element; | 160 ${namer.currentIsolate}[property][$metadataField] = element; |
| 79 } else if (firstChar === "*") { | 161 } else if (firstChar === "*") { |
| 80 globalObject[previousProperty].$defaultValuesField = element; | 162 globalObject[previousProperty].$defaultValuesField = element; |
| 81 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField; | 163 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField; |
| 82 if (!optionalMethods) { | 164 if (!optionalMethods) { |
| 83 descriptor.$methodsWithOptionalArgumentsField = optionalMethods = {} | 165 descriptor.$methodsWithOptionalArgumentsField = optionalMethods = {} |
| 84 } | 166 } |
| 85 optionalMethods[property] = previousProperty; | 167 optionalMethods[property] = previousProperty; |
| 86 } else if (typeof element === "function") { | 168 } else if (typeof element === "function") { |
| 87 globalObject[previousProperty = property] = element; | 169 globalObject[previousProperty = property] = element; |
| 88 functions.push(property); | 170 functions.push(property); |
| 89 #[property] = element; // embedded globalFunctions. | 171 #globalFunctions[property] = element; |
| 90 } else if (element.constructor === Array) { | 172 } else if (element.constructor === Array) { |
| 91 addStubs(globalObject, element, property, | 173 addStubs(globalObject, element, property, |
| 92 true, descriptor, functions); | 174 true, descriptor, functions); |
| 93 } else { | 175 } else { |
| 94 previousProperty = property; | 176 // We will not enter this case if no classes are defined. |
| 95 var newDesc = {}; | 177 if (#hasClasses) { |
| 96 var previousProp; | 178 previousProperty = property; |
| 97 for (var prop in element) { | 179 processClassData(property, element, processedClasses); |
| 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 } | |
| 127 } | 180 } |
| 128 $classesCollector[property] = [globalObject, newDesc]; | |
| 129 classes.push(property); | |
| 130 } | 181 } |
| 131 } | 182 } |
| 132 } | 183 } |
| 133 ''', [typeInformationAccess, globalFunctionsAccess, staticsAccess]); | 184 ''', {'typeInformation': typeInformationAccess, |
| 185 'globalFunctions': globalFunctionsAccess, |
| 186 'hasClasses': oldEmitter.needsClassSupport}); |
| 134 | 187 |
| 135 | 188 |
| 136 /** | 189 /** |
| 137 * See [dart2js.js_emitter.ContainerBuilder.addMemberMethod] for format of | 190 * See [dart2js.js_emitter.ContainerBuilder.addMemberMethod] for format of |
| 138 * [array]. | 191 * [array]. |
| 139 */ | 192 */ |
| 140 jsAst.Statement addStubs = js.statement(''' | 193 jsAst.Statement addStubs = js.statement(''' |
| 141 function addStubs(descriptor, array, name, isStatic, | 194 function addStubs(descriptor, array, name, isStatic, |
| 142 originalDescriptor, functions) { | 195 originalDescriptor, functions) { |
| 143 var index = $FUNCTION_INDEX, alias = array[index], f; | 196 var index = $FUNCTION_INDEX, alias = array[index], f; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 } | 272 } |
| 220 ''', {'globalFunctions' : globalFunctionsAccess, | 273 ''', {'globalFunctions' : globalFunctionsAccess, |
| 221 'interceptedNames': interceptedNamesAccess, | 274 'interceptedNames': interceptedNamesAccess, |
| 222 'mangledGlobalNames': mangledGlobalNamesAccess, | 275 'mangledGlobalNames': mangledGlobalNamesAccess, |
| 223 'mangledNames': mangledNamesAccess}); | 276 'mangledNames': mangledNamesAccess}); |
| 224 | 277 |
| 225 List<jsAst.Statement> tearOffCode = buildTearOffCode(backend); | 278 List<jsAst.Statement> tearOffCode = buildTearOffCode(backend); |
| 226 | 279 |
| 227 jsAst.Statement init = js.statement('''{ | 280 jsAst.Statement init = js.statement('''{ |
| 228 var functionCounter = 0; | 281 var functionCounter = 0; |
| 229 if (!#) # = []; // embedded libraries. | 282 if (!#libraries) #libraries = []; |
| 230 if (!#) # = map(); // embedded mangledNames. | 283 if (!#mangledNames) #mangledNames = map(); |
| 231 if (!#) # = map(); // embedded mangledGlobalNames. | 284 if (!#mangledGlobalNames) #mangledGlobalNames = map(); |
| 232 if (!#) # = map(); // embedded statics. | 285 if (!#statics) #statics = map(); |
| 233 if (!#) # = map(); // embedded typeInformation. | 286 if (!#typeInformation) #typeInformation = map(); |
| 234 if (!#) # = map(); // embedded globalFunctions. | 287 if (!#globalFunctions) #globalFunctions = map(); |
| 235 if (!#) # = map(); // embedded interceptedNames. | 288 if (!#interceptedNames) #interceptedNames = map(); |
| 236 var libraries = #; // embeded libraries. | 289 var libraries = #libraries; |
| 237 var mangledNames = #; // embedded mangledNames. | 290 var mangledNames = #mangledNames; |
| 238 var mangledGlobalNames = #; // embedded mangledGlobalNames. | 291 var mangledGlobalNames = #mangledGlobalNames; |
| 239 var hasOwnProperty = Object.prototype.hasOwnProperty; | 292 var hasOwnProperty = Object.prototype.hasOwnProperty; |
| 240 var length = reflectionData.length; | 293 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 } |
| 241 for (var i = 0; i < length; i++) { | 305 for (var i = 0; i < length; i++) { |
| 242 var data = reflectionData[i]; | 306 var data = reflectionData[i]; |
| 243 | 307 |
| 244 // [data] contains these elements: | 308 // [data] contains these elements: |
| 245 // 0. The library name (not unique). | 309 // 0. The library name (not unique). |
| 246 // 1. The library URI (unique). | 310 // 1. The library URI (unique). |
| 247 // 2. A function returning the metadata associated with this library. | 311 // 2. A function returning the metadata associated with this library. |
| 248 // 3. The global object to use for this library. | 312 // 3. The global object to use for this library. |
| 249 // 4. An object literal listing the members of the library. | 313 // 4. An object literal listing the members of the library. |
| 250 // 5. This element is optional and if present it is true and signals that this | 314 // 5. This element is optional and if present it is true and signals that this |
| 251 // library is the root library (see dart:mirrors IsolateMirror.rootLibrary). | 315 // library is the root library (see dart:mirrors IsolateMirror.rootLibrary). |
| 252 // | 316 // |
| 253 // The entries of [data] are built in [assembleProgram] above. | 317 // The entries of [data] are built in [assembleProgram] above. |
| 254 | 318 |
| 255 var name = data[0]; | 319 var name = data[0]; |
| 256 var uri = data[1]; | 320 var uri = data[1]; |
| 257 var metadata = data[2]; | 321 var metadata = data[2]; |
| 258 var globalObject = data[3]; | 322 var globalObject = data[3]; |
| 259 var descriptor = data[4]; | 323 var descriptor = data[4]; |
| 260 var isRoot = !!data[5]; | 324 var isRoot = !!data[5]; |
| 261 var fields = descriptor && descriptor["${namer.classDescriptorProperty}"]; | 325 var fields = descriptor && descriptor["${namer.classDescriptorProperty}"]; |
| 262 if (fields instanceof Array) fields = fields[0]; | 326 if (fields instanceof Array) fields = fields[0]; |
| 263 var classes = []; | 327 var classes = []; |
| 264 var functions = []; | 328 var functions = []; |
| 265 processStatics(descriptor); | 329 processStatics(descriptor, processedClasses); |
| 266 libraries.push([name, uri, classes, functions, metadata, fields, isRoot, | 330 libraries.push([name, uri, classes, functions, metadata, fields, isRoot, |
| 267 globalObject]); | 331 globalObject]); |
| 268 } | 332 } |
| 269 }''', [librariesAccess, librariesAccess, | 333 if (#needsClassSupport) finishClasses(processedClasses); |
| 270 mangledNamesAccess, mangledNamesAccess, | 334 }''', {'libraries': librariesAccess, |
| 271 mangledGlobalNamesAccess, mangledGlobalNamesAccess, | 335 'mangledNames': mangledNamesAccess, |
| 272 staticsAccess, staticsAccess, | 336 'mangledGlobalNames': mangledGlobalNamesAccess, |
| 273 typeInformationAccess, typeInformationAccess, | 337 'statics': staticsAccess, |
| 274 globalFunctionsAccess, globalFunctionsAccess, | 338 'typeInformation': typeInformationAccess, |
| 275 interceptedNamesAccess, interceptedNamesAccess, | 339 'globalFunctions': globalFunctionsAccess, |
| 276 librariesAccess, | 340 'interceptedNames': interceptedNamesAccess, |
| 277 mangledNamesAccess, | 341 'notInCspMode': !compiler.useContentSecurityPolicy, |
| 278 mangledGlobalNamesAccess]); | 342 'needsClassSupport': oldEmitter.needsClassSupport}); |
| 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}); |
| 279 | 413 |
| 280 List<jsAst.Statement> incrementalSupport = <jsAst.Statement>[]; | 414 List<jsAst.Statement> incrementalSupport = <jsAst.Statement>[]; |
| 281 if (compiler.hasIncrementalSupport) { | 415 if (compiler.hasIncrementalSupport) { |
| 282 incrementalSupport.add( | 416 incrementalSupport.add( |
| 283 js.statement( | 417 js.statement( |
| 284 r'self.$dart_unsafe_eval.addStubs = addStubs;')); | 418 r'self.$dart_unsafe_eval.addStubs = addStubs;')); |
| 285 } | 419 } |
| 286 | 420 |
| 287 return js(''' | 421 return js(''' |
| 288 (function (reflectionData) { | 422 (function (reflectionData) { |
| 289 "use strict"; | 423 "use strict"; |
| 290 #header; | 424 #header; |
| 425 if (#needsClassSupport) { |
| 426 #defineClass; |
| 427 #inheritFrom; |
| 428 #finishClasses; |
| 429 #processClassData; |
| 430 } |
| 291 #processStatics; | 431 #processStatics; |
| 292 #addStubs; | 432 #addStubs; |
| 293 #tearOffCode; | 433 #tearOffCode; |
| 294 #incrementalSupport; | 434 #incrementalSupport; |
| 295 #init; | 435 #init; |
| 296 })''', { | 436 })''', { |
| 297 'header': header, | 437 'header': header, |
| 438 'defineClass': oldEmitter.defineClassFunction, |
| 439 'inheritFrom': oldEmitter.buildInheritFrom(), |
| 440 'processClassData': processClassData, |
| 298 'processStatics': processStatics, | 441 'processStatics': processStatics, |
| 299 'incrementalSupport': incrementalSupport, | 442 'incrementalSupport': incrementalSupport, |
| 300 'addStubs': addStubs, | 443 'addStubs': addStubs, |
| 301 'tearOffCode': tearOffCode, | 444 'tearOffCode': tearOffCode, |
| 302 'init': init}); | 445 'init': init, |
| 446 'finishClasses': finishClasses, |
| 447 'needsClassSupport': oldEmitter.needsClassSupport}); |
| 303 } | 448 } |
| 304 | 449 |
| 305 | 450 |
| 306 List<jsAst.Statement> buildTearOffCode(JavaScriptBackend backend) { | 451 List<jsAst.Statement> buildTearOffCode(JavaScriptBackend backend) { |
| 307 Namer namer = backend.namer; | 452 Namer namer = backend.namer; |
| 308 Compiler compiler = backend.compiler; | 453 Compiler compiler = backend.compiler; |
| 309 | 454 |
| 310 Element closureFromTearOff = backend.findHelper('closureFromTearOff'); | 455 Element closureFromTearOff = backend.findHelper('closureFromTearOff'); |
| 311 String tearOffAccessText; | 456 String tearOffAccessText; |
| 312 jsAst.Expression tearOffAccessExpression; | 457 jsAst.Expression tearOffAccessExpression; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 (function() { | 559 (function() { |
| 415 var result = $array[$index]; | 560 var result = $array[$index]; |
| 416 if ($check) { | 561 if ($check) { |
| 417 throw new Error( | 562 throw new Error( |
| 418 name + ": expected value of type \'$type\' at index " + ($index) + | 563 name + ": expected value of type \'$type\' at index " + ($index) + |
| 419 " but got " + (typeof result)); | 564 " but got " + (typeof result)); |
| 420 } | 565 } |
| 421 return result; | 566 return result; |
| 422 })()'''; | 567 })()'''; |
| 423 } | 568 } |
| OLD | NEW |