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