| 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 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 return !(IsAccessorDescriptor(desc) || IsDataDescriptor(desc)); | 300 return !(IsAccessorDescriptor(desc) || IsDataDescriptor(desc)); |
| 301 } | 301 } |
| 302 | 302 |
| 303 | 303 |
| 304 function IsInconsistentDescriptor(desc) { | 304 function IsInconsistentDescriptor(desc) { |
| 305 return IsAccessorDescriptor(desc) && IsDataDescriptor(desc); | 305 return IsAccessorDescriptor(desc) && IsDataDescriptor(desc); |
| 306 } | 306 } |
| 307 | 307 |
| 308 // ES5 8.10.4 | 308 // ES5 8.10.4 |
| 309 function FromPropertyDescriptor(desc) { | 309 function FromPropertyDescriptor(desc) { |
| 310 if(IS_UNDEFINED(desc)) return desc; | 310 if (IS_UNDEFINED(desc)) return desc; |
| 311 var obj = new $Object(); | 311 var obj = new $Object(); |
| 312 if (IsDataDescriptor(desc)) { | 312 if (IsDataDescriptor(desc)) { |
| 313 obj.value = desc.getValue(); | 313 obj.value = desc.getValue(); |
| 314 obj.writable = desc.isWritable(); | 314 obj.writable = desc.isWritable(); |
| 315 } | 315 } |
| 316 if (IsAccessorDescriptor(desc)) { | 316 if (IsAccessorDescriptor(desc)) { |
| 317 obj.get = desc.getGet(); | 317 obj.get = desc.getGet(); |
| 318 obj.set = desc.getSet(); | 318 obj.set = desc.getSet(); |
| 319 } | 319 } |
| 320 obj.enumerable = desc.isEnumerable(); | 320 obj.enumerable = desc.isEnumerable(); |
| 321 obj.configurable = desc.isConfigurable(); | 321 obj.configurable = desc.isConfigurable(); |
| 322 return obj; | 322 return obj; |
| 323 } | 323 } |
| 324 | 324 |
| 325 // ES5 8.10.5. | 325 // ES5 8.10.5. |
| 326 function ToPropertyDescriptor(obj) { | 326 function ToPropertyDescriptor(obj) { |
| 327 if (!IS_OBJECT(obj)) { | 327 if (!IS_OBJECT(obj)) { |
| 328 throw MakeTypeError("property_desc_object", [obj]); | 328 throw MakeTypeError("property_desc_object", [obj]); |
| 329 } | 329 } |
| 330 var desc = new PropertyDescriptor(); | 330 var desc = new PropertyDescriptor(); |
| 331 | 331 |
| 332 if ("enumerable" in obj) { | 332 if ("enumerable" in obj) { |
| 333 desc.setEnumerable(ToBoolean(obj.enumerable)); | 333 desc.setEnumerable(ToBoolean(obj.enumerable)); |
| 334 } | 334 } |
| 335 | 335 |
| 336 | |
| 337 if ("configurable" in obj) { | 336 if ("configurable" in obj) { |
| 338 desc.setConfigurable(ToBoolean(obj.configurable)); | 337 desc.setConfigurable(ToBoolean(obj.configurable)); |
| 339 } | 338 } |
| 340 | 339 |
| 341 if ("value" in obj) { | 340 if ("value" in obj) { |
| 342 desc.setValue(obj.value); | 341 desc.setValue(obj.value); |
| 343 } | 342 } |
| 344 | 343 |
| 345 if ("writable" in obj) { | 344 if ("writable" in obj) { |
| 346 desc.setWritable(ToBoolean(obj.writable)); | 345 desc.setWritable(ToBoolean(obj.writable)); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 370 | 369 |
| 371 | 370 |
| 372 function PropertyDescriptor() { | 371 function PropertyDescriptor() { |
| 373 // Initialize here so they are all in-object and have the same map. | 372 // Initialize here so they are all in-object and have the same map. |
| 374 // Default values from ES5 8.6.1. | 373 // Default values from ES5 8.6.1. |
| 375 this.value_ = void 0; | 374 this.value_ = void 0; |
| 376 this.hasValue_ = false; | 375 this.hasValue_ = false; |
| 377 this.writable_ = false; | 376 this.writable_ = false; |
| 378 this.hasWritable_ = false; | 377 this.hasWritable_ = false; |
| 379 this.enumerable_ = false; | 378 this.enumerable_ = false; |
| 379 this.hasEnumerable_ = false; |
| 380 this.configurable_ = false; | 380 this.configurable_ = false; |
| 381 this.hasConfigurable_ = false; |
| 381 this.get_ = void 0; | 382 this.get_ = void 0; |
| 382 this.hasGetter_ = false; | 383 this.hasGetter_ = false; |
| 383 this.set_ = void 0; | 384 this.set_ = void 0; |
| 384 this.hasSetter_ = false; | 385 this.hasSetter_ = false; |
| 385 } | 386 } |
| 386 | 387 |
| 387 | 388 |
| 388 PropertyDescriptor.prototype.setValue = function(value) { | 389 PropertyDescriptor.prototype.setValue = function(value) { |
| 389 this.value_ = value; | 390 this.value_ = value; |
| 390 this.hasValue_ = true; | 391 this.hasValue_ = true; |
| 391 } | 392 } |
| 392 | 393 |
| 393 | 394 |
| 394 PropertyDescriptor.prototype.getValue = function() { | 395 PropertyDescriptor.prototype.getValue = function() { |
| 395 return this.value_; | 396 return this.value_; |
| 396 } | 397 } |
| 397 | 398 |
| 398 | 399 |
| 400 PropertyDescriptor.prototype.hasValue = function() { |
| 401 return this.hasValue_; |
| 402 } |
| 403 |
| 404 |
| 399 PropertyDescriptor.prototype.setEnumerable = function(enumerable) { | 405 PropertyDescriptor.prototype.setEnumerable = function(enumerable) { |
| 400 this.enumerable_ = enumerable; | 406 this.enumerable_ = enumerable; |
| 407 this.hasEnumerable_ = true; |
| 401 } | 408 } |
| 402 | 409 |
| 403 | 410 |
| 404 PropertyDescriptor.prototype.isEnumerable = function () { | 411 PropertyDescriptor.prototype.isEnumerable = function () { |
| 405 return this.enumerable_; | 412 return this.enumerable_; |
| 406 } | 413 } |
| 407 | 414 |
| 408 | 415 |
| 416 PropertyDescriptor.prototype.hasEnumerable = function() { |
| 417 return this.hasEnumerable_; |
| 418 } |
| 419 |
| 420 |
| 409 PropertyDescriptor.prototype.setWritable = function(writable) { | 421 PropertyDescriptor.prototype.setWritable = function(writable) { |
| 410 this.writable_ = writable; | 422 this.writable_ = writable; |
| 411 this.hasWritable_ = true; | 423 this.hasWritable_ = true; |
| 412 } | 424 } |
| 413 | 425 |
| 414 | 426 |
| 415 PropertyDescriptor.prototype.isWritable = function() { | 427 PropertyDescriptor.prototype.isWritable = function() { |
| 416 return this.writable_; | 428 return this.writable_; |
| 417 } | 429 } |
| 418 | 430 |
| 419 | 431 |
| 420 PropertyDescriptor.prototype.setConfigurable = function(configurable) { | 432 PropertyDescriptor.prototype.setConfigurable = function(configurable) { |
| 421 this.configurable_ = configurable; | 433 this.configurable_ = configurable; |
| 434 this.hasConfigurable_ = true; |
| 435 } |
| 436 |
| 437 |
| 438 PropertyDescriptor.prototype.hasConfigurable = function() { |
| 439 return this.hasConfigurable_; |
| 422 } | 440 } |
| 423 | 441 |
| 424 | 442 |
| 425 PropertyDescriptor.prototype.isConfigurable = function() { | 443 PropertyDescriptor.prototype.isConfigurable = function() { |
| 426 return this.configurable_; | 444 return this.configurable_; |
| 427 } | 445 } |
| 428 | 446 |
| 429 | 447 |
| 430 PropertyDescriptor.prototype.setGet = function(get) { | 448 PropertyDescriptor.prototype.setGet = function(get) { |
| 431 this.get_ = get; | 449 this.get_ = get; |
| 432 this.hasGetter_ = true; | 450 this.hasGetter_ = true; |
| 433 } | 451 } |
| 434 | 452 |
| 435 | 453 |
| 436 PropertyDescriptor.prototype.getGet = function() { | 454 PropertyDescriptor.prototype.getGet = function() { |
| 437 return this.get_; | 455 return this.get_; |
| 438 } | 456 } |
| 439 | 457 |
| 440 | 458 |
| 459 PropertyDescriptor.prototype.hasGetter = function() { |
| 460 return this.hasGetter_; |
| 461 } |
| 462 |
| 463 |
| 441 PropertyDescriptor.prototype.setSet = function(set) { | 464 PropertyDescriptor.prototype.setSet = function(set) { |
| 442 this.set_ = set; | 465 this.set_ = set; |
| 443 this.hasSetter_ = true; | 466 this.hasSetter_ = true; |
| 444 } | 467 } |
| 445 | 468 |
| 446 | 469 |
| 447 PropertyDescriptor.prototype.getSet = function() { | 470 PropertyDescriptor.prototype.getSet = function() { |
| 448 return this.set_; | 471 return this.set_; |
| 449 } | 472 } |
| 450 | 473 |
| 451 | 474 |
| 475 PropertyDescriptor.prototype.hasSetter = function() { |
| 476 return this.hasSetter_; |
| 477 } |
| 478 |
| 479 |
| 480 |
| 452 // ES5 section 8.12.1. | 481 // ES5 section 8.12.1. |
| 453 function GetOwnProperty(obj, p) { | 482 function GetOwnProperty(obj, p) { |
| 454 var desc = new PropertyDescriptor(); | 483 var desc = new PropertyDescriptor(); |
| 455 | 484 |
| 456 // An array with: | 485 // An array with: |
| 457 // obj is a data property [false, value, Writeable, Enumerable, Configurable] | 486 // obj is a data property [false, value, Writeable, Enumerable, Configurable] |
| 458 // obj is an accessor [true, Get, Set, Enumerable, Configurable] | 487 // obj is an accessor [true, Get, Set, Enumerable, Configurable] |
| 459 var props = %GetOwnProperty(ToObject(obj), ToString(p)); | 488 var props = %GetOwnProperty(ToObject(obj), ToString(p)); |
| 460 | 489 |
| 461 if (IS_UNDEFINED(props)) | 490 if (IS_UNDEFINED(props)) return void 0; |
| 462 return void 0; | |
| 463 | 491 |
| 464 // This is an accessor | 492 // This is an accessor |
| 465 if (props[0]) { | 493 if (props[0]) { |
| 466 desc.setGet(props[1]); | 494 desc.setGet(props[1]); |
| 467 desc.setSet(props[2]); | 495 desc.setSet(props[2]); |
| 468 } else { | 496 } else { |
| 469 desc.setValue(props[1]); | 497 desc.setValue(props[1]); |
| 470 desc.setWritable(props[2]); | 498 desc.setWritable(props[2]); |
| 471 } | 499 } |
| 472 desc.setEnumerable(props[3]); | 500 desc.setEnumerable(props[3]); |
| 473 desc.setConfigurable(props[4]); | 501 desc.setConfigurable(props[4]); |
| 474 | 502 |
| 475 return desc; | 503 return desc; |
| 476 } | 504 } |
| 477 | 505 |
| 478 | 506 |
| 479 // ES5 8.12.9. This version cannot cope with the property p already | 507 // ES5 section 8.12.2. |
| 480 // being present on obj. | 508 function GetProperty(obj, p) { |
| 509 var prop = GetOwnProperty(obj); |
| 510 if (!IS_UNDEFINED(prop)) return prop; |
| 511 var proto = obj.__proto__; |
| 512 if (IS_NULL(proto)) return void 0; |
| 513 return GetProperty(proto, p); |
| 514 } |
| 515 |
| 516 |
| 517 // ES5 section 8.12.6 |
| 518 function HasProperty(obj, p) { |
| 519 var desc = GetProperty(obj, p); |
| 520 return IS_UNDEFINED(desc) ? false : true; |
| 521 } |
| 522 |
| 523 |
| 524 // ES5 8.12.9. |
| 481 function DefineOwnProperty(obj, p, desc, should_throw) { | 525 function DefineOwnProperty(obj, p, desc, should_throw) { |
| 482 var flag = desc.isEnumerable() ? 0 : DONT_ENUM; | 526 var current = GetOwnProperty(obj, p); |
| 483 if (IsDataDescriptor(desc)) { | 527 var extensible = %IsExtensible(ToObject(obj)); |
| 484 flag |= desc.isWritable() ? 0 : (DONT_DELETE | READ_ONLY); | 528 |
| 485 %SetProperty(obj, p, desc.getValue(), flag); | 529 // Error handling according to spec. |
| 530 // Step 3 |
| 531 if (IS_UNDEFINED(current) && !extensible) |
| 532 throw MakeTypeError("define_disallowed", ["defineProperty"]); |
| 533 |
| 534 if (!IS_UNDEFINED(current) && !current.isConfigurable()) { |
| 535 // Step 7 |
| 536 if (desc.isConfigurable() || desc.isEnumerable() != current.isEnumerable()) |
| 537 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| 538 // Step 9 |
| 539 if (IsDataDescriptor(current) != IsDataDescriptor(desc)) |
| 540 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| 541 // Step 10 |
| 542 if (IsDataDescriptor(current) && IsDataDescriptor(desc)) { |
| 543 if (!current.isWritable() && desc.isWritable()) |
| 544 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| 545 if (!current.isWritable() && desc.hasValue() && |
| 546 !SameValue(desc.getValue(), current.getValue())) { |
| 547 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| 548 } |
| 549 } |
| 550 // Step 11 |
| 551 if (IsAccessorDescriptor(desc) && IsAccessorDescriptor(current)) { |
| 552 if (desc.hasSetter() && !SameValue(desc.getSet(), current.getSet())){ |
| 553 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| 554 } |
| 555 if (desc.hasGetter() && !SameValue(desc.getGet(),current.getGet())) |
| 556 throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| 557 } |
| 558 } |
| 559 |
| 560 // Send flags - enumerable and configurable are common - writable is |
| 561 // only send to the data descriptor. |
| 562 // Take special care if enumerable and configurable is not defined on |
| 563 // desc (we need to preserve the existing values from current). |
| 564 var flag = NONE; |
| 565 if (desc.hasEnumerable()) { |
| 566 flag |= desc.isEnumerable() ? 0 : DONT_ENUM; |
| 567 } else if (!IS_UNDEFINED(current)) { |
| 568 flag |= current.isEnumerable() ? 0 : DONT_ENUM; |
| 486 } else { | 569 } else { |
| 487 if (IS_FUNCTION(desc.getGet())) %DefineAccessor(obj, p, GETTER, desc.getGet(
), flag); | 570 flag |= DONT_ENUM; |
| 488 if (IS_FUNCTION(desc.getSet())) %DefineAccessor(obj, p, SETTER, desc.getSet(
), flag); | 571 } |
| 572 |
| 573 if (desc.hasConfigurable()) { |
| 574 flag |= desc.isConfigurable() ? 0 : DONT_DELETE; |
| 575 } else if (!IS_UNDEFINED(current)) { |
| 576 flag |= current.isConfigurable() ? 0 : DONT_DELETE; |
| 577 } else |
| 578 flag |= DONT_DELETE; |
| 579 |
| 580 if (IsDataDescriptor(desc) || IsGenericDescriptor(desc)) { |
| 581 flag |= desc.isWritable() ? 0 : READ_ONLY; |
| 582 %DefineOrRedefineDataProperty(obj, p, desc.getValue(), flag); |
| 583 } else { |
| 584 if (desc.hasGetter() && IS_FUNCTION(desc.getGet())) { |
| 585 %DefineOrRedefineAccessorProperty(obj, p, GETTER, desc.getGet(), flag); |
| 586 } |
| 587 if (desc.hasSetter() && IS_FUNCTION(desc.getSet())) { |
| 588 %DefineOrRedefineAccessorProperty(obj, p, SETTER, desc.getSet(), flag); |
| 589 } |
| 489 } | 590 } |
| 490 return true; | 591 return true; |
| 491 } | 592 } |
| 492 | 593 |
| 493 | 594 |
| 494 // ES5 section 15.2.3.2. | 595 // ES5 section 15.2.3.2. |
| 495 function ObjectGetPrototypeOf(obj) { | 596 function ObjectGetPrototypeOf(obj) { |
| 496 if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj)) | 597 if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj)) |
| 497 throw MakeTypeError("obj_ctor_property_non_object", ["getPrototypeOf"]); | 598 throw MakeTypeError("obj_ctor_property_non_object", ["getPrototypeOf"]); |
| 498 return obj.__proto__; | 599 return obj.__proto__; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 551 if (!IS_OBJECT(proto) && !IS_NULL(proto)) { | 652 if (!IS_OBJECT(proto) && !IS_NULL(proto)) { |
| 552 throw MakeTypeError("proto_object_or_null", [proto]); | 653 throw MakeTypeError("proto_object_or_null", [proto]); |
| 553 } | 654 } |
| 554 var obj = new $Object(); | 655 var obj = new $Object(); |
| 555 obj.__proto__ = proto; | 656 obj.__proto__ = proto; |
| 556 if (!IS_UNDEFINED(properties)) ObjectDefineProperties(obj, properties); | 657 if (!IS_UNDEFINED(properties)) ObjectDefineProperties(obj, properties); |
| 557 return obj; | 658 return obj; |
| 558 } | 659 } |
| 559 | 660 |
| 560 | 661 |
| 561 // ES5 section 15.2.3.7. This version cannot cope with the properies already | 662 // ES5 section 15.2.3.6. |
| 562 // being present on obj. Therefore it is not exposed as | 663 function ObjectDefineProperty(obj, p, attributes) { |
| 563 // Object.defineProperties yet. | 664 if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj)) |
| 665 throw MakeTypeError("obj_ctor_property_non_object", ["defineProperty"]); |
| 666 var name = ToString(p); |
| 667 var desc = ToPropertyDescriptor(attributes); |
| 668 DefineOwnProperty(obj, name, desc, true); |
| 669 return obj; |
| 670 } |
| 671 |
| 672 |
| 673 // ES5 section 15.2.3.7. |
| 564 function ObjectDefineProperties(obj, properties) { | 674 function ObjectDefineProperties(obj, properties) { |
| 675 if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj)) |
| 676 throw MakeTypeError("obj_ctor_property_non_object", ["defineProperties"]); |
| 565 var props = ToObject(properties); | 677 var props = ToObject(properties); |
| 566 var key_values = []; | 678 var key_values = []; |
| 567 for (var key in props) { | 679 for (var key in props) { |
| 568 if (%HasLocalProperty(props, key)) { | 680 if (%HasLocalProperty(props, key)) { |
| 569 key_values.push(key); | 681 key_values.push(key); |
| 570 var value = props[key]; | 682 var value = props[key]; |
| 571 var desc = ToPropertyDescriptor(value); | 683 var desc = ToPropertyDescriptor(value); |
| 572 key_values.push(desc); | 684 key_values.push(desc); |
| 573 } | 685 } |
| 574 } | 686 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 604 "isPrototypeOf", ObjectIsPrototypeOf, | 716 "isPrototypeOf", ObjectIsPrototypeOf, |
| 605 "propertyIsEnumerable", ObjectPropertyIsEnumerable, | 717 "propertyIsEnumerable", ObjectPropertyIsEnumerable, |
| 606 "__defineGetter__", ObjectDefineGetter, | 718 "__defineGetter__", ObjectDefineGetter, |
| 607 "__lookupGetter__", ObjectLookupGetter, | 719 "__lookupGetter__", ObjectLookupGetter, |
| 608 "__defineSetter__", ObjectDefineSetter, | 720 "__defineSetter__", ObjectDefineSetter, |
| 609 "__lookupSetter__", ObjectLookupSetter | 721 "__lookupSetter__", ObjectLookupSetter |
| 610 )); | 722 )); |
| 611 InstallFunctions($Object, DONT_ENUM, $Array( | 723 InstallFunctions($Object, DONT_ENUM, $Array( |
| 612 "keys", ObjectKeys, | 724 "keys", ObjectKeys, |
| 613 "create", ObjectCreate, | 725 "create", ObjectCreate, |
| 726 "defineProperty", ObjectDefineProperty, |
| 727 "defineProperties", ObjectDefineProperties, |
| 614 "getPrototypeOf", ObjectGetPrototypeOf, | 728 "getPrototypeOf", ObjectGetPrototypeOf, |
| 615 "getOwnPropertyDescriptor", ObjectGetOwnPropertyDescriptor, | 729 "getOwnPropertyDescriptor", ObjectGetOwnPropertyDescriptor, |
| 616 "getOwnPropertyNames", ObjectGetOwnPropertyNames | 730 "getOwnPropertyNames", ObjectGetOwnPropertyNames |
| 617 )); | 731 )); |
| 618 } | 732 } |
| 619 | 733 |
| 620 SetupObject(); | 734 SetupObject(); |
| 621 | 735 |
| 622 | 736 |
| 623 // ---------------------------------------------------------------------------- | 737 // ---------------------------------------------------------------------------- |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 874 | 988 |
| 875 // ---------------------------------------------------------------------------- | 989 // ---------------------------------------------------------------------------- |
| 876 | 990 |
| 877 function SetupFunction() { | 991 function SetupFunction() { |
| 878 InstallFunctions($Function.prototype, DONT_ENUM, $Array( | 992 InstallFunctions($Function.prototype, DONT_ENUM, $Array( |
| 879 "toString", FunctionToString | 993 "toString", FunctionToString |
| 880 )); | 994 )); |
| 881 } | 995 } |
| 882 | 996 |
| 883 SetupFunction(); | 997 SetupFunction(); |
| OLD | NEW |