Chromium Code Reviews| Index: test/mjsunit/object-create.js |
| =================================================================== |
| --- test/mjsunit/object-create.js (revision 0) |
| +++ test/mjsunit/object-create.js (revision 0) |
| @@ -0,0 +1,234 @@ |
| +// Copyright 2009 the V8 project authors. All rights reserved. |
| +// Redistribution and use in source and binary forms, with or without |
| +// modification, are permitted provided that the following conditions are |
| +// met: |
| +// |
| +// * Redistributions of source code must retain the above copyright |
| +// notice, this list of conditions and the following disclaimer. |
| +// * Redistributions in binary form must reproduce the above |
| +// copyright notice, this list of conditions and the following |
| +// disclaimer in the documentation and/or other materials provided |
| +// with the distribution. |
| +// * Neither the name of Google Inc. nor the names of its |
| +// contributors may be used to endorse or promote products derived |
| +// from this software without specific prior written permission. |
| +// |
| +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| + |
| +// Test ES5 sections 15.2.3.5 Object.create. |
| +// We do not support nonconfigurable properties on objects so that is not |
| +// tested. We do test getters, setters, writable, enumerable and value. |
| + |
| +// Check that no exceptions are thrown. |
| +Object.create(null); |
| +Object.create(null, undefined); |
| + |
| +var ctr = 0; |
| +var ctr2 = 0; |
| +var ctr3 = 0; |
| +var ctr4 = 0; |
| +var ctr5 = 0; |
| +var ctr6 = 1000; |
| + |
| +var foo_proto = { foo: function() { ctr++; }}; |
|
Christian Plesner Hansen
2009/12/08 20:44:40
lowerCamelCase.
|
| +var fooValue = { foo: { writable: true, value: function() { ctr2++; }}}; |
| +var fooGetter = { foo: { get: function() { return ctr3++; }}}; |
| +var fooSetter = { foo: { set: function() { return ctr4++; }}}; |
| +var fooAmbiguous = { foo: { get: function() { return ctr3++; }, |
| + value: 3 }}; |
| + |
| +function valueGet() { ctr5++; return 3 }; |
| +function getterGet() { ctr5++; return function() { return ctr6++; }; }; |
| + |
| +// Simple object with prototype, no properties added. |
| +Object.create(foo_proto).foo(); |
| +assertEquals(1, ctr); |
| + |
| +// Simple object with object with prototype, no properties added. |
| +Object.create(Object.create(foo_proto)).foo(); |
| +assertEquals(2, ctr); |
| + |
| +// Add a property foo that returns a function. |
| +var v = Object.create(foo_proto, fooValue); |
| +v.foo(); |
| +assertEquals(2, ctr); |
| +assertEquals(1, ctr2); |
| + |
| +// Ensure the property is writable. |
| +v.foo = 42; |
| +assertEquals(42, v.foo); |
| +assertEquals(2, ctr); |
| +assertEquals(1, ctr2); |
| + |
| +// Ensure by default properties are not writable. |
| +v = Object.create(null, { foo: {value: 103}}); |
| +assertEquals(103, v.foo); |
| +v.foo = 42; |
| +assertEquals(103, v.foo); |
| + |
| +// Add a getter foo that returns a counter value. |
| +assertEquals(0, Object.create(foo_proto, fooGetter).foo); |
| +assertEquals(2, ctr); |
| +assertEquals(1, ctr2); |
| +assertEquals(1, ctr3); |
| + |
| +// Add a setter foo that runs a function. |
| +assertEquals(1, Object.create(foo_proto, fooSetter).foo = 1); |
| +assertEquals(2, ctr); |
| +assertEquals(1, ctr2); |
| +assertEquals(1, ctr3); |
| +assertEquals(1, ctr4); |
| + |
| +// Make sure that trying to add both a value and a getter |
| +// will result in an exception. |
| +try { |
| + Object.create(foo_proto, fooAmbiguous); |
| + assertTrue(false); |
| +} catch (e) { |
| + assertTrue(/Invalid property/.test(e)); |
| +} |
| +assertEquals(2, ctr); |
| +assertEquals(1, ctr2); |
| +assertEquals(1, ctr3); |
| +assertEquals(1, ctr4); |
| + |
| +var ctr7 = 0; |
| + |
| +var metaProps = { |
| + enumerable: { get: function() { |
| + assertEquals(0, ctr7++); |
| + return true; |
| + }}, |
| + configurable: { get: function() { |
| + assertEquals(1, ctr7++); |
| + return true; |
| + }}, |
| + value: { get: function() { |
| + assertEquals(2, ctr7++); |
| + return 4; |
| + }}, |
| + writable: { get: function() { |
| + assertEquals(3, ctr7++); |
| + return true; |
| + }}, |
| + get: { get: function() { |
| + assertEquals(4, ctr7++); |
| + return function() { }; |
| + }}, |
| + set: { get: function() { |
| + assertEquals(5, ctr7++); |
| + return function() { }; |
| + }} |
| +}; |
| + |
| + |
| +// Instead of a plain props object, let's use getters to return its properties. |
| +var magicValueProps = { foo: Object.create(null, { value: { get: valueGet }})}; |
| +var magicGetterProps = { foo: Object.create(null, { get: { get: getterGet }})}; |
| +var magicAmbiguousProps = { foo: Object.create(null, metaProps) }; |
| + |
| +assertEquals(3, Object.create(null, magicValueProps).foo); |
| +assertEquals(1, ctr5); |
| + |
| +assertEquals(1000, Object.create(null, magicGetterProps).foo); |
| +assertEquals(2, ctr5); |
| + |
| +// See if we do the steps in ToPropertyDescriptor in the right order. |
| +// We shouldn't throw the exception for an ambiguous properties object |
| +// before we got all the values out. |
| +try { |
| + Object.create(null, magicAmbiguousProps); |
| + assertTrue(false); |
| +} catch (e) { |
| + assertTrue(/Invalid property/.test(e)); |
| + assertEquals(6, ctr7); |
| +} |
| + |
| +var magicWritableProps = { |
| + foo: Object.create(null, { value: { value: 4 }, |
| + writable: { get: function() { |
| + ctr6++; |
| + return false; |
| + }}})}; |
| + |
| +var fooNotWritable = Object.create(null, magicWritableProps) |
| +assertEquals(1002, ctr6); |
| +assertEquals(4, fooNotWritable.foo); |
| +fooNotWritable.foo = 5; |
| +assertEquals(4, fooNotWritable.foo); |
| + |
| + |
| +// Test enumerable flag. |
| + |
| +var fooNotEnumerable = |
| + Object.create({fizz: 14}, {foo: {value: 3, enumerable: false}, |
| + bar: {value: 4, enumerable: true}, |
| + baz: {value: 5}}); |
| +var sum = 0; |
| +for (x in fooNotEnumerable) { |
| + assertTrue(x === 'bar' || x === 'fizz'); |
| + sum += fooNotEnumerable[x]; |
| +} |
| +assertEquals(18, sum); |
| + |
| + |
| +try { |
| + Object.create(null, {foo: { get: 0 }}); |
| + assertTrue(false); |
| +} catch (e) { |
| + assertTrue(/Getter must be a function/.test(e)); |
| +} |
| + |
| +try { |
| + Object.create(null, {foo: { set: 0 }}); |
| + assertTrue(false); |
| +} catch (e) { |
| + assertTrue(/Setter must be a function/.test(e)); |
| +} |
| + |
| +try { |
| + Object.create(null, {foo: { set: 0, get: 0 }}); |
| + assertTrue(false); |
| +} catch (e) { |
| + assertTrue(/Getter must be a function/.test(e)); |
| +} |
| + |
| + |
| +// Ensure that only enumerable own properties on the descriptor are used. |
| +var tricky = Object.create( |
| + { foo: { value: 1, enumerable: true }}, |
| + { bar: { value: { value: 2, enumerable: true }, enumerable: false }, |
| + baz: { value: { value: 4, enumerable: false }, enumerable: true }, |
| + fizz: { value: { value: 8, enumerable: false }, enumerable: false }, |
| + buzz: { value: { value: 16, enumerable: true }, enumerable: true }}); |
| + |
| +assertEquals(1, tricky.foo.value); |
| +assertEquals(2, tricky.bar.value); |
| +assertEquals(4, tricky.baz.value); |
| +assertEquals(8, tricky.fizz.value); |
| +assertEquals(16, tricky.buzz.value); |
| + |
| +var sonOfTricky = Object.create(null, tricky); |
| + |
| +assertFalse("foo" in sonOfTricky); |
| +assertFalse("bar" in sonOfTricky); |
| +assertTrue("baz" in sonOfTricky); |
| +assertFalse("fizz" in sonOfTricky); |
| +assertTrue("buzz" in sonOfTricky); |
| + |
| +var sum = 0; |
| +for (x in sonOfTricky) { |
| + assertTrue(x === 'buzz'); |
| + sum += sonOfTricky[x]; |
| +} |
| +assertEquals(16, sum); |