| 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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 function InstallFunctions(object, attributes, functions) { | 49 function InstallFunctions(object, attributes, functions) { |
| 50 if (functions.length >= 8) { | 50 if (functions.length >= 8) { |
| 51 %OptimizeObjectForAddingMultipleProperties(object, functions.length >> 1); | 51 %OptimizeObjectForAddingMultipleProperties(object, functions.length >> 1); |
| 52 } | 52 } |
| 53 for (var i = 0; i < functions.length; i += 2) { | 53 for (var i = 0; i < functions.length; i += 2) { |
| 54 var key = functions[i]; | 54 var key = functions[i]; |
| 55 var f = functions[i + 1]; | 55 var f = functions[i + 1]; |
| 56 %FunctionSetName(f, key); | 56 %FunctionSetName(f, key); |
| 57 %FunctionRemovePrototype(f); | 57 %FunctionRemovePrototype(f); |
| 58 %SetProperty(object, key, f, attributes); | 58 %SetProperty(object, key, f, attributes); |
| 59 %SetES5Flag(f); | 59 %SetNativeFlag(f); |
| 60 } | 60 } |
| 61 %ToFastProperties(object); | 61 %ToFastProperties(object); |
| 62 } | 62 } |
| 63 | 63 |
| 64 // Emulates JSC by installing functions on a hidden prototype that | 64 // Emulates JSC by installing functions on a hidden prototype that |
| 65 // lies above the current object/prototype. This lets you override | 65 // lies above the current object/prototype. This lets you override |
| 66 // functions on String.prototype etc. and then restore the old function | 66 // functions on String.prototype etc. and then restore the old function |
| 67 // with delete. See http://code.google.com/p/chromium/issues/detail?id=1717 | 67 // with delete. See http://code.google.com/p/chromium/issues/detail?id=1717 |
| 68 function InstallFunctionsOnHiddenPrototype(object, attributes, functions) { | 68 function InstallFunctionsOnHiddenPrototype(object, attributes, functions) { |
| 69 var hidden_prototype = new $Object(); | 69 var hidden_prototype = new $Object(); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 99 // vs 800ns). The following optimization makes parseInt on a | 99 // vs 800ns). The following optimization makes parseInt on a |
| 100 // non-Smi number 9 times faster (230ns vs 2070ns). Together | 100 // non-Smi number 9 times faster (230ns vs 2070ns). Together |
| 101 // they make parseInt on a string 1.4% slower (274ns vs 270ns). | 101 // they make parseInt on a string 1.4% slower (274ns vs 270ns). |
| 102 if (%_IsSmi(string)) return string; | 102 if (%_IsSmi(string)) return string; |
| 103 if (IS_NUMBER(string) && | 103 if (IS_NUMBER(string) && |
| 104 ((0.01 < string && string < 1e9) || | 104 ((0.01 < string && string < 1e9) || |
| 105 (-1e9 < string && string < -0.01))) { | 105 (-1e9 < string && string < -0.01))) { |
| 106 // Truncate number. | 106 // Truncate number. |
| 107 return string | 0; | 107 return string | 0; |
| 108 } | 108 } |
| 109 if (IS_UNDEFINED(radix)) radix = 0; | 109 radix = radix | 0; |
| 110 } else { | 110 } else { |
| 111 radix = TO_INT32(radix); | 111 radix = TO_INT32(radix); |
| 112 if (!(radix == 0 || (2 <= radix && radix <= 36))) | 112 if (!(radix == 0 || (2 <= radix && radix <= 36))) |
| 113 return $NaN; | 113 return $NaN; |
| 114 } | 114 } |
| 115 string = TO_STRING_INLINE(string); | 115 string = TO_STRING_INLINE(string); |
| 116 if (%_HasCachedArrayIndex(string) && | 116 if (%_HasCachedArrayIndex(string) && |
| 117 (radix == 0 || radix == 10)) { | 117 (radix == 0 || radix == 10)) { |
| 118 return %_GetCachedArrayIndex(string); | 118 return %_GetCachedArrayIndex(string); |
| 119 } | 119 } |
| 120 return %StringParseInt(string, radix); | 120 return %StringParseInt(string, radix); |
| 121 } | 121 } |
| 122 | 122 |
| 123 | 123 |
| 124 // ECMA-262 - 15.1.2.3 | 124 // ECMA-262 - 15.1.2.3 |
| 125 function GlobalParseFloat(string) { | 125 function GlobalParseFloat(string) { |
| 126 string = TO_STRING_INLINE(string); | 126 string = TO_STRING_INLINE(string); |
| 127 if (%_HasCachedArrayIndex(string)) return %_GetCachedArrayIndex(string); | 127 if (%_HasCachedArrayIndex(string)) return %_GetCachedArrayIndex(string); |
| 128 return %StringParseFloat(string); | 128 return %StringParseFloat(string); |
| 129 } | 129 } |
| 130 | 130 |
| 131 | 131 |
| 132 function GlobalEval(x) { | 132 function GlobalEval(x) { |
| 133 if (!IS_STRING(x)) return x; | 133 if (!IS_STRING(x)) return x; |
| 134 | 134 |
| 135 var receiver = this; |
| 135 var global_receiver = %GlobalReceiver(global); | 136 var global_receiver = %GlobalReceiver(global); |
| 136 var this_is_global_receiver = (this === global_receiver); | 137 |
| 138 if (receiver == null && !IS_UNDETECTABLE(receiver)) { |
| 139 receiver = global_receiver; |
| 140 } |
| 141 |
| 142 var this_is_global_receiver = (receiver === global_receiver); |
| 137 var global_is_detached = (global === global_receiver); | 143 var global_is_detached = (global === global_receiver); |
| 138 | 144 |
| 145 // For consistency with JSC we require the global object passed to |
| 146 // eval to be the global object from which 'eval' originated. This |
| 147 // is not mandated by the spec. |
| 139 if (!this_is_global_receiver || global_is_detached) { | 148 if (!this_is_global_receiver || global_is_detached) { |
| 140 throw new $EvalError('The "this" object passed to eval must ' + | 149 throw new $EvalError('The "this" object passed to eval must ' + |
| 141 'be the global object from which eval originated'); | 150 'be the global object from which eval originated'); |
| 142 } | 151 } |
| 143 | 152 |
| 144 var f = %CompileString(x); | 153 var f = %CompileString(x); |
| 145 if (!IS_FUNCTION(f)) return f; | 154 if (!IS_FUNCTION(f)) return f; |
| 146 | 155 |
| 147 return %_CallFunction(this, f); | 156 return %_CallFunction(receiver, f); |
| 148 } | 157 } |
| 149 | 158 |
| 150 | 159 |
| 151 // ---------------------------------------------------------------------------- | 160 // ---------------------------------------------------------------------------- |
| 152 | 161 |
| 153 | 162 |
| 154 function SetupGlobal() { | 163 function SetupGlobal() { |
| 155 // ECMA 262 - 15.1.1.1. | 164 // ECMA 262 - 15.1.1.1. |
| 156 %SetProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE); | 165 %SetProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE); |
| 157 | 166 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 | 248 |
| 240 | 249 |
| 241 // ECMA-262 - 15.2.4.6 | 250 // ECMA-262 - 15.2.4.6 |
| 242 function ObjectPropertyIsEnumerable(V) { | 251 function ObjectPropertyIsEnumerable(V) { |
| 243 return %IsPropertyEnumerable(ToObject(this), ToString(V)); | 252 return %IsPropertyEnumerable(ToObject(this), ToString(V)); |
| 244 } | 253 } |
| 245 | 254 |
| 246 | 255 |
| 247 // Extensions for providing property getters and setters. | 256 // Extensions for providing property getters and setters. |
| 248 function ObjectDefineGetter(name, fun) { | 257 function ObjectDefineGetter(name, fun) { |
| 249 if (this == null && !IS_UNDETECTABLE(this)) { | 258 var receiver = this; |
| 250 throw new $TypeError('Object.prototype.__defineGetter__: this is Null'); | 259 if (receiver == null && !IS_UNDETECTABLE(receiver)) { |
| 260 receiver = %GlobalReceiver(global); |
| 251 } | 261 } |
| 252 if (!IS_FUNCTION(fun)) { | 262 if (!IS_FUNCTION(fun)) { |
| 253 throw new $TypeError('Object.prototype.__defineGetter__: Expecting function'
); | 263 throw new $TypeError('Object.prototype.__defineGetter__: Expecting function'
); |
| 254 } | 264 } |
| 255 var desc = new PropertyDescriptor(); | 265 var desc = new PropertyDescriptor(); |
| 256 desc.setGet(fun); | 266 desc.setGet(fun); |
| 257 desc.setEnumerable(true); | 267 desc.setEnumerable(true); |
| 258 desc.setConfigurable(true); | 268 desc.setConfigurable(true); |
| 259 DefineOwnProperty(ToObject(this), ToString(name), desc, false); | 269 DefineOwnProperty(ToObject(receiver), ToString(name), desc, false); |
| 260 } | 270 } |
| 261 | 271 |
| 262 | 272 |
| 263 function ObjectLookupGetter(name) { | 273 function ObjectLookupGetter(name) { |
| 264 if (this == null && !IS_UNDETECTABLE(this)) { | 274 var receiver = this; |
| 265 throw new $TypeError('Object.prototype.__lookupGetter__: this is Null'); | 275 if (receiver == null && !IS_UNDETECTABLE(receiver)) { |
| 276 receiver = %GlobalReceiver(global); |
| 266 } | 277 } |
| 267 return %LookupAccessor(ToObject(this), ToString(name), GETTER); | 278 return %LookupAccessor(ToObject(receiver), ToString(name), GETTER); |
| 268 } | 279 } |
| 269 | 280 |
| 270 | 281 |
| 271 function ObjectDefineSetter(name, fun) { | 282 function ObjectDefineSetter(name, fun) { |
| 272 if (this == null && !IS_UNDETECTABLE(this)) { | 283 var receiver = this; |
| 273 throw new $TypeError('Object.prototype.__defineSetter__: this is Null'); | 284 if (receiver == null && !IS_UNDETECTABLE(receiver)) { |
| 285 receiver = %GlobalReceiver(global); |
| 274 } | 286 } |
| 275 if (!IS_FUNCTION(fun)) { | 287 if (!IS_FUNCTION(fun)) { |
| 276 throw new $TypeError( | 288 throw new $TypeError( |
| 277 'Object.prototype.__defineSetter__: Expecting function'); | 289 'Object.prototype.__defineSetter__: Expecting function'); |
| 278 } | 290 } |
| 279 var desc = new PropertyDescriptor(); | 291 var desc = new PropertyDescriptor(); |
| 280 desc.setSet(fun); | 292 desc.setSet(fun); |
| 281 desc.setEnumerable(true); | 293 desc.setEnumerable(true); |
| 282 desc.setConfigurable(true); | 294 desc.setConfigurable(true); |
| 283 DefineOwnProperty(ToObject(this), ToString(name), desc, false); | 295 DefineOwnProperty(ToObject(receiver), ToString(name), desc, false); |
| 284 } | 296 } |
| 285 | 297 |
| 286 | 298 |
| 287 function ObjectLookupSetter(name) { | 299 function ObjectLookupSetter(name) { |
| 288 if (this == null && !IS_UNDETECTABLE(this)) { | 300 var receiver = this; |
| 289 throw new $TypeError('Object.prototype.__lookupSetter__: this is Null'); | 301 if (receiver == null && !IS_UNDETECTABLE(receiver)) { |
| 302 receiver = %GlobalReceiver(global); |
| 290 } | 303 } |
| 291 return %LookupAccessor(ToObject(this), ToString(name), SETTER); | 304 return %LookupAccessor(ToObject(receiver), ToString(name), SETTER); |
| 292 } | 305 } |
| 293 | 306 |
| 294 | 307 |
| 295 function ObjectKeys(obj) { | 308 function ObjectKeys(obj) { |
| 296 if (!IS_SPEC_OBJECT(obj)) | 309 if (!IS_SPEC_OBJECT(obj)) |
| 297 throw MakeTypeError("obj_ctor_property_non_object", ["keys"]); | 310 throw MakeTypeError("obj_ctor_property_non_object", ["keys"]); |
| 298 return %LocalKeys(obj); | 311 return %LocalKeys(obj); |
| 299 } | 312 } |
| 300 | 313 |
| 301 | 314 |
| 302 // ES5 8.10.1. | 315 // ES5 8.10.1. |
| 303 function IsAccessorDescriptor(desc) { | 316 function IsAccessorDescriptor(desc) { |
| 304 if (IS_UNDEFINED(desc)) return false; | 317 if (IS_UNDEFINED(desc)) return false; |
| 305 return desc.hasGetter_ || desc.hasSetter_; | 318 return desc.hasGetter() || desc.hasSetter(); |
| 306 } | 319 } |
| 307 | 320 |
| 308 | 321 |
| 309 // ES5 8.10.2. | 322 // ES5 8.10.2. |
| 310 function IsDataDescriptor(desc) { | 323 function IsDataDescriptor(desc) { |
| 311 if (IS_UNDEFINED(desc)) return false; | 324 if (IS_UNDEFINED(desc)) return false; |
| 312 return desc.hasValue_ || desc.hasWritable_; | 325 return desc.hasValue() || desc.hasWritable(); |
| 313 } | 326 } |
| 314 | 327 |
| 315 | 328 |
| 316 // ES5 8.10.3. | 329 // ES5 8.10.3. |
| 317 function IsGenericDescriptor(desc) { | 330 function IsGenericDescriptor(desc) { |
| 318 return !(IsAccessorDescriptor(desc) || IsDataDescriptor(desc)); | 331 return !(IsAccessorDescriptor(desc) || IsDataDescriptor(desc)); |
| 319 } | 332 } |
| 320 | 333 |
| 321 | 334 |
| 322 function IsInconsistentDescriptor(desc) { | 335 function IsInconsistentDescriptor(desc) { |
| 323 return IsAccessorDescriptor(desc) && IsDataDescriptor(desc); | 336 return IsAccessorDescriptor(desc) && IsDataDescriptor(desc); |
| 324 } | 337 } |
| 325 | 338 |
| 339 |
| 326 // ES5 8.10.4 | 340 // ES5 8.10.4 |
| 327 function FromPropertyDescriptor(desc) { | 341 function FromPropertyDescriptor(desc) { |
| 328 if (IS_UNDEFINED(desc)) return desc; | 342 if (IS_UNDEFINED(desc)) return desc; |
| 329 var obj = new $Object(); | 343 var obj = new $Object(); |
| 330 if (IsDataDescriptor(desc)) { | 344 if (IsDataDescriptor(desc)) { |
| 331 obj.value = desc.getValue(); | 345 obj.value = desc.getValue(); |
| 332 obj.writable = desc.isWritable(); | 346 obj.writable = desc.isWritable(); |
| 333 } | 347 } |
| 334 if (IsAccessorDescriptor(desc)) { | 348 if (IsAccessorDescriptor(desc)) { |
| 335 obj.get = desc.getGet(); | 349 obj.get = desc.getGet(); |
| 336 obj.set = desc.getSet(); | 350 obj.set = desc.getSet(); |
| 337 } | 351 } |
| 338 obj.enumerable = desc.isEnumerable(); | 352 obj.enumerable = desc.isEnumerable(); |
| 339 obj.configurable = desc.isConfigurable(); | 353 obj.configurable = desc.isConfigurable(); |
| 340 return obj; | 354 return obj; |
| 341 } | 355 } |
| 342 | 356 |
| 357 // Harmony Proxies |
| 358 function FromGenericPropertyDescriptor(desc) { |
| 359 if (IS_UNDEFINED(desc)) return desc; |
| 360 var obj = new $Object(); |
| 361 if (desc.hasValue()) obj.value = desc.getValue(); |
| 362 if (desc.hasWritable()) obj.writable = desc.isWritable(); |
| 363 if (desc.hasGetter()) obj.get = desc.getGet(); |
| 364 if (desc.hasSetter()) obj.set = desc.getSet(); |
| 365 if (desc.hasEnumerable()) obj.enumerable = desc.isEnumerable(); |
| 366 if (desc.hasConfigurable()) obj.configurable = desc.isConfigurable(); |
| 367 return obj; |
| 368 } |
| 369 |
| 343 // ES5 8.10.5. | 370 // ES5 8.10.5. |
| 344 function ToPropertyDescriptor(obj) { | 371 function ToPropertyDescriptor(obj) { |
| 345 if (!IS_SPEC_OBJECT(obj)) { | 372 if (!IS_SPEC_OBJECT(obj)) { |
| 346 throw MakeTypeError("property_desc_object", [obj]); | 373 throw MakeTypeError("property_desc_object", [obj]); |
| 347 } | 374 } |
| 348 var desc = new PropertyDescriptor(); | 375 var desc = new PropertyDescriptor(); |
| 349 | 376 |
| 350 if ("enumerable" in obj) { | 377 if ("enumerable" in obj) { |
| 351 desc.setEnumerable(ToBoolean(obj.enumerable)); | 378 desc.setEnumerable(ToBoolean(obj.enumerable)); |
| 352 } | 379 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 379 desc.setSet(set); | 406 desc.setSet(set); |
| 380 } | 407 } |
| 381 | 408 |
| 382 if (IsInconsistentDescriptor(desc)) { | 409 if (IsInconsistentDescriptor(desc)) { |
| 383 throw MakeTypeError("value_and_accessor", [obj]); | 410 throw MakeTypeError("value_and_accessor", [obj]); |
| 384 } | 411 } |
| 385 return desc; | 412 return desc; |
| 386 } | 413 } |
| 387 | 414 |
| 388 | 415 |
| 416 // For Harmony proxies. |
| 417 function ToCompletePropertyDescriptor(obj) { |
| 418 var desc = ToPropertyDescriptor(obj) |
| 419 if (IsGenericDescriptor(desc) || IsDataDescriptor(desc)) { |
| 420 if (!desc.hasValue()) desc.setValue(void 0); |
| 421 if (!desc.hasWritable()) desc.setWritable(false); |
| 422 } else { |
| 423 // Is accessor descriptor. |
| 424 if (!desc.hasGetter()) desc.setGet(void 0); |
| 425 if (!desc.hasSetter()) desc.setSet(void 0); |
| 426 } |
| 427 if (!desc.hasEnumerable()) desc.setEnumerable(false); |
| 428 if (!desc.hasConfigurable()) desc.setConfigurable(false); |
| 429 return desc; |
| 430 } |
| 431 |
| 432 |
| 389 function PropertyDescriptor() { | 433 function PropertyDescriptor() { |
| 390 // Initialize here so they are all in-object and have the same map. | 434 // Initialize here so they are all in-object and have the same map. |
| 391 // Default values from ES5 8.6.1. | 435 // Default values from ES5 8.6.1. |
| 392 this.value_ = void 0; | 436 this.value_ = void 0; |
| 393 this.hasValue_ = false; | 437 this.hasValue_ = false; |
| 394 this.writable_ = false; | 438 this.writable_ = false; |
| 395 this.hasWritable_ = false; | 439 this.hasWritable_ = false; |
| 396 this.enumerable_ = false; | 440 this.enumerable_ = false; |
| 397 this.hasEnumerable_ = false; | 441 this.hasEnumerable_ = false; |
| 398 this.configurable_ = false; | 442 this.configurable_ = false; |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 527 } | 571 } |
| 528 desc.setEnumerable(desc_array[ENUMERABLE_INDEX]); | 572 desc.setEnumerable(desc_array[ENUMERABLE_INDEX]); |
| 529 desc.setConfigurable(desc_array[CONFIGURABLE_INDEX]); | 573 desc.setConfigurable(desc_array[CONFIGURABLE_INDEX]); |
| 530 | 574 |
| 531 return desc; | 575 return desc; |
| 532 } | 576 } |
| 533 | 577 |
| 534 | 578 |
| 535 // ES5 section 8.12.2. | 579 // ES5 section 8.12.2. |
| 536 function GetProperty(obj, p) { | 580 function GetProperty(obj, p) { |
| 581 if (%IsJSProxy(obj)) { |
| 582 var handler = %GetHandler(obj); |
| 583 var getProperty = handler.getPropertyDescriptor; |
| 584 if (IS_UNDEFINED(getProperty)) { |
| 585 throw MakeTypeError("handler_trap_missing", |
| 586 [handler, "getPropertyDescriptor"]); |
| 587 } |
| 588 var descriptor = getProperty.call(handler, p); |
| 589 if (IS_UNDEFINED(descriptor)) return descriptor; |
| 590 var desc = ToCompletePropertyDescriptor(descriptor); |
| 591 if (!desc.configurable) { |
| 592 throw MakeTypeError("proxy_prop_not_configurable", |
| 593 [handler, "getPropertyDescriptor", p, descriptor]); |
| 594 } |
| 595 return desc; |
| 596 } |
| 537 var prop = GetOwnProperty(obj); | 597 var prop = GetOwnProperty(obj); |
| 538 if (!IS_UNDEFINED(prop)) return prop; | 598 if (!IS_UNDEFINED(prop)) return prop; |
| 539 var proto = obj.__proto__; | 599 var proto = %GetPrototype(obj); |
| 540 if (IS_NULL(proto)) return void 0; | 600 if (IS_NULL(proto)) return void 0; |
| 541 return GetProperty(proto, p); | 601 return GetProperty(proto, p); |
| 542 } | 602 } |
| 543 | 603 |
| 544 | 604 |
| 545 // ES5 section 8.12.6 | 605 // ES5 section 8.12.6 |
| 546 function HasProperty(obj, p) { | 606 function HasProperty(obj, p) { |
| 607 if (%IsJSProxy(obj)) { |
| 608 var handler = %GetHandler(obj); |
| 609 var has = handler.has; |
| 610 if (IS_UNDEFINED(has)) has = DerivedHasTrap; |
| 611 return ToBoolean(has.call(handler, obj, p)); |
| 612 } |
| 547 var desc = GetProperty(obj, p); | 613 var desc = GetProperty(obj, p); |
| 548 return IS_UNDEFINED(desc) ? false : true; | 614 return IS_UNDEFINED(desc) ? false : true; |
| 549 } | 615 } |
| 550 | 616 |
| 551 | 617 |
| 552 // ES5 section 8.12.1. | 618 // ES5 section 8.12.1. |
| 553 function GetOwnProperty(obj, p) { | 619 function GetOwnProperty(obj, p) { |
| 554 // GetOwnProperty returns an array indexed by the constants | 620 // GetOwnProperty returns an array indexed by the constants |
| 555 // defined in macros.py. | 621 // defined in macros.py. |
| 556 // If p is not a property on obj undefined is returned. | 622 // If p is not a property on obj undefined is returned. |
| 557 var props = %GetOwnProperty(ToObject(obj), ToString(p)); | 623 var props = %GetOwnProperty(ToObject(obj), ToString(p)); |
| 558 | 624 |
| 559 // A false value here means that access checks failed. | 625 // A false value here means that access checks failed. |
| 560 if (props === false) return void 0; | 626 if (props === false) return void 0; |
| 561 | 627 |
| 562 return ConvertDescriptorArrayToDescriptor(props); | 628 return ConvertDescriptorArrayToDescriptor(props); |
| 563 } | 629 } |
| 564 | 630 |
| 565 | 631 |
| 632 // Harmony proxies. |
| 633 function DefineProxyProperty(obj, p, attributes, should_throw) { |
| 634 var handler = %GetHandler(obj); |
| 635 var defineProperty = handler.defineProperty; |
| 636 if (IS_UNDEFINED(defineProperty)) { |
| 637 throw MakeTypeError("handler_trap_missing", [handler, "defineProperty"]); |
| 638 } |
| 639 var result = defineProperty.call(handler, p, attributes); |
| 640 if (!ToBoolean(result)) { |
| 641 if (should_throw) { |
| 642 throw MakeTypeError("handler_failed", [handler, "defineProperty"]); |
| 643 } else { |
| 644 return false; |
| 645 } |
| 646 } |
| 647 return true; |
| 648 } |
| 649 |
| 650 |
| 566 // ES5 8.12.9. | 651 // ES5 8.12.9. |
| 567 function DefineOwnProperty(obj, p, desc, should_throw) { | 652 function DefineOwnProperty(obj, p, desc, should_throw) { |
| 653 if (%IsJSProxy(obj)) { |
| 654 var attributes = FromGenericPropertyDescriptor(desc); |
| 655 return DefineProxyProperty(obj, p, attributes, should_throw); |
| 656 } |
| 657 |
| 568 var current_or_access = %GetOwnProperty(ToObject(obj), ToString(p)); | 658 var current_or_access = %GetOwnProperty(ToObject(obj), ToString(p)); |
| 569 // A false value here means that access checks failed. | 659 // A false value here means that access checks failed. |
| 570 if (current_or_access === false) return void 0; | 660 if (current_or_access === false) return void 0; |
| 571 | 661 |
| 572 var current = ConvertDescriptorArrayToDescriptor(current_or_access); | 662 var current = ConvertDescriptorArrayToDescriptor(current_or_access); |
| 573 var extensible = %IsExtensible(ToObject(obj)); | 663 var extensible = %IsExtensible(ToObject(obj)); |
| 574 | 664 |
| 575 // Error handling according to spec. | 665 // Error handling according to spec. |
| 576 // Step 3 | 666 // Step 3 |
| 577 if (IS_UNDEFINED(current) && !extensible) { | 667 if (IS_UNDEFINED(current) && !extensible) { |
| 578 if (should_throw) { | 668 if (should_throw) { |
| 579 throw MakeTypeError("define_disallowed", ["defineProperty"]); | 669 throw MakeTypeError("define_disallowed", [p]); |
| 580 } else { | 670 } else { |
| 581 return; | 671 return; |
| 582 } | 672 } |
| 583 } | 673 } |
| 584 | 674 |
| 585 if (!IS_UNDEFINED(current)) { | 675 if (!IS_UNDEFINED(current)) { |
| 586 // Step 5 and 6 | 676 // Step 5 and 6 |
| 587 if ((IsGenericDescriptor(desc) || | 677 if ((IsGenericDescriptor(desc) || |
| 588 IsDataDescriptor(desc) == IsDataDescriptor(current)) && | 678 IsDataDescriptor(desc) == IsDataDescriptor(current)) && |
| 589 (!desc.hasEnumerable() || | 679 (!desc.hasEnumerable() || |
| 590 SameValue(desc.isEnumerable(), current.isEnumerable())) && | 680 SameValue(desc.isEnumerable(), current.isEnumerable())) && |
| 591 (!desc.hasConfigurable() || | 681 (!desc.hasConfigurable() || |
| 592 SameValue(desc.isConfigurable(), current.isConfigurable())) && | 682 SameValue(desc.isConfigurable(), current.isConfigurable())) && |
| 593 (!desc.hasWritable() || | 683 (!desc.hasWritable() || |
| 594 SameValue(desc.isWritable(), current.isWritable())) && | 684 SameValue(desc.isWritable(), current.isWritable())) && |
| 595 (!desc.hasValue() || | 685 (!desc.hasValue() || |
| 596 SameValue(desc.getValue(), current.getValue())) && | 686 SameValue(desc.getValue(), current.getValue())) && |
| 597 (!desc.hasGetter() || | 687 (!desc.hasGetter() || |
| 598 SameValue(desc.getGet(), current.getGet())) && | 688 SameValue(desc.getGet(), current.getGet())) && |
| 599 (!desc.hasSetter() || | 689 (!desc.hasSetter() || |
| 600 SameValue(desc.getSet(), current.getSet()))) { | 690 SameValue(desc.getSet(), current.getSet()))) { |
| 601 return true; | 691 return true; |
| 602 } | 692 } |
| 603 if (!current.isConfigurable()) { | 693 if (!current.isConfigurable()) { |
| 604 // Step 7 | 694 // Step 7 |
| 605 if (desc.isConfigurable() || | 695 if (desc.isConfigurable() || |
| 606 (desc.hasEnumerable() && | 696 (desc.hasEnumerable() && |
| 607 desc.isEnumerable() != current.isEnumerable())) { | 697 desc.isEnumerable() != current.isEnumerable())) { |
| 608 if (should_throw) { | 698 if (should_throw) { |
| 609 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); | 699 throw MakeTypeError("redefine_disallowed", [p]); |
| 610 } else { | 700 } else { |
| 611 return; | 701 return; |
| 612 } | 702 } |
| 613 } | 703 } |
| 614 // Step 8 | 704 // Step 8 |
| 615 if (!IsGenericDescriptor(desc)) { | 705 if (!IsGenericDescriptor(desc)) { |
| 616 // Step 9a | 706 // Step 9a |
| 617 if (IsDataDescriptor(current) != IsDataDescriptor(desc)) { | 707 if (IsDataDescriptor(current) != IsDataDescriptor(desc)) { |
| 618 if (should_throw) { | 708 if (should_throw) { |
| 619 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); | 709 throw MakeTypeError("redefine_disallowed", [p]); |
| 620 } else { | 710 } else { |
| 621 return; | 711 return; |
| 622 } | 712 } |
| 623 } | 713 } |
| 624 // Step 10a | 714 // Step 10a |
| 625 if (IsDataDescriptor(current) && IsDataDescriptor(desc)) { | 715 if (IsDataDescriptor(current) && IsDataDescriptor(desc)) { |
| 626 if (!current.isWritable() && desc.isWritable()) { | 716 if (!current.isWritable() && desc.isWritable()) { |
| 627 if (should_throw) { | 717 if (should_throw) { |
| 628 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); | 718 throw MakeTypeError("redefine_disallowed", [p]); |
| 629 } else { | 719 } else { |
| 630 return; | 720 return; |
| 631 } | 721 } |
| 632 } | 722 } |
| 633 if (!current.isWritable() && desc.hasValue() && | 723 if (!current.isWritable() && desc.hasValue() && |
| 634 !SameValue(desc.getValue(), current.getValue())) { | 724 !SameValue(desc.getValue(), current.getValue())) { |
| 635 if (should_throw) { | 725 if (should_throw) { |
| 636 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); | 726 throw MakeTypeError("redefine_disallowed", [p]); |
| 637 } else { | 727 } else { |
| 638 return; | 728 return; |
| 639 } | 729 } |
| 640 } | 730 } |
| 641 } | 731 } |
| 642 // Step 11 | 732 // Step 11 |
| 643 if (IsAccessorDescriptor(desc) && IsAccessorDescriptor(current)) { | 733 if (IsAccessorDescriptor(desc) && IsAccessorDescriptor(current)) { |
| 644 if (desc.hasSetter() && !SameValue(desc.getSet(), current.getSet())) { | 734 if (desc.hasSetter() && !SameValue(desc.getSet(), current.getSet())) { |
| 645 if (should_throw) { | 735 if (should_throw) { |
| 646 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); | 736 throw MakeTypeError("redefine_disallowed", [p]); |
| 647 } else { | 737 } else { |
| 648 return; | 738 return; |
| 649 } | 739 } |
| 650 } | 740 } |
| 651 if (desc.hasGetter() && !SameValue(desc.getGet(),current.getGet())) { | 741 if (desc.hasGetter() && !SameValue(desc.getGet(),current.getGet())) { |
| 652 if (should_throw) { | 742 if (should_throw) { |
| 653 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); | 743 throw MakeTypeError("redefine_disallowed", [p]); |
| 654 } else { | 744 } else { |
| 655 return; | 745 return; |
| 656 } | 746 } |
| 657 } | 747 } |
| 658 } | 748 } |
| 659 } | 749 } |
| 660 } | 750 } |
| 661 } | 751 } |
| 662 | 752 |
| 663 // Send flags - enumerable and configurable are common - writable is | 753 // Send flags - enumerable and configurable are common - writable is |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 725 } | 815 } |
| 726 } | 816 } |
| 727 return true; | 817 return true; |
| 728 } | 818 } |
| 729 | 819 |
| 730 | 820 |
| 731 // ES5 section 15.2.3.2. | 821 // ES5 section 15.2.3.2. |
| 732 function ObjectGetPrototypeOf(obj) { | 822 function ObjectGetPrototypeOf(obj) { |
| 733 if (!IS_SPEC_OBJECT(obj)) | 823 if (!IS_SPEC_OBJECT(obj)) |
| 734 throw MakeTypeError("obj_ctor_property_non_object", ["getPrototypeOf"]); | 824 throw MakeTypeError("obj_ctor_property_non_object", ["getPrototypeOf"]); |
| 735 return obj.__proto__; | 825 return %GetPrototype(obj); |
| 736 } | 826 } |
| 737 | 827 |
| 738 | 828 |
| 739 // ES5 section 15.2.3.3 | 829 // ES5 section 15.2.3.3 |
| 740 function ObjectGetOwnPropertyDescriptor(obj, p) { | 830 function ObjectGetOwnPropertyDescriptor(obj, p) { |
| 741 if (!IS_SPEC_OBJECT(obj)) | 831 if (!IS_SPEC_OBJECT(obj)) |
| 742 throw MakeTypeError("obj_ctor_property_non_object", ["getOwnPropertyDescript
or"]); | 832 throw MakeTypeError("obj_ctor_property_non_object", ["getOwnPropertyDescript
or"]); |
| 743 var desc = GetOwnProperty(obj, p); | 833 var desc = GetOwnProperty(obj, p); |
| 744 return FromPropertyDescriptor(desc); | 834 return FromPropertyDescriptor(desc); |
| 745 } | 835 } |
| 746 | 836 |
| 747 | 837 |
| 838 // For Harmony proxies |
| 839 function ToStringArray(obj, trap) { |
| 840 if (!IS_SPEC_OBJECT(obj)) { |
| 841 throw MakeTypeError("proxy_non_object_prop_names", [obj, trap]); |
| 842 } |
| 843 var n = ToUint32(obj.length); |
| 844 var array = new $Array(n); |
| 845 var names = {} |
| 846 for (var index = 0; index < n; index++) { |
| 847 var s = ToString(obj[index]); |
| 848 if (s in names) { |
| 849 throw MakeTypeError("proxy_repeated_prop_name", [obj, trap, s]) |
| 850 } |
| 851 array[index] = s; |
| 852 names.s = 0; |
| 853 } |
| 854 return array; |
| 855 } |
| 856 |
| 857 |
| 748 // ES5 section 15.2.3.4. | 858 // ES5 section 15.2.3.4. |
| 749 function ObjectGetOwnPropertyNames(obj) { | 859 function ObjectGetOwnPropertyNames(obj) { |
| 750 if (!IS_SPEC_OBJECT(obj)) | 860 if (!IS_SPEC_OBJECT(obj)) |
| 751 throw MakeTypeError("obj_ctor_property_non_object", ["getOwnPropertyNames"])
; | 861 throw MakeTypeError("obj_ctor_property_non_object", ["getOwnPropertyNames"])
; |
| 752 | 862 |
| 863 // Special handling for proxies. |
| 864 if (%IsJSProxy(obj)) { |
| 865 var handler = %GetHandler(obj); |
| 866 var getOwnPropertyNames = handler.getOwnPropertyNames; |
| 867 if (IS_UNDEFINED(getOwnPropertyNames)) { |
| 868 throw MakeTypeError("handler_trap_missing", |
| 869 [handler, "getOwnPropertyNames"]); |
| 870 } |
| 871 var names = getOwnPropertyNames.call(handler); |
| 872 return ToStringArray(names, "getOwnPropertyNames"); |
| 873 } |
| 874 |
| 753 // Find all the indexed properties. | 875 // Find all the indexed properties. |
| 754 | 876 |
| 755 // Get the local element names. | 877 // Get the local element names. |
| 756 var propertyNames = %GetLocalElementNames(obj); | 878 var propertyNames = %GetLocalElementNames(obj); |
| 757 | 879 |
| 758 // Get names for indexed interceptor properties. | 880 // Get names for indexed interceptor properties. |
| 759 if (%GetInterceptorInfo(obj) & 1) { | 881 if (%GetInterceptorInfo(obj) & 1) { |
| 760 var indexedInterceptorNames = | 882 var indexedInterceptorNames = |
| 761 %GetIndexedInterceptorElementNames(obj); | 883 %GetIndexedInterceptorElementNames(obj); |
| 762 if (indexedInterceptorNames) | 884 if (indexedInterceptorNames) |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 808 return obj; | 930 return obj; |
| 809 } | 931 } |
| 810 | 932 |
| 811 | 933 |
| 812 // ES5 section 15.2.3.6. | 934 // ES5 section 15.2.3.6. |
| 813 function ObjectDefineProperty(obj, p, attributes) { | 935 function ObjectDefineProperty(obj, p, attributes) { |
| 814 if (!IS_SPEC_OBJECT(obj)) { | 936 if (!IS_SPEC_OBJECT(obj)) { |
| 815 throw MakeTypeError("obj_ctor_property_non_object", ["defineProperty"]); | 937 throw MakeTypeError("obj_ctor_property_non_object", ["defineProperty"]); |
| 816 } | 938 } |
| 817 var name = ToString(p); | 939 var name = ToString(p); |
| 818 var desc = ToPropertyDescriptor(attributes); | 940 if (%IsJSProxy(obj)) { |
| 819 DefineOwnProperty(obj, name, desc, true); | 941 // Clone the attributes object for protection. |
| 942 // TODO(rossberg): not spec'ed yet, so not sure if this should involve |
| 943 // non-own properties as it does (or non-enumerable ones, as it doesn't?). |
| 944 var attributesClone = {} |
| 945 for (var a in attributes) { |
| 946 attributesClone[a] = attributes[a]; |
| 947 } |
| 948 DefineProxyProperty(obj, name, attributesClone, true); |
| 949 // The following would implement the spec as in the current proposal, |
| 950 // but after recent comments on es-discuss, is most likely obsolete. |
| 951 /* |
| 952 var defineObj = FromGenericPropertyDescriptor(desc); |
| 953 var names = ObjectGetOwnPropertyNames(attributes); |
| 954 var standardNames = |
| 955 {value: 0, writable: 0, get: 0, set: 0, enumerable: 0, configurable: 0}; |
| 956 for (var i = 0; i < names.length; i++) { |
| 957 var N = names[i]; |
| 958 if (!(%HasLocalProperty(standardNames, N))) { |
| 959 var attr = GetOwnProperty(attributes, N); |
| 960 DefineOwnProperty(descObj, N, attr, true); |
| 961 } |
| 962 } |
| 963 // This is really confusing the types, but it is what the proxies spec |
| 964 // currently requires: |
| 965 desc = descObj; |
| 966 */ |
| 967 } else { |
| 968 var desc = ToPropertyDescriptor(attributes); |
| 969 DefineOwnProperty(obj, name, desc, true); |
| 970 } |
| 820 return obj; | 971 return obj; |
| 821 } | 972 } |
| 822 | 973 |
| 823 | 974 |
| 824 // ES5 section 15.2.3.7. | 975 // ES5 section 15.2.3.7. |
| 825 function ObjectDefineProperties(obj, properties) { | 976 function ObjectDefineProperties(obj, properties) { |
| 826 if (!IS_SPEC_OBJECT(obj)) | 977 if (!IS_SPEC_OBJECT(obj)) |
| 827 throw MakeTypeError("obj_ctor_property_non_object", ["defineProperties"]); | 978 throw MakeTypeError("obj_ctor_property_non_object", ["defineProperties"]); |
| 828 var props = ToObject(properties); | 979 var props = ToObject(properties); |
| 829 var key_values = []; | 980 var key_values = []; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 846 | 997 |
| 847 // ES5 section 15.2.3.8. | 998 // ES5 section 15.2.3.8. |
| 848 function ObjectSeal(obj) { | 999 function ObjectSeal(obj) { |
| 849 if (!IS_SPEC_OBJECT(obj)) { | 1000 if (!IS_SPEC_OBJECT(obj)) { |
| 850 throw MakeTypeError("obj_ctor_property_non_object", ["seal"]); | 1001 throw MakeTypeError("obj_ctor_property_non_object", ["seal"]); |
| 851 } | 1002 } |
| 852 var names = ObjectGetOwnPropertyNames(obj); | 1003 var names = ObjectGetOwnPropertyNames(obj); |
| 853 for (var i = 0; i < names.length; i++) { | 1004 for (var i = 0; i < names.length; i++) { |
| 854 var name = names[i]; | 1005 var name = names[i]; |
| 855 var desc = GetOwnProperty(obj, name); | 1006 var desc = GetOwnProperty(obj, name); |
| 856 if (desc.isConfigurable()) desc.setConfigurable(false); | 1007 if (desc.isConfigurable()) { |
| 857 DefineOwnProperty(obj, name, desc, true); | 1008 desc.setConfigurable(false); |
| 1009 DefineOwnProperty(obj, name, desc, true); |
| 1010 } |
| 858 } | 1011 } |
| 859 return ObjectPreventExtension(obj); | 1012 return ObjectPreventExtension(obj); |
| 860 } | 1013 } |
| 861 | 1014 |
| 862 | 1015 |
| 863 // ES5 section 15.2.3.9. | 1016 // ES5 section 15.2.3.9. |
| 864 function ObjectFreeze(obj) { | 1017 function ObjectFreeze(obj) { |
| 865 if (!IS_SPEC_OBJECT(obj)) { | 1018 if (!IS_SPEC_OBJECT(obj)) { |
| 866 throw MakeTypeError("obj_ctor_property_non_object", ["freeze"]); | 1019 throw MakeTypeError("obj_ctor_property_non_object", ["freeze"]); |
| 867 } | 1020 } |
| 868 var names = ObjectGetOwnPropertyNames(obj); | 1021 var names = ObjectGetOwnPropertyNames(obj); |
| 869 for (var i = 0; i < names.length; i++) { | 1022 for (var i = 0; i < names.length; i++) { |
| 870 var name = names[i]; | 1023 var name = names[i]; |
| 871 var desc = GetOwnProperty(obj, name); | 1024 var desc = GetOwnProperty(obj, name); |
| 872 if (IsDataDescriptor(desc)) desc.setWritable(false); | 1025 if (desc.isWritable() || desc.isConfigurable()) { |
| 873 if (desc.isConfigurable()) desc.setConfigurable(false); | 1026 if (IsDataDescriptor(desc)) desc.setWritable(false); |
| 874 DefineOwnProperty(obj, name, desc, true); | 1027 desc.setConfigurable(false); |
| 1028 DefineOwnProperty(obj, name, desc, true); |
| 1029 } |
| 875 } | 1030 } |
| 876 return ObjectPreventExtension(obj); | 1031 return ObjectPreventExtension(obj); |
| 877 } | 1032 } |
| 878 | 1033 |
| 879 | 1034 |
| 880 // ES5 section 15.2.3.10 | 1035 // ES5 section 15.2.3.10 |
| 881 function ObjectPreventExtension(obj) { | 1036 function ObjectPreventExtension(obj) { |
| 882 if (!IS_SPEC_OBJECT(obj)) { | 1037 if (!IS_SPEC_OBJECT(obj)) { |
| 883 throw MakeTypeError("obj_ctor_property_non_object", ["preventExtension"]); | 1038 throw MakeTypeError("obj_ctor_property_non_object", ["preventExtension"]); |
| 884 } | 1039 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 920 if (!ObjectIsExtensible(obj)) { | 1075 if (!ObjectIsExtensible(obj)) { |
| 921 return true; | 1076 return true; |
| 922 } | 1077 } |
| 923 return false; | 1078 return false; |
| 924 } | 1079 } |
| 925 | 1080 |
| 926 | 1081 |
| 927 // ES5 section 15.2.3.13 | 1082 // ES5 section 15.2.3.13 |
| 928 function ObjectIsExtensible(obj) { | 1083 function ObjectIsExtensible(obj) { |
| 929 if (!IS_SPEC_OBJECT(obj)) { | 1084 if (!IS_SPEC_OBJECT(obj)) { |
| 930 throw MakeTypeError("obj_ctor_property_non_object", ["preventExtension"]); | 1085 throw MakeTypeError("obj_ctor_property_non_object", ["isExtensible"]); |
| 931 } | 1086 } |
| 932 return %IsExtensible(obj); | 1087 return %IsExtensible(obj); |
| 933 } | 1088 } |
| 934 | 1089 |
| 935 | 1090 |
| 936 %SetCode($Object, function(x) { | 1091 %SetCode($Object, function(x) { |
| 937 if (%_IsConstructCall()) { | 1092 if (%_IsConstructCall()) { |
| 938 if (x == null) return this; | 1093 if (x == null) return this; |
| 939 return ToObject(x); | 1094 return ToObject(x); |
| 940 } else { | 1095 } else { |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1262 // We already have caller and arguments properties on functions, | 1417 // We already have caller and arguments properties on functions, |
| 1263 // which are non-configurable. It therefore makes no sence to | 1418 // which are non-configurable. It therefore makes no sence to |
| 1264 // try to redefine these as defined by the spec. The spec says | 1419 // try to redefine these as defined by the spec. The spec says |
| 1265 // that bind should make these throw a TypeError if get or set | 1420 // that bind should make these throw a TypeError if get or set |
| 1266 // is called and make them non-enumerable and non-configurable. | 1421 // is called and make them non-enumerable and non-configurable. |
| 1267 // To be consistent with our normal functions we leave this as it is. | 1422 // To be consistent with our normal functions we leave this as it is. |
| 1268 | 1423 |
| 1269 // Set the correct length. | 1424 // Set the correct length. |
| 1270 var length = (this.length - argc_bound) > 0 ? this.length - argc_bound : 0; | 1425 var length = (this.length - argc_bound) > 0 ? this.length - argc_bound : 0; |
| 1271 %FunctionSetLength(result, length); | 1426 %FunctionSetLength(result, length); |
| 1272 | 1427 %FunctionRemovePrototype(result); |
| 1428 %FunctionSetBound(result); |
| 1273 return result; | 1429 return result; |
| 1274 } | 1430 } |
| 1275 | 1431 |
| 1276 | 1432 |
| 1277 function NewFunction(arg1) { // length == 1 | 1433 function NewFunction(arg1) { // length == 1 |
| 1278 var n = %_ArgumentsLength(); | 1434 var n = %_ArgumentsLength(); |
| 1279 var p = ''; | 1435 var p = ''; |
| 1280 if (n > 1) { | 1436 if (n > 1) { |
| 1281 p = new InternalArray(n - 1); | 1437 p = new InternalArray(n - 1); |
| 1282 for (var i = 0; i < n - 1; i++) p[i] = %_Arguments(i); | 1438 for (var i = 0; i < n - 1; i++) p[i] = %_Arguments(i); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1301 // ---------------------------------------------------------------------------- | 1457 // ---------------------------------------------------------------------------- |
| 1302 | 1458 |
| 1303 function SetupFunction() { | 1459 function SetupFunction() { |
| 1304 InstallFunctions($Function.prototype, DONT_ENUM, $Array( | 1460 InstallFunctions($Function.prototype, DONT_ENUM, $Array( |
| 1305 "bind", FunctionBind, | 1461 "bind", FunctionBind, |
| 1306 "toString", FunctionToString | 1462 "toString", FunctionToString |
| 1307 )); | 1463 )); |
| 1308 } | 1464 } |
| 1309 | 1465 |
| 1310 SetupFunction(); | 1466 SetupFunction(); |
| OLD | NEW |