| 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(zarah): Rename this when renaming this file. | 17 // TODO(zarah): Rename this when renaming this file. |
| 18 String get parseReflectionDataName => 'parseReflectionData'; | 18 String get parseReflectionDataName => 'parseReflectionData'; |
| 19 | 19 |
| 20 jsAst.Expression getReflectionDataParser(OldEmitter oldEmitter, | 20 jsAst.Statement getReflectionDataParser(OldEmitter oldEmitter, |
| 21 JavaScriptBackend backend, | 21 JavaScriptBackend backend, |
| 22 bool needsNativeSupport) { | 22 bool needsNativeSupport) { |
| 23 Namer namer = backend.namer; | 23 Namer namer = backend.namer; |
| 24 Compiler compiler = backend.compiler; | 24 Compiler compiler = backend.compiler; |
| 25 CodeEmitterTask emitter = backend.emitter; | 25 CodeEmitterTask emitter = backend.emitter; |
| 26 | 26 |
| 27 String reflectableField = namer.reflectableField; | 27 String reflectableField = namer.reflectableField; |
| 28 String reflectionInfoField = namer.reflectionInfoField; | 28 String reflectionInfoField = namer.reflectionInfoField; |
| 29 String reflectionNameField = namer.reflectionNameField; | 29 String reflectionNameField = namer.reflectionNameField; |
| 30 String metadataIndexField = namer.metadataIndexField; | 30 String metadataIndexField = namer.metadataIndexField; |
| 31 String defaultValuesField = namer.defaultValuesField; | 31 String defaultValuesField = namer.defaultValuesField; |
| 32 String methodsWithOptionalArgumentsField = | 32 String methodsWithOptionalArgumentsField = |
| (...skipping 13 matching lines...) Expand all 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 typesAccess = | 53 jsAst.Expression typesAccess = |
| 54 emitter.generateEmbeddedGlobalAccess(embeddedNames.TYPES); | 54 emitter.generateEmbeddedGlobalAccess(embeddedNames.TYPES); |
| 55 | 55 |
| 56 |
| 56 jsAst.Statement processClassData = js.statement('''{ | 57 jsAst.Statement processClassData = js.statement('''{ |
| 58 // For convenience, this method can be called with a prototype as argument |
| 59 // or, if it was bound to an object, by invoking it as a method. Therefore, |
| 60 // if prototype is undefined, this is used as prototype. |
| 61 function finishAddStubsHelper(prototype) { |
| 62 var prototype = prototype || this; |
| 63 var object; |
| 64 while (prototype.#deferredAction != #markerFun) { |
| 65 if (prototype.hasOwnProperty(#deferredActionString)) { |
| 66 delete prototype.#deferredAction; // Intended to make it slow, too. |
| 67 var properties = Object.keys(prototype); |
| 68 for (var index = 0; index < properties.length; index++) { |
| 69 var property = properties[index]; |
| 70 var firstChar = property.charCodeAt(0); |
| 71 var elem; |
| 72 // We have to filter out some special properties that are used for |
| 73 // metadata in descriptors. Currently, we filter everything that |
| 74 // starts with + or *. This has to stay in sync with the special |
| 75 // properties that are used by processClassData below. |
| 76 if (property !== "${namer.classDescriptorProperty}" && |
| 77 property !== "$reflectableField" && |
| 78 firstChar !== 43 && // 43 is aka "+". |
| 79 firstChar !== 42 && // 42 is aka "*" |
| 80 (elem = prototype[property]) != null && |
| 81 elem.constructor === Array && |
| 82 property !== "<>") { |
| 83 addStubs(prototype, elem, property, false, []); |
| 84 } |
| 85 } |
| 86 convertToFastObject(prototype); |
| 87 } |
| 88 prototype = prototype.__proto__; |
| 89 } |
| 90 } |
| 91 |
| 57 function processClassData(cls, descriptor, processedClasses) { | 92 function processClassData(cls, descriptor, processedClasses) { |
| 58 descriptor = convertToSlowObject(descriptor); // Use a slow object. | 93 descriptor = convertToSlowObject(descriptor); // Use a slow object. |
| 59 var previousProperty; | 94 var previousProperty; |
| 60 var properties = Object.keys(descriptor); | 95 var properties = Object.keys(descriptor); |
| 96 var hasDeferredWork = false; |
| 97 var shouldDeferWork = supportsDirectProtoAccess && cls != #objectClassName; |
| 61 for (var i = 0; i < properties.length; i++) { | 98 for (var i = 0; i < properties.length; i++) { |
| 62 var property = properties[i]; | 99 var property = properties[i]; |
| 63 var firstChar = property.charCodeAt(0); | 100 var firstChar = property.charCodeAt(0); |
| 64 if (property === "static") { | 101 if (property === "static") { |
| 65 processStatics(#embeddedStatics[cls] = descriptor.static, | 102 processStatics(#embeddedStatics[cls] = descriptor.static, |
| 66 processedClasses); | 103 processedClasses); |
| 104 delete descriptor.static; |
| 67 } else if (firstChar === 43) { // 43 is "+". | 105 } else if (firstChar === 43) { // 43 is "+". |
| 68 mangledNames[previousProperty] = property.substring(1); | 106 mangledNames[previousProperty] = property.substring(1); |
| 69 var flag = descriptor[property]; | 107 var flag = descriptor[property]; |
| 70 if (flag > 0) | 108 if (flag > 0) |
| 71 descriptor[previousProperty].$reflectableField = flag; | 109 descriptor[previousProperty].$reflectableField = flag; |
| 72 } else if (firstChar === 42) { // 42 is "*" | 110 } else if (firstChar === 42) { // 42 is "*" |
| 73 descriptor[previousProperty].$defaultValuesField = descriptor[property]; | 111 descriptor[previousProperty].$defaultValuesField = descriptor[property]; |
| 74 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField; | 112 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField; |
| 75 if (!optionalMethods) { | 113 if (!optionalMethods) { |
| 76 descriptor.$methodsWithOptionalArgumentsField = optionalMethods={} | 114 descriptor.$methodsWithOptionalArgumentsField = optionalMethods={} |
| 77 } | 115 } |
| 78 optionalMethods[property] = previousProperty; | 116 optionalMethods[property] = previousProperty; |
| 79 } else { | 117 } else { |
| 80 var elem = descriptor[property]; | 118 var elem = descriptor[property]; |
| 81 if (property !== "${namer.classDescriptorProperty}" && | 119 if (property !== "${namer.classDescriptorProperty}" && |
| 82 elem != null && | 120 elem != null && |
| 83 elem.constructor === Array && | 121 elem.constructor === Array && |
| 84 property !== "<>") { | 122 property !== "<>") { |
| 85 addStubs(descriptor, elem, property, false, []); | 123 if (shouldDeferWork) { |
| 124 hasDeferredWork = true; |
| 125 } else { |
| 126 addStubs(descriptor, elem, property, false, []); |
| 127 } |
| 86 } else { | 128 } else { |
| 87 previousProperty = property; | 129 previousProperty = property; |
| 88 } | 130 } |
| 89 } | 131 } |
| 90 } | 132 } |
| 133 |
| 134 if (hasDeferredWork) |
| 135 descriptor.#deferredAction = finishAddStubsHelper; |
| 91 | 136 |
| 92 /* The 'fields' are either a constructor function or a | 137 /* The 'fields' are either a constructor function or a |
| 93 * string encoding fields, constructor and superclass. Gets the | 138 * string encoding fields, constructor and superclass. Gets the |
| 94 * superclass and fields in the format | 139 * superclass and fields in the format |
| 95 * 'Super;field1,field2' | 140 * 'Super;field1,field2' |
| 96 * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor. | 141 * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor. |
| 97 */ | 142 */ |
| 98 var classData = descriptor["${namer.classDescriptorProperty}"], | 143 var classData = descriptor["${namer.classDescriptorProperty}"], |
| 99 split, supr, fields = classData; | 144 split, supr, fields = classData; |
| 100 | 145 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 121 } | 166 } |
| 122 | 167 |
| 123 if (supr) processedClasses.pending[cls] = supr; | 168 if (supr) processedClasses.pending[cls] = supr; |
| 124 if (#notInCspMode) { | 169 if (#notInCspMode) { |
| 125 processedClasses.combinedConstructorFunction += defineClass(cls, fields); | 170 processedClasses.combinedConstructorFunction += defineClass(cls, fields); |
| 126 processedClasses.constructorsList.push(cls); | 171 processedClasses.constructorsList.push(cls); |
| 127 } | 172 } |
| 128 processedClasses.collected[cls] = [globalObject, descriptor]; | 173 processedClasses.collected[cls] = [globalObject, descriptor]; |
| 129 classes.push(cls); | 174 classes.push(cls); |
| 130 } | 175 } |
| 131 }''', {'embeddedStatics': staticsAccess, | 176 }''', {'deferredAction': namer.deferredAction, |
| 177 'deferredActionString': js.string(namer.deferredAction), |
| 178 'embeddedStatics': staticsAccess, |
| 132 'hasRetainedMetadata': backend.hasRetainedMetadata, | 179 'hasRetainedMetadata': backend.hasRetainedMetadata, |
| 180 'markerFun': oldEmitter.markerFun, |
| 133 'types': typesAccess, | 181 'types': typesAccess, |
| 134 'notInCspMode': !compiler.useContentSecurityPolicy}); | 182 'notInCspMode': !compiler.useContentSecurityPolicy, |
| 183 'objectClassName': |
| 184 js.string(namer.runtimeTypeName(compiler.objectClass))}); |
| 135 | 185 |
| 136 // TODO(zarah): Remove empty else branches in output when if(#hole) is false. | 186 // TODO(zarah): Remove empty else branches in output when if(#hole) is false. |
| 137 jsAst.Statement processStatics = js.statement(''' | 187 jsAst.Statement processStatics = js.statement(''' |
| 138 function processStatics(descriptor, processedClasses) { | 188 function processStatics(descriptor, processedClasses) { |
| 139 var properties = Object.keys(descriptor); | 189 var properties = Object.keys(descriptor); |
| 140 for (var i = 0; i < properties.length; i++) { | 190 for (var i = 0; i < properties.length; i++) { |
| 141 var property = properties[i]; | 191 var property = properties[i]; |
| 142 if (property === "${namer.classDescriptorProperty}") continue; | 192 if (property === "${namer.classDescriptorProperty}") continue; |
| 143 var element = descriptor[property]; | 193 var element = descriptor[property]; |
| 144 var firstChar = property.charCodeAt(0); | 194 var firstChar = property.charCodeAt(0); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 'globalFunctions': globalFunctionsAccess, | 228 'globalFunctions': globalFunctionsAccess, |
| 179 'hasClasses': oldEmitter.needsClassSupport, | 229 'hasClasses': oldEmitter.needsClassSupport, |
| 180 'needsStructuredMemberInfo': oldEmitter.needsStructuredMemberInfo}); | 230 'needsStructuredMemberInfo': oldEmitter.needsStructuredMemberInfo}); |
| 181 | 231 |
| 182 | 232 |
| 183 /** | 233 /** |
| 184 * See [dart2js.js_emitter.ContainerBuilder.addMemberMethod] for format of | 234 * See [dart2js.js_emitter.ContainerBuilder.addMemberMethod] for format of |
| 185 * [array]. | 235 * [array]. |
| 186 */ | 236 */ |
| 187 jsAst.Statement addStubs = js.statement(''' | 237 jsAst.Statement addStubs = js.statement(''' |
| 188 function addStubs(descriptor, array, name, isStatic, functions) { | 238 // Processes the stub declaration given by [array] and stores the results |
| 239 // in the corresponding [prototype]. [name] is the property name in |
| 240 // [prototype] that the stub declaration belongs to. |
| 241 // If [isStatic] is true, the property being processed belongs to a static |
| 242 // function and thus is stored as a global. In that case we also add all |
| 243 // generated functions to the [functions] array, which is used by the mirrors |
| 244 // system to enumerate all static functions of a library. For non-static |
| 245 // functions we might still add some functions to [functions] but the |
| 246 // information is thrown away at the call site. This is to avoid conditionals.
|
| 247 function addStubs(prototype, array, name, isStatic, functions) { |
| 189 var index = $FUNCTION_INDEX, alias = array[index], f; | 248 var index = $FUNCTION_INDEX, alias = array[index], f; |
| 190 if (typeof alias == "string") { | 249 if (typeof alias == "string") { |
| 191 f = array[++index]; | 250 f = array[++index]; |
| 192 } else { | 251 } else { |
| 193 f = alias; | 252 f = alias; |
| 194 alias = name; | 253 alias = name; |
| 195 } | 254 } |
| 196 var funcs = [descriptor[name] = descriptor[alias] = f]; | 255 var funcs = [prototype[name] = prototype[alias] = f]; |
| 197 f.\$stubName = name; | 256 f.\$stubName = name; |
| 198 functions.push(name); | 257 functions.push(name); |
| 199 for (; index < array.length; index += 2) { | 258 for (; index < array.length; index += 2) { |
| 200 f = array[index + 1]; | 259 f = array[index + 1]; |
| 201 if (typeof f != "function") break; | 260 if (typeof f != "function") break; |
| 202 f.\$stubName = ${readString("array", "index + 2")}; | 261 f.\$stubName = ${readString("array", "index + 2")}; |
| 203 funcs.push(f); | 262 funcs.push(f); |
| 204 if (f.\$stubName) { | 263 if (f.\$stubName) { |
| 205 descriptor[f.\$stubName] = f; | 264 prototype[f.\$stubName] = f; |
| 206 functions.push(f.\$stubName); | 265 functions.push(f.\$stubName); |
| 207 } | 266 } |
| 208 } | 267 } |
| 209 index++; | 268 index++; |
| 210 for (var i = 0; i < funcs.length; index++, i++) { | 269 for (var i = 0; i < funcs.length; index++, i++) { |
| 211 funcs[i].\$callName = ${readString("array", "index")}; | 270 funcs[i].\$callName = ${readString("array", "index")}; |
| 212 } | 271 } |
| 213 var getterStubName = ${readString("array", "index")}; | 272 var getterStubName = ${readString("array", "index")}; |
| 214 array = array.slice(++index); | 273 array = array.slice(++index); |
| 215 var requiredParameterInfo = ${readInt("array", "0")}; | 274 var requiredParameterInfo = ${readInt("array", "0")}; |
| 216 var requiredParameterCount = requiredParameterInfo >> 1; | 275 var requiredParameterCount = requiredParameterInfo >> 1; |
| 217 var isAccessor = (requiredParameterInfo & 1) === 1; | 276 var isAccessor = (requiredParameterInfo & 1) === 1; |
| 218 var isSetter = requiredParameterInfo === 3; | 277 var isSetter = requiredParameterInfo === 3; |
| 219 var isGetter = requiredParameterInfo === 1; | 278 var isGetter = requiredParameterInfo === 1; |
| 220 var optionalParameterInfo = ${readInt("array", "1")}; | 279 var optionalParameterInfo = ${readInt("array", "1")}; |
| 221 var optionalParameterCount = optionalParameterInfo >> 1; | 280 var optionalParameterCount = optionalParameterInfo >> 1; |
| 222 var optionalParametersAreNamed = (optionalParameterInfo & 1) === 1; | 281 var optionalParametersAreNamed = (optionalParameterInfo & 1) === 1; |
| 223 var isIntercepted = | 282 var isIntercepted = |
| 224 requiredParameterCount + optionalParameterCount != funcs[0].length; | 283 requiredParameterCount + optionalParameterCount != funcs[0].length; |
| 225 var functionTypeIndex = ${readFunctionType("array", "2")}; | 284 var functionTypeIndex = ${readFunctionType("array", "2")}; |
| 226 var unmangledNameIndex = $unmangledNameIndex; | 285 var unmangledNameIndex = $unmangledNameIndex; |
| 227 | 286 |
| 228 if (getterStubName) { | 287 if (getterStubName) { |
| 229 f = tearOff(funcs, array, isStatic, name, isIntercepted); | 288 f = tearOff(funcs, array, isStatic, name, isIntercepted); |
| 230 descriptor[name].\$getter = f; | 289 prototype[name].\$getter = f; |
| 231 f.\$getterStub = true; | 290 f.\$getterStub = true; |
| 232 // Used to create an isolate using spawnFunction. | 291 // Used to create an isolate using spawnFunction. |
| 233 if (isStatic) #globalFunctions[name] = f; | 292 if (isStatic) { |
| 234 descriptor[getterStubName] = f; | 293 #globalFunctions[name] = f; |
| 294 functions.push(getterStubName); |
| 295 } |
| 296 prototype[getterStubName] = f; |
| 235 funcs.push(f); | 297 funcs.push(f); |
| 236 if (getterStubName) functions.push(getterStubName); | |
| 237 f.\$stubName = getterStubName; | 298 f.\$stubName = getterStubName; |
| 238 f.\$callName = null; | 299 f.\$callName = null; |
| 239 // Update the interceptedNames map (which only exists if `invokeOn` was | 300 // Update the interceptedNames map (which only exists if `invokeOn` was |
| 240 // enabled). | 301 // enabled). |
| 241 if (#enabledInvokeOn) | 302 if (#enabledInvokeOn) |
| 242 if (isIntercepted) #interceptedNames[getterStubName] = 1; | 303 if (isIntercepted) #interceptedNames[getterStubName] = 1; |
| 243 } | 304 } |
| 244 | 305 |
| 245 if (#usesMangledNames) { | 306 if (#usesMangledNames) { |
| 246 var isReflectable = array.length > unmangledNameIndex; | 307 var isReflectable = array.length > unmangledNameIndex; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 258 if (getterStubName) mangledNames[getterStubName] = reflectionName; | 319 if (getterStubName) mangledNames[getterStubName] = reflectionName; |
| 259 if (isSetter) { | 320 if (isSetter) { |
| 260 reflectionName += "="; | 321 reflectionName += "="; |
| 261 } else if (!isGetter) { | 322 } else if (!isGetter) { |
| 262 reflectionName += ":" + requiredParameterCount + | 323 reflectionName += ":" + requiredParameterCount + |
| 263 ":" + optionalParameterCount; | 324 ":" + optionalParameterCount; |
| 264 } | 325 } |
| 265 mangledNames[name] = reflectionName; | 326 mangledNames[name] = reflectionName; |
| 266 funcs[0].$reflectionNameField = reflectionName; | 327 funcs[0].$reflectionNameField = reflectionName; |
| 267 funcs[0].$metadataIndexField = unmangledNameIndex + 1; | 328 funcs[0].$metadataIndexField = unmangledNameIndex + 1; |
| 268 if (optionalParameterCount) descriptor[unmangledName + "*"] = funcs[0]; | 329 if (optionalParameterCount) prototype[unmangledName + "*"] = funcs[0]; |
| 269 } | 330 } |
| 270 } | 331 } |
| 271 } | 332 } |
| 272 ''', {'globalFunctions': globalFunctionsAccess, | 333 ''', {'globalFunctions': globalFunctionsAccess, |
| 273 'enabledInvokeOn': compiler.enabledInvokeOn, | 334 'enabledInvokeOn': compiler.enabledInvokeOn, |
| 274 'interceptedNames': interceptedNamesAccess, | 335 'interceptedNames': interceptedNamesAccess, |
| 275 'usesMangledNames': | 336 'usesMangledNames': |
| 276 compiler.mirrorsLibrary != null || compiler.enabledFunctionApply, | 337 compiler.mirrorsLibrary != null || compiler.enabledFunctionApply, |
| 277 'mangledGlobalNames': mangledGlobalNamesAccess, | 338 'mangledGlobalNames': mangledGlobalNamesAccess, |
| 278 'mangledNames': mangledNamesAccess}); | 339 'mangledNames': mangledNamesAccess}); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 'precompiled': oldEmitter | 481 'precompiled': oldEmitter |
| 421 .generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED)}); | 482 .generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED)}); |
| 422 | 483 |
| 423 List<jsAst.Statement> incrementalSupport = <jsAst.Statement>[]; | 484 List<jsAst.Statement> incrementalSupport = <jsAst.Statement>[]; |
| 424 if (compiler.hasIncrementalSupport) { | 485 if (compiler.hasIncrementalSupport) { |
| 425 incrementalSupport.add( | 486 incrementalSupport.add( |
| 426 js.statement( | 487 js.statement( |
| 427 '#.addStubs = addStubs;', [namer.accessIncrementalHelper])); | 488 '#.addStubs = addStubs;', [namer.accessIncrementalHelper])); |
| 428 } | 489 } |
| 429 | 490 |
| 430 return js(''' | 491 return js.statement(''' |
| 431 function $parseReflectionDataName(reflectionData) { | 492 function $parseReflectionDataName(reflectionData) { |
| 432 "use strict"; | 493 "use strict"; |
| 433 if (#needsClassSupport) { | 494 if (#needsClassSupport) { |
| 434 #defineClass; | 495 #defineClass; |
| 435 #inheritFrom; | 496 #inheritFrom; |
| 436 #finishClasses; | 497 #finishClasses; |
| 437 #processClassData; | 498 #processClassData; |
| 438 } | 499 } |
| 439 #processStatics; | 500 #processStatics; |
| 440 if (#needsStructuredMemberInfo) { | 501 if (#needsStructuredMemberInfo) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 (function() { | 545 (function() { |
| 485 var result = $array[$index]; | 546 var result = $array[$index]; |
| 486 if ($check) { | 547 if ($check) { |
| 487 throw new Error( | 548 throw new Error( |
| 488 name + ": expected value of type \'$type\' at index " + ($index) + | 549 name + ": expected value of type \'$type\' at index " + ($index) + |
| 489 " but got " + (typeof result)); | 550 " but got " + (typeof result)); |
| 490 } | 551 } |
| 491 return result; | 552 return result; |
| 492 })()'''; | 553 })()'''; |
| 493 } | 554 } |
| OLD | NEW |