Home | History | Annotate | Download | only in webkit
      1 // Copyright 2013 the V8 project authors. All rights reserved.
      2 // Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions
      6 // are met:
      7 // 1.  Redistributions of source code must retain the above copyright
      8 //     notice, this list of conditions and the following disclaimer.
      9 // 2.  Redistributions in binary form must reproduce the above copyright
     10 //     notice, this list of conditions and the following disclaimer in the
     11 //     documentation and/or other materials provided with the distribution.
     12 //
     13 // THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
     14 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     15 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     16 // DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     17 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     18 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     19 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     20 // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     21 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     22 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23 
     24 description(
     25 "This test checks whether various seal/freeze/preventExtentions work on a regular object."
     26 );
     27 
     28 function obj()
     29 {
     30     // Add an accessor property to check 'isFrozen' returns the correct result for objects with accessors.
     31     return Object.defineProperty({ a: 1, b: 2 }, 'g', { get: function() { return "getter"; } });
     32 }
     33 
     34 function test(obj)
     35 {
     36     obj.c =3;
     37     obj.b =4;
     38     delete obj.a;
     39 
     40     var result = "";
     41     for (key in obj)
     42         result += ("(" + key + ":" + obj[key] + ")");
     43     if (Object.isSealed(obj))
     44         result += "S";
     45     if (Object.isFrozen(obj))
     46         result += "F";
     47     if (Object.isExtensible(obj))
     48         result += "E";
     49     return result;
     50 }
     51 
     52 function seal(obj)
     53 {
     54     Object.seal(obj);
     55     return obj;
     56 }
     57 
     58 function freeze(obj)
     59 {
     60     Object.freeze(obj);
     61     return obj;
     62 }
     63 
     64 function preventExtensions(obj)
     65 {
     66     Object.preventExtensions(obj);
     67     return obj;
     68 }
     69 
     70 function inextensible(){}
     71 function sealed(){}
     72 function frozen(){};
     73 preventExtensions(inextensible);
     74 seal(sealed);
     75 freeze(frozen);
     76 new inextensible;
     77 new sealed;
     78 new frozen;
     79 inextensible.prototype.prototypeExists = true;
     80 sealed.prototype.prototypeExists = true;
     81 frozen.prototype.prototypeExists = true;
     82 
     83 shouldBeTrue("(new inextensible).prototypeExists");
     84 shouldBeTrue("(new sealed).prototypeExists");
     85 shouldBeTrue("(new frozen).prototypeExists");
     86 
     87 shouldBe('test(obj())', '"(b:4)(c:3)E"'); // extensible, can delete a, can modify b, and can add c
     88 shouldBe('test(preventExtensions(obj()))', '"(b:4)"'); // <nothing>, can delete a, can modify b, and CANNOT add c
     89 shouldBe('test(seal(obj()))', '"(a:1)(b:4)S"'); // sealed, CANNOT delete a, can modify b, and CANNOT add c
     90 shouldBe('test(freeze(obj()))', '"(a:1)(b:2)SF"'); // sealed and frozen, CANNOT delete a, CANNOT modify b, and CANNOT add c
     91 
     92 // check that we can preventExtensions on a host function.
     93 shouldBe('Object.preventExtensions(Math.sin)', 'Math.sin');
     94 
     95 shouldThrow('var o = {}; Object.preventExtensions(o); o.__proto__ = { newProp: "Should not see this" }; o.newProp;');
     96 shouldThrow('"use strict"; var o = {}; Object.preventExtensions(o); o.__proto__ = { newProp: "Should not see this" }; o.newProp;');
     97 
     98 // check that we can still access static properties on an object after calling preventExtensions.
     99 shouldBe('Object.preventExtensions(Math); Math.sqrt(4)', '2');
    100 
    101 // Should not be able to add properties to a preventExtensions array.
    102 shouldBeUndefined('var arr = Object.preventExtensions([]); arr[0] = 42; arr[0]');
    103 shouldBe('var arr = Object.preventExtensions([]); arr[0] = 42; arr.length', '0');
    104 // In strict mode, this throws.
    105 shouldThrow('"use strict"; var arr = Object.preventExtensions([]); arr[0] = 42; arr[0]');
    106 
    107 // A read-only property on the prototype should prevent a [[Put]] .
    108 function Constructor() {}
    109 Constructor.prototype.foo = 1;
    110 Object.freeze(Constructor.prototype);
    111 var obj = new Constructor();
    112 obj.foo = 2;
    113 shouldBe('obj.foo', '1');
    114 
    115 // Check that freezing a function works correctly.
    116 var func = freeze(function foo(){});
    117 shouldBeTrue('Object.isFrozen(func)')
    118 func.prototype = 42;
    119 shouldBeFalse('func.prototype === 42');
    120 shouldBeFalse('Object.getOwnPropertyDescriptor(func, "prototype").writable')
    121 
    122 // Check that freezing a strict function works correctly.
    123 var strictFunc = freeze(function foo(){ "use strict"; });
    124 shouldBeTrue('Object.isFrozen(strictFunc)')
    125 strictFunc.prototype = 42;
    126 shouldBeFalse('strictFunc.prototype === 42');
    127 shouldBeFalse('Object.getOwnPropertyDescriptor(strictFunc, "prototype").writable')
    128 
    129 // Check that freezing array objects works correctly.
    130 var array = freeze([0,1,2]);
    131 shouldBeTrue('Object.isFrozen(array)')
    132 array[0] = 3;
    133 shouldBe('array[0]', '0');
    134 shouldBeFalse('Object.getOwnPropertyDescriptor(array, "length").writable')
    135 
    136 // Check that freezing arguments objects works correctly.
    137 var args = freeze((function(){ return arguments; })(0,1,2));
    138 shouldBeTrue('Object.isFrozen(args)')
    139 args[0] = 3;
    140 shouldBe('args[0]', '0');
    141 shouldBeFalse('Object.getOwnPropertyDescriptor(args, "length").writable')
    142 shouldBeFalse('Object.getOwnPropertyDescriptor(args, "callee").writable')
    143 
    144 // Check that freeze still works if preventExtensions has been called on the object.
    145 function preventExtensionsFreezeIsFrozen(x)
    146 {
    147     Object.preventExtensions(x);
    148     Object.freeze(x);
    149     return Object.isFrozen(x);
    150 }
    151 shouldBeTrue('preventExtensionsFreezeIsFrozen(function foo(){})')
    152 shouldBeTrue('preventExtensionsFreezeIsFrozen(function foo(){ "use strict"; })')
    153 shouldBeTrue('preventExtensionsFreezeIsFrozen([0,1,2])')
    154 shouldBeTrue('preventExtensionsFreezeIsFrozen((function(){ return arguments; })(0,1,2))')
    155 
    156 shouldBeFalse('Object.getOwnPropertyDescriptor(freeze({0:0}), 0).configurable');
    157 shouldBeFalse('Object.getOwnPropertyDescriptor(freeze({10000001:0}), 10000001).configurable');
    158