/* * Tests for Object isSealed(), isFrozen(), isExtensible(), seal(), * and freeze(). */ /*=== sealed: false, frozen: false, extensible: true sealed: true, frozen: false, extensible: false sealed: false, frozen: false, extensible: true sealed: true, frozen: true, extensible: false sealed: false, frozen: false, extensible: true sealed: true, frozen: false, extensible: false sealed: false, frozen: false, extensible: true sealed: true, frozen: true, extensible: false ===*/ function basicTest() { var obj; function p(o) { print('sealed: ' + Object.isSealed(o) + ', frozen: ' + Object.isFrozen(o) + ', extensible: ' + Object.isExtensible(o)); } obj = { foo: 1, bar: 2 }; p(obj); Object.seal(obj); p(obj); obj = { foo: 1, bar: 2 }; p(obj); Object.freeze(obj); p(obj); // create objects which are already sealed/frozen(), without a // seal() or freeze() call. obj = Object.create(Object.prototype, { prop1: { value: 123, writable: true, enumerable: true, configurable: false }, prop2: { get: function(){}, set: function(){}, enumerable: true, configurable: false } }); p(obj); // extensible -> not sealed or frozen Object.preventExtensions(obj); // now sealed, but not frozen (writable property exists) p(obj); // sealed and frozen obj = Object.create(Object.prototype, { prop1: { value: 123, writable: false, enumerable: true, configurable: false }, prop2: { get: function(){}, set: function(){}, enumerable: true, configurable: false } }); p(obj); // extensible -> not sealed or frozen Object.preventExtensions(obj); // now sealed and frozen: no writable properties, accessors are OK p(obj); } try { basicTest(); } catch (e) { print(e); } /*=== object, #names: 12, extensible: true index: 0, name: prop1, value: 1, writable: true, enumerable: true, configurable: true, get: undefined, set: undefined index: 1, name: prop2, value: 2, writable: false, enumerable: true, configurable: true, get: undefined, set: undefined index: 2, name: prop3, value: 3, writable: true, enumerable: false, configurable: true, get: undefined, set: undefined index: 3, name: prop4, value: 4, writable: false, enumerable: false, configurable: true, get: undefined, set: undefined index: 4, name: prop5, value: 5, writable: true, enumerable: true, configurable: false, get: undefined, set: undefined index: 5, name: prop6, value: 6, writable: false, enumerable: true, configurable: false, get: undefined, set: undefined index: 6, name: prop7, value: 7, writable: true, enumerable: false, configurable: false, get: undefined, set: undefined index: 7, name: prop8, value: 8, writable: false, enumerable: false, configurable: false, get: undefined, set: undefined index: 8, name: acc1, value: undefined, writable: undefined, enumerable: true, configurable: true, get: function, set: function index: 9, name: acc2, value: undefined, writable: undefined, enumerable: false, configurable: true, get: function, set: function index: 10, name: acc3, value: undefined, writable: undefined, enumerable: true, configurable: false, get: function, set: function index: 11, name: acc4, value: undefined, writable: undefined, enumerable: false, configurable: false, get: function, set: function object, #names: 12, extensible: false index: 0, name: prop1, value: 1, writable: true, enumerable: true, configurable: false, get: undefined, set: undefined index: 1, name: prop2, value: 2, writable: false, enumerable: true, configurable: false, get: undefined, set: undefined index: 2, name: prop3, value: 3, writable: true, enumerable: false, configurable: false, get: undefined, set: undefined index: 3, name: prop4, value: 4, writable: false, enumerable: false, configurable: false, get: undefined, set: undefined index: 4, name: prop5, value: 5, writable: true, enumerable: true, configurable: false, get: undefined, set: undefined index: 5, name: prop6, value: 6, writable: false, enumerable: true, configurable: false, get: undefined, set: undefined index: 6, name: prop7, value: 7, writable: true, enumerable: false, configurable: false, get: undefined, set: undefined index: 7, name: prop8, value: 8, writable: false, enumerable: false, configurable: false, get: undefined, set: undefined index: 8, name: acc1, value: undefined, writable: undefined, enumerable: true, configurable: false, get: function, set: function index: 9, name: acc2, value: undefined, writable: undefined, enumerable: false, configurable: false, get: function, set: function index: 10, name: acc3, value: undefined, writable: undefined, enumerable: true, configurable: false, get: function, set: function index: 11, name: acc4, value: undefined, writable: undefined, enumerable: false, configurable: false, get: function, set: function object, #names: 12, extensible: true index: 0, name: prop1, value: 1, writable: true, enumerable: true, configurable: true, get: undefined, set: undefined index: 1, name: prop2, value: 2, writable: false, enumerable: true, configurable: true, get: undefined, set: undefined index: 2, name: prop3, value: 3, writable: true, enumerable: false, configurable: true, get: undefined, set: undefined index: 3, name: prop4, value: 4, writable: false, enumerable: false, configurable: true, get: undefined, set: undefined index: 4, name: prop5, value: 5, writable: true, enumerable: true, configurable: false, get: undefined, set: undefined index: 5, name: prop6, value: 6, writable: false, enumerable: true, configurable: false, get: undefined, set: undefined index: 6, name: prop7, value: 7, writable: true, enumerable: false, configurable: false, get: undefined, set: undefined index: 7, name: prop8, value: 8, writable: false, enumerable: false, configurable: false, get: undefined, set: undefined index: 8, name: acc1, value: undefined, writable: undefined, enumerable: true, configurable: true, get: function, set: function index: 9, name: acc2, value: undefined, writable: undefined, enumerable: false, configurable: true, get: function, set: function index: 10, name: acc3, value: undefined, writable: undefined, enumerable: true, configurable: false, get: function, set: function index: 11, name: acc4, value: undefined, writable: undefined, enumerable: false, configurable: false, get: function, set: function object, #names: 12, extensible: false index: 0, name: prop1, value: 1, writable: false, enumerable: true, configurable: false, get: undefined, set: undefined index: 1, name: prop2, value: 2, writable: false, enumerable: true, configurable: false, get: undefined, set: undefined index: 2, name: prop3, value: 3, writable: false, enumerable: false, configurable: false, get: undefined, set: undefined index: 3, name: prop4, value: 4, writable: false, enumerable: false, configurable: false, get: undefined, set: undefined index: 4, name: prop5, value: 5, writable: false, enumerable: true, configurable: false, get: undefined, set: undefined index: 5, name: prop6, value: 6, writable: false, enumerable: true, configurable: false, get: undefined, set: undefined index: 6, name: prop7, value: 7, writable: false, enumerable: false, configurable: false, get: undefined, set: undefined index: 7, name: prop8, value: 8, writable: false, enumerable: false, configurable: false, get: undefined, set: undefined index: 8, name: acc1, value: undefined, writable: undefined, enumerable: true, configurable: false, get: function, set: function index: 9, name: acc2, value: undefined, writable: undefined, enumerable: false, configurable: false, get: function, set: function index: 10, name: acc3, value: undefined, writable: undefined, enumerable: true, configurable: false, get: function, set: function index: 11, name: acc4, value: undefined, writable: undefined, enumerable: false, configurable: false, get: function, set: function ===*/ function propertyAttributeTest() { var obj; var prop_names = [ 'prop1', 'prop2', 'prop3', 'prop4', 'prop5', 'prop6', 'prop7', 'prop8', 'acc1', 'acc2', 'acc3', 'acc4' ]; function mkGetter() { return function getter() { print('getter called'); throw new Error('unexpected getter call'); }; } function mkSetter() { return function getter() { print('setter called'); throw new Error('unexpected setter call'); }; } function mkObj() { var obj = {}; Object.defineProperties(obj, { prop1: { value: 1, writable: true, enumerable: true, configurable: true }, prop2: { value: 2, writable: false, enumerable: true, configurable: true }, prop3: { value: 3, writable: true, enumerable: false, configurable: true }, prop4: { value: 4, writable: false, enumerable: false, configurable: true }, prop5: { value: 5, writable: true, enumerable: true, configurable: false }, prop6: { value: 6, writable: false, enumerable: true, configurable: false }, prop7: { value: 7, writable: true, enumerable: false, configurable: false }, prop8: { value: 8, writable: false, enumerable: false, configurable: false }, acc1: { get: mkGetter(), set: mkSetter(), enumerable: true, configurable: true }, acc2: { get: mkGetter(), set: mkSetter(), enumerable: false, configurable: true }, acc3: { get: mkGetter(), set: mkSetter(), enumerable: true, configurable: false }, acc4: { get: mkGetter(), set: mkSetter(), enumerable: false, configurable: false }, }); /* For some reason V8 (at least 3.7.12.22) reorders these properties regardless of whether one uses defineProperty() or defineProperties(). So, we read back properties with explicitly ordered names below instead of relying on Object.getOwnPropertyNames(). Object.defineProperty(obj, 'prop1', { value: 1, writable: true, enumerable: true, configurable: true }); Object.defineProperty(obj, 'prop2', { value: 2, writable: false, enumerable: true, configurable: true }); Object.defineProperty(obj, 'prop3', { value: 3, writable: true, enumerable: false, configurable: true }); Object.defineProperty(obj, 'prop4', { value: 4, writable: false, enumerable: false, configurable: true }); Object.defineProperty(obj, 'prop5', { value: 5, writable: true, enumerable: true, configurable: false }); Object.defineProperty(obj, 'prop6', { value: 6, writable: false, enumerable: true, configurable: false }); Object.defineProperty(obj, 'prop7', { value: 7, writable: true, enumerable: false, configurable: false }); Object.defineProperty(obj, 'prop8', { value: 8, writable: false, enumerable: false, configurable: false }); Object.defineProperty(obj, 'acc1', { get: mkGetter(), set: mkSetter(), enumerable: true, configurable: true }); Object.defineProperty(obj, 'acc2', { get: mkGetter(), set: mkSetter(), enumerable: false, configurable: true }); Object.defineProperty(obj, 'acc3', { get: mkGetter(), set: mkSetter(), enumerable: true, configurable: false }); Object.defineProperty(obj, 'acc4', { get: mkGetter(), set: mkSetter(), enumerable: false, configurable: false }); */ return obj; } function printObj(o) { var i, pd; names = Object.getOwnPropertyNames(o); print('object, #names: ' + names.length + ', extensible: ' + Object.isExtensible(o)); /* Use explicit names because V8 loses property order for some reason */ for (i = 0; i < prop_names.length; i++) { pd = Object.getOwnPropertyDescriptor(o, prop_names[i]); print('index: ' + i + ', name: ' + prop_names[i] + ', value: ' + pd.value + ', writable: ' + pd.writable + ', enumerable: ' + pd.enumerable + ', configurable: ' + pd.configurable + ', get: ' + typeof pd.get + ', set: ' + typeof pd.set); } } obj = mkObj(); printObj(obj); Object.seal(obj); printObj(obj); obj = mkObj(); printObj(obj); Object.freeze(obj); printObj(obj); } try { propertyAttributeTest(); } catch (e) { print(e); } /*=== 0 0 TypeError 0 1 TypeError 0 2 TypeError 0 3 TypeError 0 4 TypeError 0 5 TypeError 0 6 ok 0 7 ok 1 0 TypeError 1 1 TypeError 1 2 TypeError 1 3 TypeError 1 4 TypeError 1 5 TypeError 1 6 ok 1 7 ok 2 0 TypeError 2 1 TypeError 2 2 TypeError 2 3 TypeError 2 4 TypeError 2 5 TypeError 2 6 ok 2 7 ok 3 0 TypeError 3 1 TypeError 3 2 TypeError 3 3 TypeError 3 4 TypeError 3 5 TypeError 3 6 ok 3 7 ok 4 0 TypeError 4 1 TypeError 4 2 TypeError 4 3 TypeError 4 4 TypeError 4 5 TypeError 4 6 ok 4 7 ok ===*/ function coercionTest() { var funcs = [ Object.isSealed, Object.isFrozen, Object.isExtensible, Object.seal, Object.freeze ]; var values = [ undefined, null, true, false, 123, 'foo', [1,2], { foo: 1, bar: 2 } ]; var i, j; function test(func, obj) { try { func(obj); print('ok'); } catch (e) { print(e.name); } } for (i = 0; i < funcs.length; i++) { for (j = 0; j < values.length; j++) { print(i, j); test(funcs[i], values[j]); } } } try { coercionTest(); } catch (e) { print(e); } /* FIXME: test that ancestors have no effect and or not affected */