| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 function GlobalIsFinite(number) { | 85 function GlobalIsFinite(number) { |
| 86 if (!IS_NUMBER(number)) number = NonNumberToNumber(number); | 86 if (!IS_NUMBER(number)) number = NonNumberToNumber(number); |
| 87 | 87 |
| 88 // NaN - NaN == NaN, Infinity - Infinity == NaN, -Infinity - -Infinity == NaN. | 88 // NaN - NaN == NaN, Infinity - Infinity == NaN, -Infinity - -Infinity == NaN. |
| 89 return %_IsSmi(number) || number - number == 0; | 89 return %_IsSmi(number) || number - number == 0; |
| 90 } | 90 } |
| 91 | 91 |
| 92 | 92 |
| 93 // ECMA-262 - 15.1.2.2 | 93 // ECMA-262 - 15.1.2.2 |
| 94 function GlobalParseInt(string, radix) { | 94 function GlobalParseInt(string, radix) { |
| 95 if (IS_UNDEFINED(radix)) { | 95 if (IS_UNDEFINED(radix) || radix === 10 || radix === 0) { |
| 96 // Some people use parseInt instead of Math.floor. This | 96 // Some people use parseInt instead of Math.floor. This |
| 97 // optimization makes parseInt on a Smi 12 times faster (60ns | 97 // optimization makes parseInt on a Smi 12 times faster (60ns |
| 98 // vs 800ns). The following optimization makes parseInt on a | 98 // vs 800ns). The following optimization makes parseInt on a |
| 99 // non-Smi number 9 times faster (230ns vs 2070ns). Together | 99 // non-Smi number 9 times faster (230ns vs 2070ns). Together |
| 100 // they make parseInt on a string 1.4% slower (274ns vs 270ns). | 100 // they make parseInt on a string 1.4% slower (274ns vs 270ns). |
| 101 if (%_IsSmi(string)) return string; | 101 if (%_IsSmi(string)) return string; |
| 102 if (IS_NUMBER(string) && | 102 if (IS_NUMBER(string) && |
| 103 ((0.01 < string && string < 1e9) || | 103 ((0.01 < string && string < 1e9) || |
| 104 (-1e9 < string && string < -0.01))) { | 104 (-1e9 < string && string < -0.01))) { |
| 105 // Truncate number. | 105 // Truncate number. |
| 106 return string | 0; | 106 return string | 0; |
| 107 } | 107 } |
| 108 radix = 0; | 108 if (IS_UNDEFINED(radix)) radix = 0; |
| 109 } else { | 109 } else { |
| 110 radix = TO_INT32(radix); | 110 radix = TO_INT32(radix); |
| 111 if (!(radix == 0 || (2 <= radix && radix <= 36))) | 111 if (!(radix == 0 || (2 <= radix && radix <= 36))) |
| 112 return $NaN; | 112 return $NaN; |
| 113 } | 113 } |
| 114 string = TO_STRING_INLINE(string); | 114 string = TO_STRING_INLINE(string); |
| 115 if (%_HasCachedArrayIndex(string) && | 115 if (%_HasCachedArrayIndex(string) && |
| 116 (radix == 0 || radix == 10)) { | 116 (radix == 0 || radix == 10)) { |
| 117 return %_GetCachedArrayIndex(string); | 117 return %_GetCachedArrayIndex(string); |
| 118 } | 118 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 136 var global_is_detached = (global === global_receiver); | 136 var global_is_detached = (global === global_receiver); |
| 137 | 137 |
| 138 if (!this_is_global_receiver || global_is_detached) { | 138 if (!this_is_global_receiver || global_is_detached) { |
| 139 throw new $EvalError('The "this" object passed to eval must ' + | 139 throw new $EvalError('The "this" object passed to eval must ' + |
| 140 'be the global object from which eval originated'); | 140 'be the global object from which eval originated'); |
| 141 } | 141 } |
| 142 | 142 |
| 143 var f = %CompileString(x); | 143 var f = %CompileString(x); |
| 144 if (!IS_FUNCTION(f)) return f; | 144 if (!IS_FUNCTION(f)) return f; |
| 145 | 145 |
| 146 return f.call(this); | 146 return %_CallFunction(this, f); |
| 147 } | 147 } |
| 148 | 148 |
| 149 | 149 |
| 150 // execScript for IE compatibility. | 150 // execScript for IE compatibility. |
| 151 function GlobalExecScript(expr, lang) { | 151 function GlobalExecScript(expr, lang) { |
| 152 // NOTE: We don't care about the character casing. | 152 // NOTE: We don't care about the character casing. |
| 153 if (!lang || /javascript/i.test(lang)) { | 153 if (!lang || /javascript/i.test(lang)) { |
| 154 var f = %CompileString(ToString(expr)); | 154 var f = %CompileString(ToString(expr)); |
| 155 f.call(%GlobalReceiver(global)); | 155 %_CallFunction(%GlobalReceiver(global), f); |
| 156 } | 156 } |
| 157 return null; | 157 return null; |
| 158 } | 158 } |
| 159 | 159 |
| 160 | 160 |
| 161 // ---------------------------------------------------------------------------- | 161 // ---------------------------------------------------------------------------- |
| 162 | 162 |
| 163 | 163 |
| 164 function SetupGlobal() { | 164 function SetupGlobal() { |
| 165 // ECMA 262 - 15.1.1.1. | 165 // ECMA 262 - 15.1.1.1. |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 | 244 |
| 245 | 245 |
| 246 // Extensions for providing property getters and setters. | 246 // Extensions for providing property getters and setters. |
| 247 function ObjectDefineGetter(name, fun) { | 247 function ObjectDefineGetter(name, fun) { |
| 248 if (this == null && !IS_UNDETECTABLE(this)) { | 248 if (this == null && !IS_UNDETECTABLE(this)) { |
| 249 throw new $TypeError('Object.prototype.__defineGetter__: this is Null'); | 249 throw new $TypeError('Object.prototype.__defineGetter__: this is Null'); |
| 250 } | 250 } |
| 251 if (!IS_FUNCTION(fun)) { | 251 if (!IS_FUNCTION(fun)) { |
| 252 throw new $TypeError('Object.prototype.__defineGetter__: Expecting function'
); | 252 throw new $TypeError('Object.prototype.__defineGetter__: Expecting function'
); |
| 253 } | 253 } |
| 254 return %DefineAccessor(ToObject(this), ToString(name), GETTER, fun); | 254 var desc = new PropertyDescriptor(); |
| 255 desc.setGet(fun); |
| 256 desc.setEnumerable(true); |
| 257 desc.setConfigurable(true); |
| 258 DefineOwnProperty(ToObject(this), ToString(name), desc, false); |
| 255 } | 259 } |
| 256 | 260 |
| 257 | 261 |
| 258 function ObjectLookupGetter(name) { | 262 function ObjectLookupGetter(name) { |
| 259 if (this == null && !IS_UNDETECTABLE(this)) { | 263 if (this == null && !IS_UNDETECTABLE(this)) { |
| 260 throw new $TypeError('Object.prototype.__lookupGetter__: this is Null'); | 264 throw new $TypeError('Object.prototype.__lookupGetter__: this is Null'); |
| 261 } | 265 } |
| 262 return %LookupAccessor(ToObject(this), ToString(name), GETTER); | 266 return %LookupAccessor(ToObject(this), ToString(name), GETTER); |
| 263 } | 267 } |
| 264 | 268 |
| 265 | 269 |
| 266 function ObjectDefineSetter(name, fun) { | 270 function ObjectDefineSetter(name, fun) { |
| 267 if (this == null && !IS_UNDETECTABLE(this)) { | 271 if (this == null && !IS_UNDETECTABLE(this)) { |
| 268 throw new $TypeError('Object.prototype.__defineSetter__: this is Null'); | 272 throw new $TypeError('Object.prototype.__defineSetter__: this is Null'); |
| 269 } | 273 } |
| 270 if (!IS_FUNCTION(fun)) { | 274 if (!IS_FUNCTION(fun)) { |
| 271 throw new $TypeError( | 275 throw new $TypeError( |
| 272 'Object.prototype.__defineSetter__: Expecting function'); | 276 'Object.prototype.__defineSetter__: Expecting function'); |
| 273 } | 277 } |
| 274 return %DefineAccessor(ToObject(this), ToString(name), SETTER, fun); | 278 var desc = new PropertyDescriptor(); |
| 279 desc.setSet(fun); |
| 280 desc.setEnumerable(true); |
| 281 desc.setConfigurable(true); |
| 282 DefineOwnProperty(ToObject(this), ToString(name), desc, false); |
| 275 } | 283 } |
| 276 | 284 |
| 277 | 285 |
| 278 function ObjectLookupSetter(name) { | 286 function ObjectLookupSetter(name) { |
| 279 if (this == null && !IS_UNDETECTABLE(this)) { | 287 if (this == null && !IS_UNDETECTABLE(this)) { |
| 280 throw new $TypeError('Object.prototype.__lookupSetter__: this is Null'); | 288 throw new $TypeError('Object.prototype.__lookupSetter__: this is Null'); |
| 281 } | 289 } |
| 282 return %LookupAccessor(ToObject(this), ToString(name), SETTER); | 290 return %LookupAccessor(ToObject(this), ToString(name), SETTER); |
| 283 } | 291 } |
| 284 | 292 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 this.enumerable_ = false; | 395 this.enumerable_ = false; |
| 388 this.hasEnumerable_ = false; | 396 this.hasEnumerable_ = false; |
| 389 this.configurable_ = false; | 397 this.configurable_ = false; |
| 390 this.hasConfigurable_ = false; | 398 this.hasConfigurable_ = false; |
| 391 this.get_ = void 0; | 399 this.get_ = void 0; |
| 392 this.hasGetter_ = false; | 400 this.hasGetter_ = false; |
| 393 this.set_ = void 0; | 401 this.set_ = void 0; |
| 394 this.hasSetter_ = false; | 402 this.hasSetter_ = false; |
| 395 } | 403 } |
| 396 | 404 |
| 405 PropertyDescriptor.prototype.__proto__ = null; |
| 406 PropertyDescriptor.prototype.toString = function() { |
| 407 return "[object PropertyDescriptor]"; |
| 408 }; |
| 397 | 409 |
| 398 PropertyDescriptor.prototype.setValue = function(value) { | 410 PropertyDescriptor.prototype.setValue = function(value) { |
| 399 this.value_ = value; | 411 this.value_ = value; |
| 400 this.hasValue_ = true; | 412 this.hasValue_ = true; |
| 401 } | 413 } |
| 402 | 414 |
| 403 | 415 |
| 404 PropertyDescriptor.prototype.getValue = function() { | 416 PropertyDescriptor.prototype.getValue = function() { |
| 405 return this.value_; | 417 return this.value_; |
| 406 } | 418 } |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 | 500 |
| 489 PropertyDescriptor.prototype.hasSetter = function() { | 501 PropertyDescriptor.prototype.hasSetter = function() { |
| 490 return this.hasSetter_; | 502 return this.hasSetter_; |
| 491 } | 503 } |
| 492 | 504 |
| 493 | 505 |
| 494 // Converts an array returned from Runtime_GetOwnProperty to an actual | 506 // Converts an array returned from Runtime_GetOwnProperty to an actual |
| 495 // property descriptor. For a description of the array layout please | 507 // property descriptor. For a description of the array layout please |
| 496 // see the runtime.cc file. | 508 // see the runtime.cc file. |
| 497 function ConvertDescriptorArrayToDescriptor(desc_array) { | 509 function ConvertDescriptorArrayToDescriptor(desc_array) { |
| 498 if (desc_array == false) { | 510 if (desc_array === false) { |
| 499 throw 'Internal error: invalid desc_array'; | 511 throw 'Internal error: invalid desc_array'; |
| 500 } | 512 } |
| 501 | 513 |
| 502 if (IS_UNDEFINED(desc_array)) { | 514 if (IS_UNDEFINED(desc_array)) { |
| 503 return void 0; | 515 return void 0; |
| 504 } | 516 } |
| 505 | 517 |
| 506 var desc = new PropertyDescriptor(); | 518 var desc = new PropertyDescriptor(); |
| 507 // This is an accessor. | 519 // This is an accessor. |
| 508 if (desc_array[IS_ACCESSOR_INDEX]) { | 520 if (desc_array[IS_ACCESSOR_INDEX]) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 537 | 549 |
| 538 | 550 |
| 539 // ES5 section 8.12.1. | 551 // ES5 section 8.12.1. |
| 540 function GetOwnProperty(obj, p) { | 552 function GetOwnProperty(obj, p) { |
| 541 // GetOwnProperty returns an array indexed by the constants | 553 // GetOwnProperty returns an array indexed by the constants |
| 542 // defined in macros.py. | 554 // defined in macros.py. |
| 543 // If p is not a property on obj undefined is returned. | 555 // If p is not a property on obj undefined is returned. |
| 544 var props = %GetOwnProperty(ToObject(obj), ToString(p)); | 556 var props = %GetOwnProperty(ToObject(obj), ToString(p)); |
| 545 | 557 |
| 546 // A false value here means that access checks failed. | 558 // A false value here means that access checks failed. |
| 547 if (props == false) return void 0; | 559 if (props === false) return void 0; |
| 548 | 560 |
| 549 return ConvertDescriptorArrayToDescriptor(props); | 561 return ConvertDescriptorArrayToDescriptor(props); |
| 550 } | 562 } |
| 551 | 563 |
| 552 | 564 |
| 553 // ES5 8.12.9. | 565 // ES5 8.12.9. |
| 554 function DefineOwnProperty(obj, p, desc, should_throw) { | 566 function DefineOwnProperty(obj, p, desc, should_throw) { |
| 555 var current_or_access = %GetOwnProperty(ToObject(obj), ToString(p)); | 567 var current_or_access = %GetOwnProperty(ToObject(obj), ToString(p)); |
| 556 // A false value here means that access checks failed. | 568 // A false value here means that access checks failed. |
| 557 if (current_or_access == false) return void 0; | 569 if (current_or_access === false) return void 0; |
| 558 | 570 |
| 559 var current = ConvertDescriptorArrayToDescriptor(current_or_access); | 571 var current = ConvertDescriptorArrayToDescriptor(current_or_access); |
| 560 var extensible = %IsExtensible(ToObject(obj)); | 572 var extensible = %IsExtensible(ToObject(obj)); |
| 561 | 573 |
| 562 // Error handling according to spec. | 574 // Error handling according to spec. |
| 563 // Step 3 | 575 // Step 3 |
| 564 if (IS_UNDEFINED(current) && !extensible) | 576 if (IS_UNDEFINED(current) && !extensible) { |
| 565 throw MakeTypeError("define_disallowed", ["defineProperty"]); | 577 if (should_throw) { |
| 578 throw MakeTypeError("define_disallowed", ["defineProperty"]); |
| 579 } else { |
| 580 return; |
| 581 } |
| 582 } |
| 566 | 583 |
| 567 if (!IS_UNDEFINED(current)) { | 584 if (!IS_UNDEFINED(current)) { |
| 568 // Step 5 and 6 | 585 // Step 5 and 6 |
| 569 if ((IsGenericDescriptor(desc) || | 586 if ((IsGenericDescriptor(desc) || |
| 570 IsDataDescriptor(desc) == IsDataDescriptor(current)) && | 587 IsDataDescriptor(desc) == IsDataDescriptor(current)) && |
| 571 (!desc.hasEnumerable() || | 588 (!desc.hasEnumerable() || |
| 572 SameValue(desc.isEnumerable(), current.isEnumerable())) && | 589 SameValue(desc.isEnumerable(), current.isEnumerable())) && |
| 573 (!desc.hasConfigurable() || | 590 (!desc.hasConfigurable() || |
| 574 SameValue(desc.isConfigurable(), current.isConfigurable())) && | 591 SameValue(desc.isConfigurable(), current.isConfigurable())) && |
| 575 (!desc.hasWritable() || | 592 (!desc.hasWritable() || |
| 576 SameValue(desc.isWritable(), current.isWritable())) && | 593 SameValue(desc.isWritable(), current.isWritable())) && |
| 577 (!desc.hasValue() || | 594 (!desc.hasValue() || |
| 578 SameValue(desc.getValue(), current.getValue())) && | 595 SameValue(desc.getValue(), current.getValue())) && |
| 579 (!desc.hasGetter() || | 596 (!desc.hasGetter() || |
| 580 SameValue(desc.getGet(), current.getGet())) && | 597 SameValue(desc.getGet(), current.getGet())) && |
| 581 (!desc.hasSetter() || | 598 (!desc.hasSetter() || |
| 582 SameValue(desc.getSet(), current.getSet()))) { | 599 SameValue(desc.getSet(), current.getSet()))) { |
| 583 return true; | 600 return true; |
| 584 } | 601 } |
| 585 if (!current.isConfigurable()) { | 602 if (!current.isConfigurable()) { |
| 586 // Step 7 | 603 // Step 7 |
| 587 if (desc.isConfigurable() || | 604 if (desc.isConfigurable() || |
| 588 (desc.hasEnumerable() && | 605 (desc.hasEnumerable() && |
| 589 desc.isEnumerable() != current.isEnumerable())) { | 606 desc.isEnumerable() != current.isEnumerable())) { |
| 590 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); | 607 if (should_throw) { |
| 608 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| 609 } else { |
| 610 return; |
| 611 } |
| 591 } | 612 } |
| 592 // Step 8 | 613 // Step 8 |
| 593 if (!IsGenericDescriptor(desc)) { | 614 if (!IsGenericDescriptor(desc)) { |
| 594 // Step 9a | 615 // Step 9a |
| 595 if (IsDataDescriptor(current) != IsDataDescriptor(desc)) { | 616 if (IsDataDescriptor(current) != IsDataDescriptor(desc)) { |
| 596 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); | 617 if (should_throw) { |
| 618 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| 619 } else { |
| 620 return; |
| 621 } |
| 597 } | 622 } |
| 598 // Step 10a | 623 // Step 10a |
| 599 if (IsDataDescriptor(current) && IsDataDescriptor(desc)) { | 624 if (IsDataDescriptor(current) && IsDataDescriptor(desc)) { |
| 600 if (!current.isWritable() && desc.isWritable()) { | 625 if (!current.isWritable() && desc.isWritable()) { |
| 601 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); | 626 if (should_throw) { |
| 627 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| 628 } else { |
| 629 return; |
| 630 } |
| 602 } | 631 } |
| 603 if (!current.isWritable() && desc.hasValue() && | 632 if (!current.isWritable() && desc.hasValue() && |
| 604 !SameValue(desc.getValue(), current.getValue())) { | 633 !SameValue(desc.getValue(), current.getValue())) { |
| 605 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); | 634 if (should_throw) { |
| 635 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| 636 } else { |
| 637 return; |
| 638 } |
| 606 } | 639 } |
| 607 } | 640 } |
| 608 // Step 11 | 641 // Step 11 |
| 609 if (IsAccessorDescriptor(desc) && IsAccessorDescriptor(current)) { | 642 if (IsAccessorDescriptor(desc) && IsAccessorDescriptor(current)) { |
| 610 if (desc.hasSetter() && !SameValue(desc.getSet(), current.getSet())) { | 643 if (desc.hasSetter() && !SameValue(desc.getSet(), current.getSet())) { |
| 611 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); | 644 if (should_throw) { |
| 645 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| 646 } else { |
| 647 return; |
| 648 } |
| 612 } | 649 } |
| 613 if (desc.hasGetter() && !SameValue(desc.getGet(),current.getGet())) { | 650 if (desc.hasGetter() && !SameValue(desc.getGet(),current.getGet())) { |
| 614 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); | 651 if (should_throw) { |
| 652 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| 653 } else { |
| 654 return; |
| 655 } |
| 615 } | 656 } |
| 616 } | 657 } |
| 617 } | 658 } |
| 618 } | 659 } |
| 619 } | 660 } |
| 620 | 661 |
| 621 // Send flags - enumerable and configurable are common - writable is | 662 // Send flags - enumerable and configurable are common - writable is |
| 622 // only send to the data descriptor. | 663 // only send to the data descriptor. |
| 623 // Take special care if enumerable and configurable is not defined on | 664 // Take special care if enumerable and configurable is not defined on |
| 624 // desc (we need to preserve the existing values from current). | 665 // desc (we need to preserve the existing values from current). |
| (...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1163 if (%_IsConstructCall()) { | 1204 if (%_IsConstructCall()) { |
| 1164 // %NewObjectFromBound implicitly uses arguments passed to this | 1205 // %NewObjectFromBound implicitly uses arguments passed to this |
| 1165 // function. We do not pass the arguments object explicitly to avoid | 1206 // function. We do not pass the arguments object explicitly to avoid |
| 1166 // materializing it and guarantee that this function will be optimized. | 1207 // materializing it and guarantee that this function will be optimized. |
| 1167 return %NewObjectFromBound(fn, null); | 1208 return %NewObjectFromBound(fn, null); |
| 1168 } | 1209 } |
| 1169 | 1210 |
| 1170 return fn.apply(this_arg, arguments); | 1211 return fn.apply(this_arg, arguments); |
| 1171 }; | 1212 }; |
| 1172 } else { | 1213 } else { |
| 1173 var bound_args = new $Array(argc_bound); | 1214 var bound_args = new InternalArray(argc_bound); |
| 1174 for(var i = 0; i < argc_bound; i++) { | 1215 for(var i = 0; i < argc_bound; i++) { |
| 1175 bound_args[i] = %_Arguments(i+1); | 1216 bound_args[i] = %_Arguments(i+1); |
| 1176 } | 1217 } |
| 1177 | 1218 |
| 1178 var result = function() { | 1219 var result = function() { |
| 1179 // If this is a construct call we use a special runtime method | 1220 // If this is a construct call we use a special runtime method |
| 1180 // to generate the actual object using the bound function. | 1221 // to generate the actual object using the bound function. |
| 1181 if (%_IsConstructCall()) { | 1222 if (%_IsConstructCall()) { |
| 1182 // %NewObjectFromBound implicitly uses arguments passed to this | 1223 // %NewObjectFromBound implicitly uses arguments passed to this |
| 1183 // function. We do not pass the arguments object explicitly to avoid | 1224 // function. We do not pass the arguments object explicitly to avoid |
| 1184 // materializing it and guarantee that this function will be optimized. | 1225 // materializing it and guarantee that this function will be optimized. |
| 1185 return %NewObjectFromBound(fn, bound_args); | 1226 return %NewObjectFromBound(fn, bound_args); |
| 1186 } | 1227 } |
| 1187 | 1228 |
| 1188 // Combine the args we got from the bind call with the args | 1229 // Combine the args we got from the bind call with the args |
| 1189 // given as argument to the invocation. | 1230 // given as argument to the invocation. |
| 1190 var argc = %_ArgumentsLength(); | 1231 var argc = %_ArgumentsLength(); |
| 1191 var args = new $Array(argc + argc_bound); | 1232 var args = new InternalArray(argc + argc_bound); |
| 1192 // Add bound arguments. | 1233 // Add bound arguments. |
| 1193 for (var i = 0; i < argc_bound; i++) { | 1234 for (var i = 0; i < argc_bound; i++) { |
| 1194 args[i] = bound_args[i]; | 1235 args[i] = bound_args[i]; |
| 1195 } | 1236 } |
| 1196 // Add arguments from call. | 1237 // Add arguments from call. |
| 1197 for (var i = 0; i < argc; i++) { | 1238 for (var i = 0; i < argc; i++) { |
| 1198 args[argc_bound + i] = %_Arguments(i); | 1239 args[argc_bound + i] = %_Arguments(i); |
| 1199 } | 1240 } |
| 1200 return fn.apply(this_arg, args); | 1241 return fn.apply(this_arg, args); |
| 1201 }; | 1242 }; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1213 %FunctionSetLength(result, length); | 1254 %FunctionSetLength(result, length); |
| 1214 | 1255 |
| 1215 return result; | 1256 return result; |
| 1216 } | 1257 } |
| 1217 | 1258 |
| 1218 | 1259 |
| 1219 function NewFunction(arg1) { // length == 1 | 1260 function NewFunction(arg1) { // length == 1 |
| 1220 var n = %_ArgumentsLength(); | 1261 var n = %_ArgumentsLength(); |
| 1221 var p = ''; | 1262 var p = ''; |
| 1222 if (n > 1) { | 1263 if (n > 1) { |
| 1223 p = new $Array(n - 1); | 1264 p = new InternalArray(n - 1); |
| 1224 for (var i = 0; i < n - 1; i++) p[i] = %_Arguments(i); | 1265 for (var i = 0; i < n - 1; i++) p[i] = %_Arguments(i); |
| 1225 p = Join(p, n - 1, ',', NonStringToString); | 1266 p = Join(p, n - 1, ',', NonStringToString); |
| 1226 // If the formal parameters string include ) - an illegal | 1267 // If the formal parameters string include ) - an illegal |
| 1227 // character - it may make the combined function expression | 1268 // character - it may make the combined function expression |
| 1228 // compile. We avoid this problem by checking for this early on. | 1269 // compile. We avoid this problem by checking for this early on. |
| 1229 if (p.indexOf(')') != -1) throw MakeSyntaxError('unable_to_parse',[]); | 1270 if (p.indexOf(')') != -1) throw MakeSyntaxError('unable_to_parse',[]); |
| 1230 } | 1271 } |
| 1231 var body = (n > 0) ? ToString(%_Arguments(n - 1)) : ''; | 1272 var body = (n > 0) ? ToString(%_Arguments(n - 1)) : ''; |
| 1232 var source = '(function(' + p + ') {\n' + body + '\n})'; | 1273 var source = '(function(' + p + ') {\n' + body + '\n})'; |
| 1233 | 1274 |
| 1234 // The call to SetNewFunctionAttributes will ensure the prototype | 1275 // The call to SetNewFunctionAttributes will ensure the prototype |
| 1235 // property of the resulting function is enumerable (ECMA262, 15.3.5.2). | 1276 // property of the resulting function is enumerable (ECMA262, 15.3.5.2). |
| 1236 var f = %CompileString(source)(); | 1277 var f = %CompileString(source)(); |
| 1237 %FunctionSetName(f, "anonymous"); | 1278 %FunctionSetName(f, "anonymous"); |
| 1238 return %SetNewFunctionAttributes(f); | 1279 return %SetNewFunctionAttributes(f); |
| 1239 } | 1280 } |
| 1240 | 1281 |
| 1241 %SetCode($Function, NewFunction); | 1282 %SetCode($Function, NewFunction); |
| 1242 | 1283 |
| 1243 // ---------------------------------------------------------------------------- | 1284 // ---------------------------------------------------------------------------- |
| 1244 | 1285 |
| 1245 function SetupFunction() { | 1286 function SetupFunction() { |
| 1246 InstallFunctions($Function.prototype, DONT_ENUM, $Array( | 1287 InstallFunctions($Function.prototype, DONT_ENUM, $Array( |
| 1247 "bind", FunctionBind, | 1288 "bind", FunctionBind, |
| 1248 "toString", FunctionToString | 1289 "toString", FunctionToString |
| 1249 )); | 1290 )); |
| 1250 } | 1291 } |
| 1251 | 1292 |
| 1252 SetupFunction(); | 1293 SetupFunction(); |
| OLD | NEW |