| 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 // TODO(ahe): This code should be integrated in CodeEmitterTask.finishClasses. |
| 18 String getReflectionDataParser(String classesCollector, | 18 jsAst.Expression getReflectionDataParser(String classesCollector, |
| 19 JavaScriptBackend backend) { | 19 JavaScriptBackend backend) { |
| 20 var text = getReflectionDataParserAsString(classesCollector, backend); |
| 21 return js(text); |
| 22 } |
| 23 |
| 24 |
| 25 String getReflectionDataParserAsString(String classesCollector, |
| 26 JavaScriptBackend backend) { |
| 20 Namer namer = backend.namer; | 27 Namer namer = backend.namer; |
| 21 Compiler compiler = backend.compiler; | 28 Compiler compiler = backend.compiler; |
| 22 Element closureFromTearOff = compiler.findHelper('closureFromTearOff'); | 29 Element closureFromTearOff = compiler.findHelper('closureFromTearOff'); |
| 23 String tearOffAccess; | 30 String tearOffAccess; |
| 24 String tearOffGlobalObjectName; | 31 String tearOffGlobalObjectName; |
| 25 String tearOffGlobalObject; | 32 String tearOffGlobalObject; |
| 26 if (closureFromTearOff != null) { | 33 if (closureFromTearOff != null) { |
| 27 tearOffAccess = namer.isolateAccess(closureFromTearOff); | 34 tearOffAccess = namer.isolateAccess(closureFromTearOff); |
| 28 tearOffGlobalObjectName = tearOffGlobalObject = | 35 tearOffGlobalObjectName = tearOffGlobalObject = |
| 29 namer.globalObjectFor(closureFromTearOff); | 36 namer.globalObjectFor(closureFromTearOff); |
| 30 } else { | 37 } else { |
| 31 // Default values for mocked-up test libraries. | 38 // Default values for mocked-up test libraries. |
| 32 tearOffAccess = | 39 tearOffAccess = |
| 33 'function() { throw "Helper \'closureFromTearOff\' missing." }'; | 40 r'''function() { throw 'Helper \'closureFromTearOff\' missing.' }'''; |
| 34 tearOffGlobalObjectName = 'MissingHelperFunction'; | 41 tearOffGlobalObjectName = 'MissingHelperFunction'; |
| 35 tearOffGlobalObject = '($tearOffAccess())'; | 42 tearOffGlobalObject = '($tearOffAccess())'; |
| 36 } | 43 } |
| 37 | 44 |
| 38 String metadataField = '"${namer.metadataField}"'; | 45 String metadataField = '"${namer.metadataField}"'; |
| 39 String reflectableField = namer.reflectableField; | 46 String reflectableField = namer.reflectableField; |
| 40 | 47 |
| 41 // TODO(ahe): Move this string constants to namer. | 48 // TODO(ahe): Move this string constants to namer. |
| 42 String reflectionInfoField = r'$reflectionInfo'; | 49 String reflectionInfoField = r'$reflectionInfo'; |
| 43 String reflectionNameField = r'$reflectionName'; | 50 String reflectionNameField = r'$reflectionName'; |
| 44 String metadataIndexField = r'$metadataIndex'; | 51 String metadataIndexField = r'$metadataIndex'; |
| 45 | 52 |
| 46 String defaultValuesField = namer.defaultValuesField; | 53 String defaultValuesField = namer.defaultValuesField; |
| 47 String methodsWithOptionalArgumentsField = | 54 String methodsWithOptionalArgumentsField = |
| 48 namer.methodsWithOptionalArgumentsField; | 55 namer.methodsWithOptionalArgumentsField; |
| 49 | 56 |
| 57 String unmangledNameIndex = backend.mustRetainMetadata |
| 58 ? ' 3 * optionalParameterCount + 2 * requiredParameterCount + 3' |
| 59 : ' 2 * optionalParameterCount + requiredParameterCount + 3'; |
| 60 |
| 61 |
| 50 String header = ''' | 62 String header = ''' |
| 51 (function (reflectionData) { | 63 (function (reflectionData) { |
| 52 "use strict"; | 64 "use strict"; |
| 53 ''' | 65 |
| 54 // [map] returns an object literal that V8 shouldn't try to optimize with a | 66 // [map] returns an object literal that V8 shouldn't try to optimize with a |
| 55 // hidden class. This prevents a potential performance problem where V8 tries | 67 // hidden class. This prevents a potential performance problem where V8 tries |
| 56 // to build a hidden class for an object used as a hashMap. | 68 // to build a hidden class for an object used as a hashMap. |
| 57 ''' | 69 |
| 58 function map(x){x={x:x};delete x.x;return x} | 70 function map(x){x={x:x};delete x.x;return x} |
| 59 '''; | 71 '''; |
| 60 | 72 |
| 61 String unmangledNameIndex = backend.mustRetainMetadata | 73 String processStatics = ''' |
| 62 ? ' 3 * optionalParameterCount + 2 * requiredParameterCount + 3' | 74 function processStatics(descriptor) { |
| 63 : ' 2 * optionalParameterCount + requiredParameterCount + 3'; | 75 for (var property in descriptor) { |
| 76 if (!hasOwnProperty.call(descriptor, property)) continue; |
| 77 if (property === "${namer.classDescriptorProperty}") continue; |
| 78 var element = descriptor[property]; |
| 79 var firstChar = property.substring(0, 1); |
| 80 var previousProperty; |
| 81 if (firstChar === "+") { |
| 82 mangledGlobalNames[previousProperty] = property.substring(1); |
| 83 var flag = descriptor[property]; |
| 84 if (flag > 0) |
| 85 descriptor[previousProperty].$reflectableField = flag; |
| 86 if (element && element.length) |
| 87 init.typeInformation[previousProperty] = element; |
| 88 } else if (firstChar === "@") { |
| 89 property = property.substring(1); |
| 90 ${namer.currentIsolate}[property][$metadataField] = element; |
| 91 } else if (firstChar === "*") { |
| 92 globalObject[previousProperty].$defaultValuesField = element; |
| 93 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField; |
| 94 if (!optionalMethods) { |
| 95 descriptor.$methodsWithOptionalArgumentsField = optionalMethods = {} |
| 96 } |
| 97 optionalMethods[property] = previousProperty; |
| 98 } else if (typeof element === "function") { |
| 99 globalObject[previousProperty = property] = element; |
| 100 functions.push(property); |
| 101 init.globalFunctions[property] = element; |
| 102 } else if (element.constructor === Array) { |
| 103 addStubs(globalObject, element, property, |
| 104 true, descriptor, functions); |
| 105 } else { |
| 106 previousProperty = property; |
| 107 var newDesc = {}; |
| 108 var previousProp; |
| 109 for (var prop in element) { |
| 110 if (!hasOwnProperty.call(element, prop)) continue; |
| 111 firstChar = prop.substring(0, 1); |
| 112 if (prop === "static") { |
| 113 processStatics(init.statics[property] = element[prop]); |
| 114 } else if (firstChar === "+") { |
| 115 mangledNames[previousProp] = prop.substring(1); |
| 116 var flag = element[prop]; |
| 117 if (flag > 0) |
| 118 element[previousProp].$reflectableField = flag; |
| 119 } else if (firstChar === "@" && prop !== "@") { |
| 120 newDesc[prop.substring(1)][$metadataField] = element[prop]; |
| 121 } else if (firstChar === "*") { |
| 122 newDesc[previousProp].$defaultValuesField = element[prop]; |
| 123 var optionalMethods = newDesc.$methodsWithOptionalArgumentsField; |
| 124 if (!optionalMethods) { |
| 125 newDesc.$methodsWithOptionalArgumentsField = optionalMethods={} |
| 126 } |
| 127 optionalMethods[prop] = previousProp; |
| 128 } else { |
| 129 var elem = element[prop]; |
| 130 if (prop !== "${namer.classDescriptorProperty}" && |
| 131 elem != null && |
| 132 elem.constructor === Array && |
| 133 prop !== "<>") { |
| 134 addStubs(newDesc, elem, prop, false, element, []); |
| 135 } else { |
| 136 newDesc[previousProp = prop] = elem; |
| 137 } |
| 138 } |
| 139 } |
| 140 $classesCollector[property] = [globalObject, newDesc]; |
| 141 classes.push(property); |
| 142 } |
| 143 } |
| 144 } |
| 145 '''; |
| 146 |
| 64 | 147 |
| 65 /** | 148 /** |
| 66 * See [dart2js.js_emitter.ContainerBuilder.addMemberMethod] for format of | 149 * See [dart2js.js_emitter.ContainerBuilder.addMemberMethod] for format of |
| 67 * [array]. | 150 * [array]. |
| 68 */ | 151 */ |
| 69 String addStubs = ''' | 152 String addStubs = ''' |
| 70 function addStubs(descriptor, array, name, isStatic,''' // Break long line. | 153 function addStubs(descriptor, array, name, isStatic, |
| 71 ''' originalDescriptor, functions) { | 154 originalDescriptor, functions) { |
| 72 var f, funcs =''' // Break long line. | 155 var f, funcs = |
| 73 ''' [originalDescriptor[name] =''' // Break long line. | 156 [originalDescriptor[name] = |
| 74 ''' descriptor[name] = f = ${readFunction("array", "$FUNCTION_INDEX")}]; | 157 descriptor[name] = f = ${readFunction("array", "$FUNCTION_INDEX")}]; |
| 75 f.\$stubName = name; | 158 f.\$stubName = name; |
| 76 functions.push(name); | 159 functions.push(name); |
| 77 for (var index = $FUNCTION_INDEX; index < array.length; index += 2) { | 160 for (var index = $FUNCTION_INDEX; index < array.length; index += 2) { |
| 78 f = array[index + 1]; | 161 f = array[index + 1]; |
| 79 if (typeof f != "function") break; | 162 if (typeof f != "function") break; |
| 80 f.\$stubName = ${readString("array", "index + 2")}; | 163 f.\$stubName = ${readString("array", "index + 2")}; |
| 81 funcs.push(f); | 164 funcs.push(f); |
| 82 if (f.\$stubName) { | 165 if (f.\$stubName) { |
| 83 originalDescriptor[f.\$stubName] = descriptor[f.\$stubName] = f; | 166 originalDescriptor[f.\$stubName] = descriptor[f.\$stubName] = f; |
| 84 functions.push(f.\$stubName); | 167 functions.push(f.\$stubName); |
| 85 } | 168 } |
| 86 } | 169 } |
| 87 for (var i = 0; i < funcs.length; index++, i++) { | 170 for (var i = 0; i < funcs.length; index++, i++) { |
| 88 funcs[i].\$callName = ${readString("array", "index + 1")}; | 171 funcs[i].\$callName = ${readString("array", "index + 1")}; |
| 89 } | 172 } |
| 90 var getterStubName = ${readString("array", "++index")}; | 173 var getterStubName = ${readString("array", "++index")}; |
| 91 array = array.slice(++index); | 174 array = array.slice(++index); |
| 92 var requiredParameterInfo = ${readInt("array", "0")}; | 175 var requiredParameterInfo = ${readInt("array", "0")}; |
| 93 var requiredParameterCount = requiredParameterInfo >> 1; | 176 var requiredParameterCount = requiredParameterInfo >> 1; |
| 94 var isAccessor = (requiredParameterInfo & 1) === 1; | 177 var isAccessor = (requiredParameterInfo & 1) === 1; |
| 95 var isSetter = requiredParameterInfo === 3; | 178 var isSetter = requiredParameterInfo === 3; |
| 96 var isGetter = requiredParameterInfo === 1; | 179 var isGetter = requiredParameterInfo === 1; |
| 97 var optionalParameterInfo = ${readInt("array", "1")}; | 180 var optionalParameterInfo = ${readInt("array", "1")}; |
| 98 var optionalParameterCount = optionalParameterInfo >> 1; | 181 var optionalParameterCount = optionalParameterInfo >> 1; |
| 99 var optionalParametersAreNamed = (optionalParameterInfo & 1) === 1; | 182 var optionalParametersAreNamed = (optionalParameterInfo & 1) === 1; |
| 100 var isIntercepted =''' // Break long line. | 183 var isIntercepted = |
| 101 ''' requiredParameterCount + optionalParameterCount != funcs[0].length; | 184 requiredParameterCount + optionalParameterCount != funcs[0].length; |
| 102 var functionTypeIndex = ${readFunctionType("array", "2")}; | 185 var functionTypeIndex = ${readFunctionType("array", "2")}; |
| 103 var unmangledNameIndex = $unmangledNameIndex; | 186 var unmangledNameIndex = $unmangledNameIndex; |
| 104 var isReflectable = array.length > unmangledNameIndex; | 187 var isReflectable = array.length > unmangledNameIndex; |
| 105 | 188 |
| 106 if (getterStubName) { | 189 if (getterStubName) { |
| 107 f = tearOff(funcs, array, isStatic, name, isIntercepted); | 190 f = tearOff(funcs, array, isStatic, name, isIntercepted); |
| 108 descriptor[name].\$getter = f; | 191 descriptor[name].\$getter = f; |
| 109 f.\$getterStub = true; | 192 f.\$getterStub = true; |
| 110 ''' | 193 // Used to create an isolate using spawnFunction. |
| 111 /* Used to create an isolate using spawnFunction.*/ | |
| 112 ''' | |
| 113 if (isStatic) init.globalFunctions[name] = f; | 194 if (isStatic) init.globalFunctions[name] = f; |
| 114 originalDescriptor[getterStubName] = descriptor[getterStubName] = f; | 195 originalDescriptor[getterStubName] = descriptor[getterStubName] = f; |
| 115 funcs.push(f); | 196 funcs.push(f); |
| 116 if (getterStubName) functions.push(getterStubName); | 197 if (getterStubName) functions.push(getterStubName); |
| 117 f.\$stubName = getterStubName; | 198 f.\$stubName = getterStubName; |
| 118 f.\$callName = null; | 199 f.\$callName = null; |
| 119 if (isIntercepted) init.interceptedNames[getterStubName] = true; | 200 if (isIntercepted) init.interceptedNames[getterStubName] = true; |
| 120 } | 201 } |
| 121 if (isReflectable) { | 202 if (isReflectable) { |
| 122 for (var i = 0; i < funcs.length; i++) { | 203 for (var i = 0; i < funcs.length; i++) { |
| 123 funcs[i].$reflectableField = 1; | 204 funcs[i].$reflectableField = 1; |
| 124 funcs[i].$reflectionInfoField = array; | 205 funcs[i].$reflectionInfoField = array; |
| 125 } | 206 } |
| 126 var mangledNames = isStatic ? init.mangledGlobalNames : init.mangledNames; | 207 var mangledNames = isStatic ? init.mangledGlobalNames : init.mangledNames; |
| 127 var unmangledName = ${readString("array", "unmangledNameIndex")}; | 208 var unmangledName = ${readString("array", "unmangledNameIndex")}; |
| 128 ''' | |
| 129 // The function is either a getter, a setter, or a method. | 209 // The function is either a getter, a setter, or a method. |
| 130 // If it is a method, it might also have a tear-off closure. | 210 // If it is a method, it might also have a tear-off closure. |
| 131 // The unmangledName is the same as the getter-name. | 211 // The unmangledName is the same as the getter-name. |
| 132 ''' | |
| 133 var reflectionName = unmangledName; | 212 var reflectionName = unmangledName; |
| 134 if (getterStubName) mangledNames[getterStubName] = reflectionName; | 213 if (getterStubName) mangledNames[getterStubName] = reflectionName; |
| 135 if (isSetter) { | 214 if (isSetter) { |
| 136 reflectionName += "="; | 215 reflectionName += "="; |
| 137 } else if (!isGetter) { | 216 } else if (!isGetter) { |
| 138 reflectionName += ":" + requiredParameterCount +''' // Break long line. | 217 reflectionName += ":" + requiredParameterCount + |
| 139 ''' ":" + optionalParameterCount; | 218 ":" + optionalParameterCount; |
| 140 } | 219 } |
| 141 mangledNames[name] = reflectionName; | 220 mangledNames[name] = reflectionName; |
| 142 funcs[0].$reflectionNameField = reflectionName; | 221 funcs[0].$reflectionNameField = reflectionName; |
| 143 funcs[0].$metadataIndexField = unmangledNameIndex + 1; | 222 funcs[0].$metadataIndexField = unmangledNameIndex + 1; |
| 144 if (optionalParameterCount) descriptor[unmangledName + "*"] = funcs[0]; | 223 if (optionalParameterCount) descriptor[unmangledName + "*"] = funcs[0]; |
| 145 } | 224 } |
| 146 } | 225 } |
| 147 '''; | 226 '''; |
| 148 | 227 |
| 149 String tearOff = ''' | 228 String tearOff = ''' |
| 150 function tearOffGetterNoCsp(funcs, reflectionInfo, name, isIntercepted) { | 229 function tearOffGetterNoCsp(funcs, reflectionInfo, name, isIntercepted) { |
| 151 return isIntercepted | 230 return isIntercepted |
| 152 ? new Function("funcs", "reflectionInfo", "name",''' // Break long line. | 231 ? new Function("funcs", "reflectionInfo", "name", |
| 153 ''' "$tearOffGlobalObjectName", "c", | 232 "$tearOffGlobalObjectName", "c", |
| 154 "return function tearOff_" + name + (functionCounter++)+ "(x) {" + | 233 "return function tearOff_" + name + (functionCounter++)+ "(x) {" + |
| 155 "if (c === null) c = $tearOffAccess(" + | 234 "if (c === null) c = $tearOffAccess(" + |
| 156 "this, funcs, reflectionInfo, false, [x], name);" + | 235 "this, funcs, reflectionInfo, false, [x], name);" + |
| 157 "return new c(this, funcs[0], x, name);" + | 236 "return new c(this, funcs[0], x, name);" + |
| 158 "}")(funcs, reflectionInfo, name, $tearOffGlobalObject, null) | 237 "}")(funcs, reflectionInfo, name, $tearOffGlobalObject, null) |
| 159 : new Function("funcs", "reflectionInfo", "name",''' // Break long line. | 238 : new Function("funcs", "reflectionInfo", "name", |
| 160 ''' "$tearOffGlobalObjectName", "c", | 239 "$tearOffGlobalObjectName", "c", |
| 161 "return function tearOff_" + name + (functionCounter++)+ "() {" + | 240 "return function tearOff_" + name + (functionCounter++)+ "() {" + |
| 162 "if (c === null) c = $tearOffAccess(" + | 241 "if (c === null) c = $tearOffAccess(" + |
| 163 "this, funcs, reflectionInfo, false, [], name);" + | 242 "this, funcs, reflectionInfo, false, [], name);" + |
| 164 "return new c(this, funcs[0], null, name);" + | 243 "return new c(this, funcs[0], null, name);" + |
| 165 "}")(funcs, reflectionInfo, name, $tearOffGlobalObject, null) | 244 "}")(funcs, reflectionInfo, name, $tearOffGlobalObject, null); |
| 166 } | 245 } |
| 167 function tearOffGetterCsp(funcs, reflectionInfo, name, isIntercepted) { | 246 function tearOffGetterCsp(funcs, reflectionInfo, name, isIntercepted) { |
| 168 var cache = null; | 247 var cache = null; |
| 169 return isIntercepted | 248 return isIntercepted |
| 170 ? function(x) { | 249 ? function(x) { |
| 171 if (cache === null) cache = $tearOffAccess(''' // Break long line. | 250 if (cache === null) cache = $tearOffAccess( |
| 172 '''this, funcs, reflectionInfo, false, [x], name); | 251 this, funcs, reflectionInfo, false, [x], name); |
| 173 return new cache(this, funcs[0], x, name) | 252 return new cache(this, funcs[0], x, name); |
| 174 } | 253 } |
| 175 : function() { | 254 : function() { |
| 176 if (cache === null) cache = $tearOffAccess(''' // Break long line. | 255 if (cache === null) cache = $tearOffAccess( |
| 177 '''this, funcs, reflectionInfo, false, [], name); | 256 this, funcs, reflectionInfo, false, [], name); |
| 178 return new cache(this, funcs[0], null, name) | 257 return new cache(this, funcs[0], null, name); |
| 179 } | 258 }; |
| 180 } | 259 } |
| 181 function tearOff(funcs, reflectionInfo, isStatic, name, isIntercepted) { | 260 function tearOff(funcs, reflectionInfo, isStatic, name, isIntercepted) { |
| 182 var cache; | 261 var cache; |
| 183 return isStatic | 262 return isStatic |
| 184 ? function() { | 263 ? function() { |
| 185 if (cache === void 0) cache = $tearOffAccess(''' // Break long line. | 264 if (cache === void 0) cache = $tearOffAccess( |
| 186 '''this, funcs, reflectionInfo, true, [], name).prototype; | 265 this, funcs, reflectionInfo, true, [], name).prototype; |
| 187 return cache; | 266 return cache; |
| 188 } | 267 } |
| 189 : tearOffGetter(funcs, reflectionInfo, name, isIntercepted); | 268 : tearOffGetter(funcs, reflectionInfo, name, isIntercepted); |
| 190 } | 269 } |
| 191 '''; | 270 '''; |
| 192 | 271 |
| 193 | 272 |
| 194 | 273 |
| 195 | 274 |
| 196 String init = ''' | 275 String init = ''' |
| 197 var functionCounter = 0; | 276 var functionCounter = 0; |
| 198 var tearOffGetter = (typeof dart_precompiled == "function") | 277 var tearOffGetter = (typeof dart_precompiled == "function") |
| 199 ? tearOffGetterCsp : tearOffGetterNoCsp; | 278 ? tearOffGetterCsp : tearOffGetterNoCsp; |
| 200 if (!init.libraries) init.libraries = []; | 279 if (!init.libraries) init.libraries = []; |
| 201 if (!init.mangledNames) init.mangledNames = map(); | 280 if (!init.mangledNames) init.mangledNames = map(); |
| 202 if (!init.mangledGlobalNames) init.mangledGlobalNames = map(); | 281 if (!init.mangledGlobalNames) init.mangledGlobalNames = map(); |
| 203 if (!init.statics) init.statics = map(); | 282 if (!init.statics) init.statics = map(); |
| 204 if (!init.typeInformation) init.typeInformation = map(); | 283 if (!init.typeInformation) init.typeInformation = map(); |
| 205 if (!init.globalFunctions) init.globalFunctions = map(); | 284 if (!init.globalFunctions) init.globalFunctions = map(); |
| 206 if (!init.interceptedNames) init.interceptedNames = map(); | 285 if (!init.interceptedNames) init.interceptedNames = map(); |
| 207 var libraries = init.libraries; | 286 var libraries = init.libraries; |
| 208 var mangledNames = init.mangledNames; | 287 var mangledNames = init.mangledNames; |
| 209 var mangledGlobalNames = init.mangledGlobalNames; | 288 var mangledGlobalNames = init.mangledGlobalNames; |
| 210 var hasOwnProperty = Object.prototype.hasOwnProperty; | 289 var hasOwnProperty = Object.prototype.hasOwnProperty; |
| 211 var length = reflectionData.length; | 290 var length = reflectionData.length; |
| 212 for (var i = 0; i < length; i++) { | 291 for (var i = 0; i < length; i++) { |
| 213 var data = reflectionData[i]; | 292 var data = reflectionData[i]; |
| 214 ''' | 293 |
| 215 // [data] contains these elements: | 294 // [data] contains these elements: |
| 216 // 0. The library name (not unique). | 295 // 0. The library name (not unique). |
| 217 // 1. The library URI (unique). | 296 // 1. The library URI (unique). |
| 218 // 2. A function returning the metadata associated with this library. | 297 // 2. A function returning the metadata associated with this library. |
| 219 // 3. The global object to use for this library. | 298 // 3. The global object to use for this library. |
| 220 // 4. An object literal listing the members of the library. | 299 // 4. An object literal listing the members of the library. |
| 221 // 5. This element is optional and if present it is true and signals that this | 300 // 5. This element is optional and if present it is true and signals that this |
| 222 // library is the root library (see dart:mirrors IsolateMirror.rootLibrary). | 301 // library is the root library (see dart:mirrors IsolateMirror.rootLibrary). |
| 223 // | 302 // |
| 224 // The entries of [data] are built in [assembleProgram] above. | 303 // The entries of [data] are built in [assembleProgram] above. |
| 225 ''' | 304 |
| 226 var name = data[0]; | 305 var name = data[0]; |
| 227 var uri = data[1]; | 306 var uri = data[1]; |
| 228 var metadata = data[2]; | 307 var metadata = data[2]; |
| 229 var globalObject = data[3]; | 308 var globalObject = data[3]; |
| 230 var descriptor = data[4]; | 309 var descriptor = data[4]; |
| 231 var isRoot = !!data[5]; | 310 var isRoot = !!data[5]; |
| 232 var fields = descriptor && descriptor["${namer.classDescriptorProperty}"]; | 311 var fields = descriptor && descriptor["${namer.classDescriptorProperty}"]; |
| 233 var classes = []; | 312 var classes = []; |
| 234 var functions = []; | 313 var functions = []; |
| 235 '''; | 314 '''; |
| 236 | 315 |
| 237 String processStatics = ''' | |
| 238 function processStatics(descriptor) { | |
| 239 for (var property in descriptor) { | |
| 240 if (!hasOwnProperty.call(descriptor, property)) continue; | |
| 241 if (property === "${namer.classDescriptorProperty}") continue; | |
| 242 var element = descriptor[property]; | |
| 243 var firstChar = property.substring(0, 1); | |
| 244 var previousProperty; | |
| 245 if (firstChar === "+") { | |
| 246 mangledGlobalNames[previousProperty] = property.substring(1); | |
| 247 var flag = descriptor[property]; | |
| 248 if (flag > 0) ''' // Break long line. | |
| 249 '''descriptor[previousProperty].$reflectableField = flag; | |
| 250 if (element && element.length) ''' // Break long line. | |
| 251 '''init.typeInformation[previousProperty] = element; | |
| 252 } else if (firstChar === "@") { | |
| 253 property = property.substring(1); | |
| 254 ${namer.currentIsolate}[property][$metadataField] = element; | |
| 255 } else if (firstChar === "*") { | |
| 256 globalObject[previousProperty].$defaultValuesField = element; | |
| 257 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField; | |
| 258 if (!optionalMethods) { | |
| 259 descriptor.$methodsWithOptionalArgumentsField = optionalMethods = {} | |
| 260 } | |
| 261 optionalMethods[property] = previousProperty; | |
| 262 } else if (typeof element === "function") { | |
| 263 globalObject[previousProperty = property] = element; | |
| 264 functions.push(property); | |
| 265 init.globalFunctions[property] = element; | |
| 266 } else if (element.constructor === Array) { | |
| 267 addStubs(globalObject, element, property, ''' // Break long line. | |
| 268 '''true, descriptor, functions); | |
| 269 } else { | |
| 270 previousProperty = property; | |
| 271 var newDesc = {}; | |
| 272 var previousProp; | |
| 273 for (var prop in element) { | |
| 274 if (!hasOwnProperty.call(element, prop)) continue; | |
| 275 firstChar = prop.substring(0, 1); | |
| 276 if (prop === "static") { | |
| 277 processStatics(init.statics[property] = element[prop]); | |
| 278 } else if (firstChar === "+") { | |
| 279 mangledNames[previousProp] = prop.substring(1); | |
| 280 var flag = element[prop]; | |
| 281 if (flag > 0) ''' // Break long line. | |
| 282 '''element[previousProp].$reflectableField = flag; | |
| 283 } else if (firstChar === "@" && prop !== "@") { | |
| 284 newDesc[prop.substring(1)][$metadataField] = element[prop]; | |
| 285 } else if (firstChar === "*") { | |
| 286 newDesc[previousProp].$defaultValuesField = element[prop]; | |
| 287 var optionalMethods = newDesc.$methodsWithOptionalArgumentsField; | |
| 288 if (!optionalMethods) { | |
| 289 newDesc.$methodsWithOptionalArgumentsField = optionalMethods={} | |
| 290 } | |
| 291 optionalMethods[prop] = previousProp; | |
| 292 } else { | |
| 293 var elem = element[prop]; | |
| 294 if (prop !== "${namer.classDescriptorProperty}" &&''' | |
| 295 ''' elem != null &&''' // Break long line. | |
| 296 ''' elem.constructor === Array &&''' // Break long line. | |
| 297 ''' prop !== "<>") { | |
| 298 addStubs(newDesc, elem, prop, false, element, []); | |
| 299 } else { | |
| 300 newDesc[previousProp = prop] = elem; | |
| 301 } | |
| 302 } | |
| 303 } | |
| 304 $classesCollector[property] = [globalObject, newDesc]; | |
| 305 classes.push(property); | |
| 306 } | |
| 307 } | |
| 308 } | |
| 309 '''; | |
| 310 | |
| 311 String footer = ''' | 316 String footer = ''' |
| 312 processStatics(descriptor); | 317 processStatics(descriptor); |
| 313 libraries.push([name, uri, classes, functions, metadata, fields, isRoot, | 318 libraries.push([name, uri, classes, functions, metadata, fields, isRoot, |
| 314 globalObject]); | 319 globalObject]); |
| 315 } | 320 } |
| 316 }) | 321 }) |
| 317 '''; | 322 '''; |
| 318 | 323 |
| 319 return '$header$processStatics$addStubs$tearOff$init$footer'; | 324 return '$header$processStatics$addStubs$tearOff$init$footer'; |
| 320 } | 325 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 (function() { | 357 (function() { |
| 353 var result = $array[$index]; | 358 var result = $array[$index]; |
| 354 if ($check) { | 359 if ($check) { |
| 355 throw new Error( | 360 throw new Error( |
| 356 name + ": expected value of type \'$type\' at index " + ($index) + | 361 name + ": expected value of type \'$type\' at index " + ($index) + |
| 357 " but got " + (typeof result)); | 362 " but got " + (typeof result)); |
| 358 } | 363 } |
| 359 return result; | 364 return result; |
| 360 })()'''; | 365 })()'''; |
| 361 } | 366 } |
| OLD | NEW |