Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(269)

Side by Side Diff: src/v8natives.js

Issue 555149: Added Object.defineProperty + needed internal functionality:... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/runtime.js ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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();
OLDNEW
« no previous file with comments | « src/runtime.js ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698