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; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 46 emitter.generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTED_NAMES); | 46 emitter.generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTED_NAMES); |
| 47 jsAst.Expression mangledGlobalNamesAccess = | 47 jsAst.Expression mangledGlobalNamesAccess = |
| 48 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); | 48 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); |
| 49 jsAst.Expression mangledNamesAccess = | 49 jsAst.Expression mangledNamesAccess = |
| 50 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES); | 50 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES); |
| 51 jsAst.Expression librariesAccess = | 51 jsAst.Expression librariesAccess = |
| 52 emitter.generateEmbeddedGlobalAccess(embeddedNames.LIBRARIES); | 52 emitter.generateEmbeddedGlobalAccess(embeddedNames.LIBRARIES); |
| 53 jsAst.Expression metadataAccess = | 53 jsAst.Expression metadataAccess = |
| 54 emitter.generateEmbeddedGlobalAccess(embeddedNames.METADATA); | 54 emitter.generateEmbeddedGlobalAccess(embeddedNames.METADATA); |
| 55 | 55 |
| 56 | |
| 56 jsAst.Statement processClassData = js.statement('''{ | 57 jsAst.Statement processClassData = js.statement('''{ |
| 58 function markerFun() {} | |
| 59 function finishAddStubsHelper(prototype) { | |
| 60 var prototype = prototype || this; | |
| 61 var object; | |
| 62 while (prototype.#deferredAction != markerFun) { | |
| 63 if (prototype.hasOwnProperty(#deferredActionString)) { | |
| 64 delete prototype.#deferredAction; // Intended to make it slow, too. | |
| 65 var properties = Object.keys(prototype); | |
| 66 for (var index = 0; index < properties.length; index++) { | |
| 67 var property = properties[index]; | |
| 68 var firstChar = property.charCodeAt(0); | |
| 69 var elem; | |
| 70 if (property !== "${namer.classDescriptorProperty}" && | |
| 71 property !== "$reflectableField" && | |
| 72 firstChar !== 43 && // 43 is aka "+". | |
|
floitsch
2015/03/06 14:54:09
Please add comment what this is for. The "+" and "
herhut
2015/03/09 14:28:35
Done.
| |
| 73 firstChar !== 42 && // 42 is aka "*" | |
| 74 (elem = prototype[property]) != null && | |
| 75 elem.constructor === Array && | |
| 76 property !== "<>") { | |
| 77 addStubs(prototype, elem, property, false, null); | |
| 78 } | |
| 79 } | |
| 80 convertToFastObject(prototype); | |
| 81 } | |
| 82 prototype = prototype.__proto__; | |
| 83 } | |
| 84 } | |
| 85 | |
| 57 function processClassData(cls, descriptor, processedClasses) { | 86 function processClassData(cls, descriptor, processedClasses) { |
| 58 descriptor = convertToSlowObject(descriptor); // Use a slow object. | 87 descriptor = convertToSlowObject(descriptor); // Use a slow object. |
| 59 var previousProperty; | 88 var previousProperty; |
| 60 var properties = Object.keys(descriptor); | 89 var properties = Object.keys(descriptor); |
| 90 var hasDeferredWork = false; | |
| 91 var deferWork = supportsDirectProtoAccess && cls != #objectClassName; | |
| 61 for (var i = 0; i < properties.length; i++) { | 92 for (var i = 0; i < properties.length; i++) { |
| 62 var property = properties[i]; | 93 var property = properties[i]; |
| 63 var firstChar = property.charCodeAt(0); | 94 var firstChar = property.charCodeAt(0); |
| 64 if (property === "static") { | 95 if (property === "static") { |
| 65 processStatics(#embeddedStatics[cls] = descriptor.static, | 96 processStatics(#embeddedStatics[cls] = descriptor.static, |
| 66 processedClasses); | 97 processedClasses); |
| 98 delete descriptor.static; | |
|
floitsch
2015/03/06 14:54:09
we don't need it for reflection?
herhut
2015/03/09 14:28:35
No, statics are collected separately in an array t
| |
| 67 } else if (firstChar === 43) { // 43 is aka "+". | 99 } else if (firstChar === 43) { // 43 is aka "+". |
| 68 mangledNames[previousProperty] = property.substring(1); | 100 mangledNames[previousProperty] = property.substring(1); |
| 69 var flag = descriptor[property]; | 101 var flag = descriptor[property]; |
| 70 if (flag > 0) | 102 if (flag > 0) |
| 71 descriptor[previousProperty].$reflectableField = flag; | 103 descriptor[previousProperty].$reflectableField = flag; |
| 72 } else if (firstChar === 42) { // 42 is aka "*" | 104 } else if (firstChar === 42) { // 42 is aka "*" |
| 73 descriptor[previousProperty].$defaultValuesField = descriptor[property]; | 105 descriptor[previousProperty].$defaultValuesField = descriptor[property]; |
| 74 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField; | 106 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField; |
| 75 if (!optionalMethods) { | 107 if (!optionalMethods) { |
| 76 descriptor.$methodsWithOptionalArgumentsField = optionalMethods={} | 108 descriptor.$methodsWithOptionalArgumentsField = optionalMethods={} |
| 77 } | 109 } |
| 78 optionalMethods[property] = previousProperty; | 110 optionalMethods[property] = previousProperty; |
| 79 } else { | 111 } else { |
| 80 var elem = descriptor[property]; | 112 var elem = descriptor[property]; |
| 81 if (property !== "${namer.classDescriptorProperty}" && | 113 if (property !== "${namer.classDescriptorProperty}" && |
| 82 elem != null && | 114 elem != null && |
| 83 elem.constructor === Array && | 115 elem.constructor === Array && |
| 84 property !== "<>") { | 116 property !== "<>") { |
| 85 addStubs(descriptor, elem, property, false, []); | 117 if (deferWork) { |
| 118 hasDeferredWork = true; | |
| 119 } else { | |
| 120 addStubs(descriptor, elem, property, false, null); | |
| 121 } | |
| 86 } else { | 122 } else { |
| 87 previousProperty = property; | 123 previousProperty = property; |
| 88 } | 124 } |
| 89 } | 125 } |
| 90 } | 126 } |
| 127 | |
| 128 if (hasDeferredWork) | |
| 129 descriptor.#deferredAction = finishAddStubsHelper; | |
| 91 | 130 |
| 92 /* The 'fields' are either a constructor function or a | 131 /* The 'fields' are either a constructor function or a |
| 93 * string encoding fields, constructor and superclass. Gets the | 132 * string encoding fields, constructor and superclass. Gets the |
| 94 * superclass and fields in the format | 133 * superclass and fields in the format |
| 95 * 'Super;field1,field2' | 134 * 'Super;field1,field2' |
| 96 * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor. | 135 * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor. |
| 97 */ | 136 */ |
| 98 var classData = descriptor["${namer.classDescriptorProperty}"], | 137 var classData = descriptor["${namer.classDescriptorProperty}"], |
| 99 split, supr, fields = classData; | 138 split, supr, fields = classData; |
| 100 | 139 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 121 } | 160 } |
| 122 | 161 |
| 123 if (supr) processedClasses.pending[cls] = supr; | 162 if (supr) processedClasses.pending[cls] = supr; |
| 124 if (#notInCspMode) { | 163 if (#notInCspMode) { |
| 125 processedClasses.combinedConstructorFunction += defineClass(cls, fields); | 164 processedClasses.combinedConstructorFunction += defineClass(cls, fields); |
| 126 processedClasses.constructorsList.push(cls); | 165 processedClasses.constructorsList.push(cls); |
| 127 } | 166 } |
| 128 processedClasses.collected[cls] = [globalObject, descriptor]; | 167 processedClasses.collected[cls] = [globalObject, descriptor]; |
| 129 classes.push(cls); | 168 classes.push(cls); |
| 130 } | 169 } |
| 131 }''', {'embeddedStatics': staticsAccess, | 170 }''', {'deferredAction': namer.deferredAction, |
| 171 'deferredActionString': js.string(namer.deferredAction), | |
| 172 'embeddedStatics': staticsAccess, | |
| 132 'hasRetainedMetadata': backend.hasRetainedMetadata, | 173 'hasRetainedMetadata': backend.hasRetainedMetadata, |
| 133 'metadata': metadataAccess, | 174 'metadata': metadataAccess, |
| 134 'notInCspMode': !compiler.useContentSecurityPolicy}); | 175 'notInCspMode': !compiler.useContentSecurityPolicy, |
| 176 'objectClassName': | |
| 177 js.string(namer.getNameOfClass(compiler.objectClass))}); | |
| 135 | 178 |
| 136 // TODO(zarah): Remove empty else branches in output when if(#hole) is false. | 179 // TODO(zarah): Remove empty else branches in output when if(#hole) is false. |
| 137 jsAst.Statement processStatics = js.statement(''' | 180 jsAst.Statement processStatics = js.statement(''' |
| 138 function processStatics(descriptor, processedClasses) { | 181 function processStatics(descriptor, processedClasses) { |
| 139 var properties = Object.keys(descriptor); | 182 var properties = Object.keys(descriptor); |
| 140 for (var i = 0; i < properties.length; i++) { | 183 for (var i = 0; i < properties.length; i++) { |
| 141 var property = properties[i]; | 184 var property = properties[i]; |
| 142 if (property === "${namer.classDescriptorProperty}") continue; | 185 if (property === "${namer.classDescriptorProperty}") continue; |
| 143 var element = descriptor[property]; | 186 var element = descriptor[property]; |
| 144 var firstChar = property.charCodeAt(0); | 187 var firstChar = property.charCodeAt(0); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 188 function addStubs(descriptor, array, name, isStatic, functions) { | 231 function addStubs(descriptor, array, name, isStatic, functions) { |
| 189 var index = $FUNCTION_INDEX, alias = array[index], f; | 232 var index = $FUNCTION_INDEX, alias = array[index], f; |
| 190 if (typeof alias == "string") { | 233 if (typeof alias == "string") { |
| 191 f = array[++index]; | 234 f = array[++index]; |
| 192 } else { | 235 } else { |
| 193 f = alias; | 236 f = alias; |
| 194 alias = name; | 237 alias = name; |
| 195 } | 238 } |
| 196 var funcs = [descriptor[name] = descriptor[alias] = f]; | 239 var funcs = [descriptor[name] = descriptor[alias] = f]; |
| 197 f.\$stubName = name; | 240 f.\$stubName = name; |
| 198 functions.push(name); | 241 if (isStatic) functions.push(name); |
| 199 for (; index < array.length; index += 2) { | 242 for (; index < array.length; index += 2) { |
| 200 f = array[index + 1]; | 243 f = array[index + 1]; |
| 201 if (typeof f != "function") break; | 244 if (typeof f != "function") break; |
| 202 f.\$stubName = ${readString("array", "index + 2")}; | 245 f.\$stubName = ${readString("array", "index + 2")}; |
| 203 funcs.push(f); | 246 funcs.push(f); |
| 204 if (f.\$stubName) { | 247 if (f.\$stubName) { |
| 205 descriptor[f.\$stubName] = f; | 248 descriptor[f.\$stubName] = f; |
| 206 functions.push(f.\$stubName); | 249 if (isStatic) functions.push(f.\$stubName); |
| 207 } | 250 } |
| 208 } | 251 } |
| 209 index++; | 252 index++; |
| 210 for (var i = 0; i < funcs.length; index++, i++) { | 253 for (var i = 0; i < funcs.length; index++, i++) { |
| 211 funcs[i].\$callName = ${readString("array", "index")}; | 254 funcs[i].\$callName = ${readString("array", "index")}; |
| 212 } | 255 } |
| 213 var getterStubName = ${readString("array", "index")}; | 256 var getterStubName = ${readString("array", "index")}; |
| 214 array = array.slice(++index); | 257 array = array.slice(++index); |
| 215 var requiredParameterInfo = ${readInt("array", "0")}; | 258 var requiredParameterInfo = ${readInt("array", "0")}; |
| 216 var requiredParameterCount = requiredParameterInfo >> 1; | 259 var requiredParameterCount = requiredParameterInfo >> 1; |
| 217 var isAccessor = (requiredParameterInfo & 1) === 1; | 260 var isAccessor = (requiredParameterInfo & 1) === 1; |
| 218 var isSetter = requiredParameterInfo === 3; | 261 var isSetter = requiredParameterInfo === 3; |
| 219 var isGetter = requiredParameterInfo === 1; | 262 var isGetter = requiredParameterInfo === 1; |
| 220 var optionalParameterInfo = ${readInt("array", "1")}; | 263 var optionalParameterInfo = ${readInt("array", "1")}; |
| 221 var optionalParameterCount = optionalParameterInfo >> 1; | 264 var optionalParameterCount = optionalParameterInfo >> 1; |
| 222 var optionalParametersAreNamed = (optionalParameterInfo & 1) === 1; | 265 var optionalParametersAreNamed = (optionalParameterInfo & 1) === 1; |
| 223 var isIntercepted = | 266 var isIntercepted = |
| 224 requiredParameterCount + optionalParameterCount != funcs[0].length; | 267 requiredParameterCount + optionalParameterCount != funcs[0].length; |
| 225 var functionTypeIndex = ${readFunctionType("array", "2")}; | 268 var functionTypeIndex = ${readFunctionType("array", "2")}; |
| 226 var unmangledNameIndex = $unmangledNameIndex; | 269 var unmangledNameIndex = $unmangledNameIndex; |
| 227 | 270 |
| 228 if (getterStubName) { | 271 if (getterStubName) { |
| 229 f = tearOff(funcs, array, isStatic, name, isIntercepted); | 272 f = tearOff(funcs, array, isStatic, name, isIntercepted); |
| 230 descriptor[name].\$getter = f; | 273 descriptor[name].\$getter = f; |
| 231 f.\$getterStub = true; | 274 f.\$getterStub = true; |
| 232 // Used to create an isolate using spawnFunction. | 275 // Used to create an isolate using spawnFunction. |
| 233 if (isStatic) #globalFunctions[name] = f; | 276 if (isStatic) { |
| 277 #globalFunctions[name] = f; | |
| 278 functions.push(getterStubName); | |
| 279 } | |
| 234 descriptor[getterStubName] = f; | 280 descriptor[getterStubName] = f; |
| 235 funcs.push(f); | 281 funcs.push(f); |
| 236 if (getterStubName) functions.push(getterStubName); | |
| 237 f.\$stubName = getterStubName; | 282 f.\$stubName = getterStubName; |
| 238 f.\$callName = null; | 283 f.\$callName = null; |
| 239 // Update the interceptedNames map (which only exists if `invokeOn` was | 284 // Update the interceptedNames map (which only exists if `invokeOn` was |
| 240 // enabled). | 285 // enabled). |
| 241 if (#enabledInvokeOn) | 286 if (#enabledInvokeOn) |
| 242 if (isIntercepted) #interceptedNames[getterStubName] = 1; | 287 if (isIntercepted) #interceptedNames[getterStubName] = 1; |
| 243 } | 288 } |
| 244 | 289 |
| 245 if (#usesMangledNames) { | 290 if (#usesMangledNames) { |
| 246 var isReflectable = array.length > unmangledNameIndex; | 291 var isReflectable = array.length > unmangledNameIndex; |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 482 (function() { | 527 (function() { |
| 483 var result = $array[$index]; | 528 var result = $array[$index]; |
| 484 if ($check) { | 529 if ($check) { |
| 485 throw new Error( | 530 throw new Error( |
| 486 name + ": expected value of type \'$type\' at index " + ($index) + | 531 name + ": expected value of type \'$type\' at index " + ($index) + |
| 487 " but got " + (typeof result)); | 532 " but got " + (typeof result)); |
| 488 } | 533 } |
| 489 return result; | 534 return result; |
| 490 })()'''; | 535 })()'''; |
| 491 } | 536 } |
| OLD | NEW |