diff options
author | Sergio Ahumada <sergio.ahumada@digia.com> | 2013-03-19 09:25:14 +0100 |
---|---|---|
committer | Sergio Ahumada <sergio.ahumada@digia.com> | 2013-03-19 09:56:31 +0100 |
commit | 6313e1fe4c27755adde87e62db1c2f9fac534ae4 (patch) | |
tree | c57bb29f65e02fbfcc07895a8cc2903fff9300ba /src/3rdparty/v8/test/mjsunit/harmony | |
parent | b5a49a260d03249c386f1b63c249089383dd81fa (diff) | |
parent | cac65e7a222b848a735a974b0aeb43209b0cfa18 (diff) |
Merge branch 'dev' into stable
This starts Qt 5.1 release cycle
Change-Id: I892bbc73c276842894a720f761ce31ad1b015672
Diffstat (limited to 'src/3rdparty/v8/test/mjsunit/harmony')
11 files changed, 1194 insertions, 35 deletions
diff --git a/src/3rdparty/v8/test/mjsunit/harmony/block-conflicts.js b/src/3rdparty/v8/test/mjsunit/harmony/block-conflicts.js index 8388504..3aa9d22 100644 --- a/src/3rdparty/v8/test/mjsunit/harmony/block-conflicts.js +++ b/src/3rdparty/v8/test/mjsunit/harmony/block-conflicts.js @@ -35,7 +35,8 @@ function CheckException(e) { var string = e.toString(); assertTrue(string.indexOf("has already been declared") >= 0 || - string.indexOf("redeclaration") >= 0); return 'Conflict'; + string.indexOf("redeclaration") >= 0); + return 'Conflict'; } diff --git a/src/3rdparty/v8/test/mjsunit/harmony/block-let-crankshaft.js b/src/3rdparty/v8/test/mjsunit/harmony/block-let-crankshaft.js index 1db1792..d01e5c0 100644 --- a/src/3rdparty/v8/test/mjsunit/harmony/block-let-crankshaft.js +++ b/src/3rdparty/v8/test/mjsunit/harmony/block-let-crankshaft.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --harmony-scoping --allow-natives-syntax +// Flags: --harmony-scoping --allow-natives-syntax --noparallel-recompilation // TODO(ES6): properly activate extended mode "use strict"; diff --git a/src/3rdparty/v8/test/mjsunit/harmony/collections.js b/src/3rdparty/v8/test/mjsunit/harmony/collections.js index 412e6f1..0219f39 100644 --- a/src/3rdparty/v8/test/mjsunit/harmony/collections.js +++ b/src/3rdparty/v8/test/mjsunit/harmony/collections.js @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 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: @@ -65,9 +65,11 @@ TestInvalidCalls(new WeakMap); // Test expected behavior for Sets function TestSet(set, key) { assertFalse(set.has(key)); - set.add(key); + assertSame(undefined, set.add(key)); assertTrue(set.has(key)); - set.delete(key); + assertTrue(set.delete(key)); + assertFalse(set.has(key)); + assertFalse(set.delete(key)); assertFalse(set.has(key)); } function TestSetBehavior(set) { @@ -87,7 +89,7 @@ TestSetBehavior(new Set); // Test expected mapping behavior for Maps and WeakMaps function TestMapping(map, key, value) { - map.set(key, value); + assertSame(undefined, map.set(key, value)); assertSame(value, map.get(key)); } function TestMapBehavior1(m) { @@ -117,12 +119,12 @@ TestMapBehavior2(new Map); // Test expected querying behavior of Maps and WeakMaps function TestQuery(m) { var key = new Object; - TestMapping(m, key, 'to-be-present'); - assertTrue(m.has(key)); - assertFalse(m.has(new Object)); - TestMapping(m, key, undefined); - assertFalse(m.has(key)); - assertFalse(m.has(new Object)); + var values = [ 'x', 0, +Infinity, -Infinity, true, false, null, undefined ]; + for (var i = 0; i < values.length; i++) { + TestMapping(m, key, values[i]); + assertTrue(m.has(key)); + assertFalse(m.has(new Object)); + } } TestQuery(new Map); TestQuery(new WeakMap); @@ -311,4 +313,60 @@ TestBogusReceivers(bogusReceiversTestSet); // Stress Test // There is a proposed stress-test available at the es-discuss mailing list // which cannot be reasonably automated. Check it out by hand if you like: -// https://mail.mozilla.org/pipermail/es-discuss/2011-May/014096.html
\ No newline at end of file +// https://mail.mozilla.org/pipermail/es-discuss/2011-May/014096.html + + +// Set and Map size getters +var setSizeDescriptor = Object.getOwnPropertyDescriptor(Set.prototype, 'size'); +assertEquals(undefined, setSizeDescriptor.value); +assertEquals(undefined, setSizeDescriptor.set); +assertTrue(setSizeDescriptor.get instanceof Function); +assertEquals(undefined, setSizeDescriptor.get.prototype); +assertFalse(setSizeDescriptor.enumerable); +assertTrue(setSizeDescriptor.configurable); + +var s = new Set(); +assertFalse(s.hasOwnProperty('size')); +for (var i = 0; i < 10; i++) { + assertEquals(i, s.size); + s.add(i); +} +for (var i = 9; i >= 0; i--) { + s.delete(i); + assertEquals(i, s.size); +} + + +var mapSizeDescriptor = Object.getOwnPropertyDescriptor(Map.prototype, 'size'); +assertEquals(undefined, mapSizeDescriptor.value); +assertEquals(undefined, mapSizeDescriptor.set); +assertTrue(mapSizeDescriptor.get instanceof Function); +assertEquals(undefined, mapSizeDescriptor.get.prototype); +assertFalse(mapSizeDescriptor.enumerable); +assertTrue(mapSizeDescriptor.configurable); + +var m = new Map(); +assertFalse(m.hasOwnProperty('size')); +for (var i = 0; i < 10; i++) { + assertEquals(i, m.size); + m.set(i, i); +} +for (var i = 9; i >= 0; i--) { + m.delete(i); + assertEquals(i, m.size); +} + +// Test clear +var a = new Set(); +s.add(42); +assertTrue(s.has(42)); +s.clear(); +assertFalse(s.has(42)); +assertEquals(0, s.size); + +var m = new Map(); +m.set(42, true); +assertTrue(m.has(42)); +m.clear(); +assertFalse(m.has(42)); +assertEquals(0, m.size); diff --git a/src/3rdparty/v8/test/mjsunit/harmony/debug-blockscopes.js b/src/3rdparty/v8/test/mjsunit/harmony/debug-blockscopes.js index 10aac2d..ca2ab9e 100644 --- a/src/3rdparty/v8/test/mjsunit/harmony/debug-blockscopes.js +++ b/src/3rdparty/v8/test/mjsunit/harmony/debug-blockscopes.js @@ -376,7 +376,7 @@ listener_delegate = function(exec_state) { debug.ScopeType.Global], exec_state); CheckScopeContent({x:'y'}, 0, exec_state); // The function scope contains a temporary iteration variable. - CheckScopeContent({x:'y'}, 1, exec_state); + CheckScopeContent({'.for.x':'y'}, 1, exec_state); }; for_loop_1(); EndTest(); @@ -401,7 +401,7 @@ listener_delegate = function(exec_state) { CheckScopeContent({x:3}, 0, exec_state); CheckScopeContent({x:'y'}, 1, exec_state); // The function scope contains a temporary iteration variable. - CheckScopeContent({x:'y'}, 2, exec_state); + CheckScopeContent({'.for.x':'y'}, 2, exec_state); }; for_loop_2(); EndTest(); diff --git a/src/3rdparty/v8/test/mjsunit/harmony/module-linking.js b/src/3rdparty/v8/test/mjsunit/harmony/module-linking.js index 13ca6f7..a4b272f 100644 --- a/src/3rdparty/v8/test/mjsunit/harmony/module-linking.js +++ b/src/3rdparty/v8/test/mjsunit/harmony/module-linking.js @@ -27,10 +27,188 @@ // Flags: --harmony-modules --harmony-scoping -// Test basic module linking. +// Test basic module linking and initialization. "use strict"; +module R { + // At this point, only functions and modules are initialized. + assertEquals(undefined, v) + assertEquals(undefined, vv) + assertEquals(undefined, R.v) + assertEquals(undefined, M.v) + assertEquals(undefined, MM.v) + assertEquals(undefined, F.v) + assertEquals(undefined, G.v) + assertThrows(function() { l }, ReferenceError) + assertThrows(function() { ll }, ReferenceError) + assertThrows(function() { R.l }, ReferenceError) + assertThrows(function() { M.l }, ReferenceError) + assertThrows(function() { MM.l }, ReferenceError) + assertThrows(function() { F.l }, ReferenceError) + assertThrows(function() { G.l }, ReferenceError) + assertThrows(function() { c }, ReferenceError) + assertThrows(function() { cc }, ReferenceError) + assertThrows(function() { R.c }, ReferenceError) + assertThrows(function() { M.c }, ReferenceError) + assertThrows(function() { MM.c }, ReferenceError) + assertThrows(function() { F.c }, ReferenceError) + assertThrows(function() { G.c }, ReferenceError) + assertEquals(4, f()) + assertEquals(24, ff()) + assertEquals(4, R.f()) + assertEquals(14, M.f()) + assertEquals(34, MM.f()) + assertEquals(44, F.f()) + assertEquals(14, G.f()) + + // All properties should already exist on the instance objects, though. + assertTrue("v" in R) + assertTrue("v" in RR) + assertTrue("v" in M) + assertTrue("v" in MM) + assertTrue("v" in F) + assertTrue("v" in G) + assertTrue("l" in R) + assertTrue("l" in RR) + assertTrue("l" in M) + assertTrue("l" in MM) + assertTrue("l" in F) + assertTrue("l" in G) + assertTrue("c" in R) + assertTrue("c" in RR) + assertTrue("c" in M) + assertTrue("c" in MM) + assertTrue("c" in F) + assertTrue("c" in G) + assertTrue("f" in R) + assertTrue("f" in RR) + assertTrue("f" in M) + assertTrue("f" in MM) + assertTrue("f" in F) + assertTrue("f" in G) + assertTrue("M" in R) + assertTrue("M" in RR) + assertTrue("RR" in R) + assertTrue("RR" in RR) + + // And aliases should be identical. + assertSame(R, RR) + assertSame(R, R.RR) + assertSame(M, R.M) + assertSame(M, G) + + // We can only assign to var. + assertEquals(-1, v = -1) + assertEquals(-2, R.v = -2) + assertEquals(-2, v) + assertEquals(-2, R.v) + + assertThrows(function() { l = -1 }, ReferenceError) + assertThrows(function() { R.l = -2 }, ReferenceError) + assertThrows(function() { l }, ReferenceError) + assertThrows(function() { R.l }, ReferenceError) + + assertThrows(function() { eval("c = -1") }, SyntaxError) + assertThrows(function() { R.c = -2 }, TypeError) + + // Initialize first bunch or variables. + export var v = 1 + export let l = 2 + export const c = 3 + export function f() { return 4 } + + assertEquals(1, v) + assertEquals(1, R.v) + assertEquals(2, l) + assertEquals(2, R.l) + assertEquals(3, c) + assertEquals(3, R.c) + + assertEquals(-3, v = -3) + assertEquals(-4, R.v = -4) + assertEquals(-3, l = -3) + assertEquals(-4, R.l = -4) + assertThrows(function() { eval("c = -3") }, SyntaxError) + assertThrows(function() { R.c = -4 }, TypeError) + + assertEquals(-4, v) + assertEquals(-4, R.v) + assertEquals(-4, l) + assertEquals(-4, R.l) + assertEquals(3, c) + assertEquals(3, R.c) + + // Initialize nested module. + export module M { + export var v = 11 + export let l = 12 + export const c = 13 + export function f() { return 14 } + } + + assertEquals(11, M.v) + assertEquals(11, G.v) + assertEquals(12, M.l) + assertEquals(12, G.l) + assertEquals(13, M.c) + assertEquals(13, G.c) + + // Initialize non-exported variables. + var vv = 21 + let ll = 22 + const cc = 23 + function ff() { return 24 } + + assertEquals(21, vv) + assertEquals(22, ll) + assertEquals(23, cc) + + // Initialize non-exported module. + module MM { + export var v = 31 + export let l = 32 + export const c = 33 + export function f() { return 34 } + } + + assertEquals(31, MM.v) + assertEquals(32, MM.l) + assertEquals(33, MM.c) + + // Recursive self reference. + export module RR = R +} + +// Initialize sibling module that was forward-used. +module F { + assertEquals(undefined, v) + assertEquals(undefined, F.v) + assertThrows(function() { l }, ReferenceError) + assertThrows(function() { F.l }, ReferenceError) + assertThrows(function() { c }, ReferenceError) + assertThrows(function() { F.c }, ReferenceError) + + export var v = 41 + export let l = 42 + export const c = 43 + export function f() { return 44 } + + assertEquals(41, v) + assertEquals(41, F.v) + assertEquals(42, l) + assertEquals(42, F.l) + assertEquals(43, c) + assertEquals(43, F.c) +} + +// Define recursive module alias. +module G = R.M + + + +// Second test with side effects and more module nesting. + let log = ""; export let x = (log += "1"); @@ -117,5 +295,4 @@ assertSame(M2, M1.A2); assertSame(M1, M1.A2.A1); assertSame(M2, M2.A1.A2); -// TODO(rossberg): inner declarations are not executed yet. -// assertEquals("1234567890", log); +assertEquals("1234567890", log); diff --git a/src/3rdparty/v8/test/mjsunit/harmony/module-parsing.js b/src/3rdparty/v8/test/mjsunit/harmony/module-parsing.js index cdd0a2e..8a9103d 100644 --- a/src/3rdparty/v8/test/mjsunit/harmony/module-parsing.js +++ b/src/3rdparty/v8/test/mjsunit/harmony/module-parsing.js @@ -116,6 +116,11 @@ x , y +var +x +, +y + export var v1 = 1 @@ -157,3 +162,29 @@ try {} catch (module) {} module v = 20 + + + +// Check that module declarations are rejected in eval or local scope. + +module M { export let x; } + +assertThrows("export x;", SyntaxError); // It's using eval, so should throw. +assertThrows("export let x;", SyntaxError); +assertThrows("import x from M;", SyntaxError); +assertThrows("module M {};", SyntaxError); + +assertThrows("{ export x; }", SyntaxError); +assertThrows("{ export let x; }", SyntaxError); +assertThrows("{ import x from M; }", SyntaxError); +assertThrows("{ module M {}; }", SyntaxError); + +assertThrows("function f() { export x; }", SyntaxError); +assertThrows("function f() { export let x; }", SyntaxError); +assertThrows("function f() { import x from M; }", SyntaxError); +assertThrows("function f() { module M {}; }", SyntaxError); + +assertThrows("function f() { { export x; } }", SyntaxError); +assertThrows("function f() { { export let x; } }", SyntaxError); +assertThrows("function f() { { import x from M; } }", SyntaxError); +assertThrows("function f() { { module M {}; } }", SyntaxError); diff --git a/src/3rdparty/v8/test/mjsunit/harmony/module-recompile.js b/src/3rdparty/v8/test/mjsunit/harmony/module-recompile.js new file mode 100644 index 0000000..23f5bfc --- /dev/null +++ b/src/3rdparty/v8/test/mjsunit/harmony/module-recompile.js @@ -0,0 +1,87 @@ +// Copyright 2012 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. + +// Flags: --harmony-modules + +// Test that potential recompilation of the global scope does not screw up. + +"use strict"; + +var N = 1e5; // Number of loop iterations that trigger optimization. + +module A { + export var x = 1 + export function f() { return x } +} +var f = A.f + +assertEquals(1, A.x) +assertEquals(1, A.f()) +assertEquals(1, f()) + +A.x = 2 + +assertEquals(2, A.x) +assertEquals(2, A.f()) +assertEquals(2, f()) + +for (var i = 0; i < N; i++) { + if (i > N) print("impossible"); +} + +assertEquals(2, A.x) +assertEquals(2, A.f()) +assertEquals(2, f()) + + +// Same test with loop inside a module. + +module B { + module A { + export var x = 1 + export function f() { return x } + } + var f = A.f + + assertEquals(1, A.x) + assertEquals(1, A.f()) + assertEquals(1, f()) + + A.x = 2 + + assertEquals(2, A.x) + assertEquals(2, A.f()) + assertEquals(2, f()) + + for (var i = 0; i < N; i++) { + if (i > N) print("impossible"); + } + + assertEquals(2, A.x) + assertEquals(2, A.f()) + assertEquals(2, f()) +} diff --git a/src/3rdparty/v8/test/mjsunit/harmony/module-resolution.js b/src/3rdparty/v8/test/mjsunit/harmony/module-resolution.js index a1b9917..1a95347 100644 --- a/src/3rdparty/v8/test/mjsunit/harmony/module-resolution.js +++ b/src/3rdparty/v8/test/mjsunit/harmony/module-resolution.js @@ -33,6 +33,7 @@ print("begin.") + export let x = print("0") export module B = A.B @@ -44,15 +45,25 @@ export module A { module BB = B export BB, x let x = print("2") - let y = print("3") + var y = print("3") let Ax = A.x + try { A.y } catch (e) {} // throws + let Az = A.z // undefined + let Az2 = z // undefined + A.g() // hoisted + g() // hoisted let ABx = A.B.x - let Ay = A.y + let ABy = A.B.y + let Bx = B.x + let By = B.y let BBx = BB.x + let BBy = BB.y let Af = A.f function f(x,y) { return x } } export let y = print("4") + export var z = print("4.1") + export function g() {} let Ax = A.x let Bx = B.x let ABx = A.B.x @@ -92,6 +103,8 @@ export module E { let Bx = B.x // TODO(rossberg): Handle import *. // import A.* + module B = A.B + let y = A.y } export module M1 { diff --git a/src/3rdparty/v8/test/mjsunit/harmony/object-observe.js b/src/3rdparty/v8/test/mjsunit/harmony/object-observe.js new file mode 100644 index 0000000..945841b --- /dev/null +++ b/src/3rdparty/v8/test/mjsunit/harmony/object-observe.js @@ -0,0 +1,591 @@ +// Copyright 2012 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. + +// Flags: --harmony-observation + +var allObservers = []; +function reset() { + allObservers.forEach(function(observer) { observer.reset(); }); +} + +function createObserver() { + "use strict"; // So that |this| in callback can be undefined. + + var observer = { + records: undefined, + callbackCount: 0, + reset: function() { + this.records = undefined; + this.callbackCount = 0; + }, + assertNotCalled: function() { + assertEquals(undefined, this.records); + assertEquals(0, this.callbackCount); + }, + assertCalled: function() { + assertEquals(1, this.callbackCount); + }, + assertRecordCount: function(count) { + this.assertCalled(); + assertEquals(count, this.records.length); + }, + assertCallbackRecords: function(recs) { + this.assertRecordCount(recs.length); + for (var i = 0; i < recs.length; i++) { + assertSame(this.records[i].object, recs[i].object); + assertEquals('string', typeof recs[i].type); + assertPropertiesEqual(this.records[i], recs[i]); + } + } + }; + + observer.callback = function(r) { + assertEquals(undefined, this); + assertEquals('object', typeof r); + assertTrue(r instanceof Array) + observer.records = r; + observer.callbackCount++; + }; + + observer.reset(); + allObservers.push(observer); + return observer; +} + +var observer = createObserver(); +assertEquals("function", typeof observer.callback); +var obj = {}; + +function frozenFunction() {} +Object.freeze(frozenFunction); +var nonFunction = {}; +var changeRecordWithAccessor = { type: 'foo' }; +var recordCreated = false; +Object.defineProperty(changeRecordWithAccessor, 'name', { + get: function() { + recordCreated = true; + return "bar"; + }, + enumerable: true +}) + +// Object.observe +assertThrows(function() { Object.observe("non-object", observer.callback); }, TypeError); +assertThrows(function() { Object.observe(obj, nonFunction); }, TypeError); +assertThrows(function() { Object.observe(obj, frozenFunction); }, TypeError); + +// Object.unobserve +assertThrows(function() { Object.unobserve(4, observer.callback); }, TypeError); + +// Object.getNotifier +var notifier = Object.getNotifier(obj); +assertSame(notifier, Object.getNotifier(obj)); +assertEquals(null, Object.getNotifier(Object.freeze({}))); +assertFalse(notifier.hasOwnProperty('notify')); +assertEquals([], Object.keys(notifier)); +var notifyDesc = Object.getOwnPropertyDescriptor(notifier.__proto__, 'notify'); +assertTrue(notifyDesc.configurable); +assertTrue(notifyDesc.writable); +assertFalse(notifyDesc.enumerable); +assertThrows(function() { notifier.notify({}); }, TypeError); +assertThrows(function() { notifier.notify({ type: 4 }); }, TypeError); +var notify = notifier.notify; +assertThrows(function() { notify.call(undefined, { type: 'a' }); }, TypeError); +assertThrows(function() { notify.call(null, { type: 'a' }); }, TypeError); +assertThrows(function() { notify.call(5, { type: 'a' }); }, TypeError); +assertThrows(function() { notify.call('hello', { type: 'a' }); }, TypeError); +assertThrows(function() { notify.call(false, { type: 'a' }); }, TypeError); +assertThrows(function() { notify.call({}, { type: 'a' }); }, TypeError); +assertFalse(recordCreated); +notifier.notify(changeRecordWithAccessor); +assertFalse(recordCreated); // not observed yet + +// Object.deliverChangeRecords +assertThrows(function() { Object.deliverChangeRecords(nonFunction); }, TypeError); + +// Multiple records are delivered. +Object.observe(obj, observer.callback); +notifier.notify({ + type: 'updated', + name: 'foo', + expando: 1 +}); + +notifier.notify({ + object: notifier, // object property is ignored + type: 'deleted', + name: 'bar', + expando2: 'str' +}); +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: obj, name: 'foo', type: 'updated', expando: 1 }, + { object: obj, name: 'bar', type: 'deleted', expando2: 'str' } +]); + +// No delivery takes place if no records are pending +reset(); +Object.deliverChangeRecords(observer.callback); +observer.assertNotCalled(); + +// Multiple observation has no effect. +reset(); +Object.observe(obj, observer.callback); +Object.observe(obj, observer.callback); +Object.getNotifier(obj).notify({ + type: 'foo', +}); +Object.deliverChangeRecords(observer.callback); +observer.assertCalled(); + +// Observation can be stopped. +reset(); +Object.unobserve(obj, observer.callback); +Object.getNotifier(obj).notify({ + type: 'foo', +}); +Object.deliverChangeRecords(observer.callback); +observer.assertNotCalled(); + +// Multiple unobservation has no effect +reset(); +Object.unobserve(obj, observer.callback); +Object.unobserve(obj, observer.callback); +Object.getNotifier(obj).notify({ + type: 'foo', +}); +Object.deliverChangeRecords(observer.callback); +observer.assertNotCalled(); + +// Re-observation works and only includes changeRecords after of call. +reset(); +Object.getNotifier(obj).notify({ + type: 'foo', +}); +Object.observe(obj, observer.callback); +Object.getNotifier(obj).notify({ + type: 'foo', +}); +records = undefined; +Object.deliverChangeRecords(observer.callback); +observer.assertRecordCount(1); + +// Observing a continuous stream of changes, while itermittantly unobserving. +reset(); +Object.observe(obj, observer.callback); +Object.getNotifier(obj).notify({ + type: 'foo', + val: 1 +}); + +Object.unobserve(obj, observer.callback); +Object.getNotifier(obj).notify({ + type: 'foo', + val: 2 +}); + +Object.observe(obj, observer.callback); +Object.getNotifier(obj).notify({ + type: 'foo', + val: 3 +}); + +Object.unobserve(obj, observer.callback); +Object.getNotifier(obj).notify({ + type: 'foo', + val: 4 +}); + +Object.observe(obj, observer.callback); +Object.getNotifier(obj).notify({ + type: 'foo', + val: 5 +}); + +Object.unobserve(obj, observer.callback); +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: obj, type: 'foo', val: 1 }, + { object: obj, type: 'foo', val: 3 }, + { object: obj, type: 'foo', val: 5 } +]); + +// Observing multiple objects; records appear in order. +reset(); +var obj2 = {}; +var obj3 = {} +Object.observe(obj, observer.callback); +Object.observe(obj3, observer.callback); +Object.observe(obj2, observer.callback); +Object.getNotifier(obj).notify({ + type: 'foo1', +}); +Object.getNotifier(obj2).notify({ + type: 'foo2', +}); +Object.getNotifier(obj3).notify({ + type: 'foo3', +}); +Object.observe(obj3, observer.callback); +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: obj, type: 'foo1' }, + { object: obj2, type: 'foo2' }, + { object: obj3, type: 'foo3' } +]); + +// Observing named properties. +reset(); +var obj = {a: 1} +Object.observe(obj, observer.callback); +obj.a = 2; +obj["a"] = 3; +delete obj.a; +obj.a = 4; +obj.a = 4; // ignored +obj.a = 5; +Object.defineProperty(obj, "a", {value: 6}); +Object.defineProperty(obj, "a", {writable: false}); +obj.a = 7; // ignored +Object.defineProperty(obj, "a", {value: 8}); +Object.defineProperty(obj, "a", {value: 7, writable: true}); +Object.defineProperty(obj, "a", {get: function() {}}); +Object.defineProperty(obj, "a", {get: function() {}}); +delete obj.a; +delete obj.a; +Object.defineProperty(obj, "a", {get: function() {}, configurable: true}); +Object.defineProperty(obj, "a", {value: 9, writable: true}); +obj.a = 10; +delete obj.a; +Object.defineProperty(obj, "a", {value: 11, configurable: true}); +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: obj, name: "a", type: "updated", oldValue: 1 }, + { object: obj, name: "a", type: "updated", oldValue: 2 }, + { object: obj, name: "a", type: "deleted", oldValue: 3 }, + { object: obj, name: "a", type: "new" }, + { object: obj, name: "a", type: "updated", oldValue: 4 }, + { object: obj, name: "a", type: "updated", oldValue: 5 }, + { object: obj, name: "a", type: "reconfigured", oldValue: 6 }, + { object: obj, name: "a", type: "updated", oldValue: 6 }, + { object: obj, name: "a", type: "reconfigured", oldValue: 8 }, + { object: obj, name: "a", type: "reconfigured", oldValue: 7 }, + { object: obj, name: "a", type: "reconfigured" }, + { object: obj, name: "a", type: "deleted" }, + { object: obj, name: "a", type: "new" }, + { object: obj, name: "a", type: "reconfigured" }, + { object: obj, name: "a", type: "updated", oldValue: 9 }, + { object: obj, name: "a", type: "deleted", oldValue: 10 }, + { object: obj, name: "a", type: "new" }, +]); + +// Observing indexed properties. +reset(); +var obj = {'1': 1} +Object.observe(obj, observer.callback); +obj[1] = 2; +obj[1] = 3; +delete obj[1]; +obj[1] = 4; +obj[1] = 4; // ignored +obj[1] = 5; +Object.defineProperty(obj, "1", {value: 6}); +Object.defineProperty(obj, "1", {writable: false}); +obj[1] = 7; // ignored +Object.defineProperty(obj, "1", {value: 8}); +Object.defineProperty(obj, "1", {value: 7, writable: true}); +Object.defineProperty(obj, "1", {get: function() {}}); +delete obj[1]; +delete obj[1]; +Object.defineProperty(obj, "1", {get: function() {}, configurable: true}); +Object.defineProperty(obj, "1", {value: 9, writable: true}); +obj[1] = 10; +delete obj[1]; +Object.defineProperty(obj, "1", {value: 11, configurable: true}); +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: obj, name: "1", type: "updated", oldValue: 1 }, + { object: obj, name: "1", type: "updated", oldValue: 2 }, + { object: obj, name: "1", type: "deleted", oldValue: 3 }, + { object: obj, name: "1", type: "new" }, + { object: obj, name: "1", type: "updated", oldValue: 4 }, + { object: obj, name: "1", type: "updated", oldValue: 5 }, + { object: obj, name: "1", type: "reconfigured", oldValue: 6 }, + { object: obj, name: "1", type: "updated", oldValue: 6 }, + { object: obj, name: "1", type: "reconfigured", oldValue: 8 }, + { object: obj, name: "1", type: "reconfigured", oldValue: 7 }, + // TODO(observe): oldValue should not be present below. + { object: obj, name: "1", type: "deleted", oldValue: undefined }, + { object: obj, name: "1", type: "new" }, + // TODO(observe): oldValue should be absent below, and type = "reconfigured". + { object: obj, name: "1", type: "updated", oldValue: undefined }, + { object: obj, name: "1", type: "updated", oldValue: 9 }, + { object: obj, name: "1", type: "deleted", oldValue: 10 }, + { object: obj, name: "1", type: "new" }, +]); + +// Observing array length (including truncation) +reset(); +var arr = ['a', 'b', 'c', 'd']; +var arr2 = ['alpha', 'beta']; +var arr3 = ['hello']; +arr3[2] = 'goodbye'; +arr3.length = 6; +// TODO(adamk): Enable this test case when it can run in a reasonable +// amount of time. +//var slow_arr = new Array(1000000000); +//slow_arr[500000000] = 'hello'; +Object.defineProperty(arr, '0', {configurable: false}); +Object.defineProperty(arr, '2', {get: function(){}}); +Object.defineProperty(arr2, '0', {get: function(){}, configurable: false}); +Object.observe(arr, observer.callback); +Object.observe(arr2, observer.callback); +Object.observe(arr3, observer.callback); +arr.length = 2; +arr.length = 0; +arr.length = 10; +arr2.length = 0; +arr2.length = 1; // no change expected +arr3.length = 0; +Object.defineProperty(arr3, 'length', {value: 5}); +Object.defineProperty(arr3, 'length', {value: 10, writable: false}); +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: arr, name: '3', type: 'deleted', oldValue: 'd' }, + // TODO(adamk): oldValue should not be present below + { object: arr, name: '2', type: 'deleted', oldValue: undefined }, + { object: arr, name: 'length', type: 'updated', oldValue: 4 }, + { object: arr, name: '1', type: 'deleted', oldValue: 'b' }, + { object: arr, name: 'length', type: 'updated', oldValue: 2 }, + { object: arr, name: 'length', type: 'updated', oldValue: 1 }, + { object: arr2, name: '1', type: 'deleted', oldValue: 'beta' }, + { object: arr2, name: 'length', type: 'updated', oldValue: 2 }, + { object: arr3, name: '2', type: 'deleted', oldValue: 'goodbye' }, + { object: arr3, name: '0', type: 'deleted', oldValue: 'hello' }, + { object: arr3, name: 'length', type: 'updated', oldValue: 6 }, + { object: arr3, name: 'length', type: 'updated', oldValue: 0 }, + { object: arr3, name: 'length', type: 'updated', oldValue: 5 }, + // TODO(adamk): This record should be merged with the above + { object: arr3, name: 'length', type: 'reconfigured' }, +]); + +// Assignments in loops (checking different IC states). +reset(); +var obj = {}; +Object.observe(obj, observer.callback); +for (var i = 0; i < 5; i++) { + obj["a" + i] = i; +} +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: obj, name: "a0", type: "new" }, + { object: obj, name: "a1", type: "new" }, + { object: obj, name: "a2", type: "new" }, + { object: obj, name: "a3", type: "new" }, + { object: obj, name: "a4", type: "new" }, +]); + +reset(); +var obj = {}; +Object.observe(obj, observer.callback); +for (var i = 0; i < 5; i++) { + obj[i] = i; +} +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: obj, name: "0", type: "new" }, + { object: obj, name: "1", type: "new" }, + { object: obj, name: "2", type: "new" }, + { object: obj, name: "3", type: "new" }, + { object: obj, name: "4", type: "new" }, +]); + +// Adding elements past the end of an array should notify on length +reset(); +var arr = [1, 2, 3]; +Object.observe(arr, observer.callback); +arr[3] = 10; +arr[100] = 20; +Object.defineProperty(arr, '200', {value: 7}); +Object.defineProperty(arr, '400', {get: function(){}}); +arr[50] = 30; // no length change expected +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: arr, name: '3', type: 'new' }, + { object: arr, name: 'length', type: 'updated', oldValue: 3 }, + { object: arr, name: '100', type: 'new' }, + { object: arr, name: 'length', type: 'updated', oldValue: 4 }, + { object: arr, name: '200', type: 'new' }, + { object: arr, name: 'length', type: 'updated', oldValue: 101 }, + { object: arr, name: '400', type: 'new' }, + { object: arr, name: 'length', type: 'updated', oldValue: 201 }, + { object: arr, name: '50', type: 'new' }, +]); + +// Tests for array methods, first on arrays and then on plain objects +// +// === ARRAYS === +// +// Push +reset(); +var array = [1, 2]; +Object.observe(array, observer.callback); +array.push(3, 4); +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: array, name: '2', type: 'new' }, + { object: array, name: 'length', type: 'updated', oldValue: 2 }, + { object: array, name: '3', type: 'new' }, + { object: array, name: 'length', type: 'updated', oldValue: 3 }, +]); + +// Pop +reset(); +var array = [1, 2]; +Object.observe(array, observer.callback); +array.pop(); +array.pop(); +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: array, name: '1', type: 'deleted', oldValue: 2 }, + { object: array, name: 'length', type: 'updated', oldValue: 2 }, + { object: array, name: '0', type: 'deleted', oldValue: 1 }, + { object: array, name: 'length', type: 'updated', oldValue: 1 }, +]); + +// Shift +reset(); +var array = [1, 2]; +Object.observe(array, observer.callback); +array.shift(); +array.shift(); +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: array, name: '0', type: 'updated', oldValue: 1 }, + { object: array, name: '1', type: 'deleted', oldValue: 2 }, + { object: array, name: 'length', type: 'updated', oldValue: 2 }, + { object: array, name: '0', type: 'deleted', oldValue: 2 }, + { object: array, name: 'length', type: 'updated', oldValue: 1 }, +]); + +// Unshift +reset(); +var array = [1, 2]; +Object.observe(array, observer.callback); +array.unshift(3, 4); +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: array, name: '3', type: 'new' }, + { object: array, name: 'length', type: 'updated', oldValue: 2 }, + { object: array, name: '2', type: 'new' }, + { object: array, name: '0', type: 'updated', oldValue: 1 }, + { object: array, name: '1', type: 'updated', oldValue: 2 }, +]); + +// Splice +reset(); +var array = [1, 2, 3]; +Object.observe(array, observer.callback); +array.splice(1, 1, 4, 5); +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: array, name: '3', type: 'new' }, + { object: array, name: 'length', type: 'updated', oldValue: 3 }, + { object: array, name: '1', type: 'updated', oldValue: 2 }, + { object: array, name: '2', type: 'updated', oldValue: 3 }, +]); + +// +// === PLAIN OBJECTS === +// +// Push +reset() +var array = {0: 1, 1: 2, length: 2} +Object.observe(array, observer.callback); +Array.prototype.push.call(array, 3, 4); +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: array, name: '2', type: 'new' }, + { object: array, name: '3', type: 'new' }, + { object: array, name: 'length', type: 'updated', oldValue: 2 }, +]); + +// Pop +reset() +var array = {0: 1, 1: 2, length: 2}; +Object.observe(array, observer.callback); +Array.prototype.pop.call(array); +Array.prototype.pop.call(array); +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: array, name: '1', type: 'deleted', oldValue: 2 }, + { object: array, name: 'length', type: 'updated', oldValue: 2 }, + { object: array, name: '0', type: 'deleted', oldValue: 1 }, + { object: array, name: 'length', type: 'updated', oldValue: 1 }, +]); + +// Shift +reset() +var array = {0: 1, 1: 2, length: 2}; +Object.observe(array, observer.callback); +Array.prototype.shift.call(array); +Array.prototype.shift.call(array); +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: array, name: '0', type: 'updated', oldValue: 1 }, + { object: array, name: '1', type: 'deleted', oldValue: 2 }, + { object: array, name: 'length', type: 'updated', oldValue: 2 }, + { object: array, name: '0', type: 'deleted', oldValue: 2 }, + { object: array, name: 'length', type: 'updated', oldValue: 1 }, +]); + +// Unshift +reset() +var array = {0: 1, 1: 2, length: 2}; +Object.observe(array, observer.callback); +Array.prototype.unshift.call(array, 3, 4); +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: array, name: '3', type: 'new' }, + { object: array, name: '2', type: 'new' }, + { object: array, name: '0', type: 'updated', oldValue: 1 }, + { object: array, name: '1', type: 'updated', oldValue: 2 }, + { object: array, name: 'length', type: 'updated', oldValue: 2 }, +]); + +// Splice +reset() +var array = {0: 1, 1: 2, 2: 3, length: 3}; +Object.observe(array, observer.callback); +Array.prototype.splice.call(array, 1, 1, 4, 5); +Object.deliverChangeRecords(observer.callback); +observer.assertCallbackRecords([ + { object: array, name: '3', type: 'new' }, + { object: array, name: '1', type: 'updated', oldValue: 2 }, + { object: array, name: '2', type: 'updated', oldValue: 3 }, + { object: array, name: 'length', type: 'updated', oldValue: 3 }, +]); diff --git a/src/3rdparty/v8/test/mjsunit/harmony/proxies-json.js b/src/3rdparty/v8/test/mjsunit/harmony/proxies-json.js new file mode 100644 index 0000000..539c5a8 --- /dev/null +++ b/src/3rdparty/v8/test/mjsunit/harmony/proxies-json.js @@ -0,0 +1,178 @@ +// Copyright 2012 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. + +// Flags: --harmony + +function testStringify(expected, object) { + // Test fast case that bails out to slow case. + assertEquals(expected, JSON.stringify(object)); + // Test slow case. + assertEquals(expected, JSON.stringify(object, undefined, 0)); +} + +// Test serializing a proxy, function proxy and objects that contain them. +var handler1 = { + get: function(target, name) { + return name.toUpperCase(); + }, + enumerate: function(target) { + return ['a', 'b', 'c']; + }, + getOwnPropertyDescriptor: function(target, name) { + return { enumerable: true }; + } +} + +var proxy1 = Proxy.create(handler1); +testStringify('{"a":"A","b":"B","c":"C"}', proxy1); + +var proxy_fun = Proxy.createFunction(handler1, function() { return 1; }); +testStringify(undefined, proxy_fun); +testStringify('[1,null]', [1, proxy_fun]); + +var parent1a = { b: proxy1 }; +testStringify('{"b":{"a":"A","b":"B","c":"C"}}', parent1a); + +var parent1b = { a: 123, b: proxy1, c: true }; +testStringify('{"a":123,"b":{"a":"A","b":"B","c":"C"},"c":true}', parent1b); + +var parent1c = [123, proxy1, true]; +testStringify('[123,{"a":"A","b":"B","c":"C"},true]', parent1c); + +// Proxy with side effect. +var handler2 = { + get: function(target, name) { + delete parent2.c; + return name.toUpperCase(); + }, + enumerate: function(target) { + return ['a', 'b', 'c']; + }, + getOwnPropertyDescriptor: function(target, name) { + return { enumerable: true }; + } +} + +var proxy2 = Proxy.create(handler2); +var parent2 = { a: "delete", b: proxy2, c: "remove" }; +var expected2 = '{"a":"delete","b":{"a":"A","b":"B","c":"C"}}'; +assertEquals(expected2, JSON.stringify(parent2)); +parent2.c = "remove"; // Revert side effect. +assertEquals(expected2, JSON.stringify(parent2, undefined, 0)); + +// Proxy with a get function that uses the first argument. +var handler3 = { + get: function(target, name) { + if (name == 'valueOf') return function() { return "proxy" }; + return name + "(" + target + ")"; + }, + enumerate: function(target) { + return ['a', 'b', 'c']; + }, + getOwnPropertyDescriptor: function(target, name) { + return { enumerable: true }; + } +} + +var proxy3 = Proxy.create(handler3); +var parent3 = { x: 123, y: proxy3 } +testStringify('{"x":123,"y":{"a":"a(proxy)","b":"b(proxy)","c":"c(proxy)"}}', + parent3); + +// Empty proxy. +var handler4 = { + get: function(target, name) { + return 0; + }, + enumerate: function(target) { + return []; + }, + getOwnPropertyDescriptor: function(target, name) { + return { enumerable: false }; + } +} + +var proxy4 = Proxy.create(handler4); +testStringify('{}', proxy4); +testStringify('{"a":{}}', { a: proxy4 }); + +// Proxy that provides a toJSON function that uses this. +var handler5 = { + get: function(target, name) { + if (name == 'z') return 97000; + return function(key) { return key.charCodeAt(0) + this.z; }; + }, + enumerate: function(target) { + return ['toJSON', 'z']; + }, + getOwnPropertyDescriptor: function(target, name) { + return { enumerable: true }; + } +} + +var proxy5 = Proxy.create(handler5); +testStringify('{"a":97097}', { a: proxy5 }); + +// Proxy that provides a toJSON function that returns undefined. +var handler6 = { + get: function(target, name) { + return function(key) { return undefined; }; + }, + enumerate: function(target) { + return ['toJSON']; + }, + getOwnPropertyDescriptor: function(target, name) { + return { enumerable: true }; + } +} + +var proxy6 = Proxy.create(handler6); +testStringify('[1,null,true]', [1, proxy6, true]); +testStringify('{"a":1,"c":true}', {a: 1, b: proxy6, c: true}); + +// Object containing a proxy that changes the parent's properties. +var handler7 = { + get: function(target, name) { + delete parent7.a; + delete parent7.c; + parent7.e = "5"; + return name.toUpperCase(); + }, + enumerate: function(target) { + return ['a', 'b', 'c']; + }, + getOwnPropertyDescriptor: function(target, name) { + return { enumerable: true }; + } +} + +var proxy7 = Proxy.create(handler7); +var parent7 = { a: "1", b: proxy7, c: "3", d: "4" }; +assertEquals('{"a":"1","b":{"a":"A","b":"B","c":"C"},"d":"4"}', + JSON.stringify(parent7)); +assertEquals('{"b":{"a":"A","b":"B","c":"C"},"d":"4","e":"5"}', + JSON.stringify(parent7)); diff --git a/src/3rdparty/v8/test/mjsunit/harmony/proxies.js b/src/3rdparty/v8/test/mjsunit/harmony/proxies.js index 8d8f839..04fc769 100644 --- a/src/3rdparty/v8/test/mjsunit/harmony/proxies.js +++ b/src/3rdparty/v8/test/mjsunit/harmony/proxies.js @@ -572,15 +572,16 @@ TestSetThrow(Proxy.create({ })) +var rec var key var val -function TestSetForDerived(handler) { - TestWithProxies(TestSetForDerived2, handler) +function TestSetForDerived(trap) { + TestWithProxies(TestSetForDerived2, trap) } -function TestSetForDerived2(create, handler) { - var p = create(handler) +function TestSetForDerived2(create, trap) { + var p = create({getPropertyDescriptor: trap, getOwnPropertyDescriptor: trap}) var o = Object.create(p, {x: {value: 88, writable: true}, '1': {value: 89, writable: true}}) @@ -607,10 +608,16 @@ function TestSetForDerived2(create, handler) { assertEquals(45, o.p_nonwritable = 45) assertEquals("p_nonwritable", key) - assertEquals(45, o.p_nonwritable) + assertFalse(Object.prototype.hasOwnProperty.call(o, "p_nonwritable")) + + assertThrows(function(){ "use strict"; o.p_nonwritable = 45 }, TypeError) + assertEquals("p_nonwritable", key) + assertFalse(Object.prototype.hasOwnProperty.call(o, "p_nonwritable")) + val = "" assertEquals(46, o.p_setter = 46) assertEquals("p_setter", key) + assertSame(o, rec) assertEquals(46, val) // written to parent assertFalse(Object.prototype.hasOwnProperty.call(o, "p_setter")) @@ -624,32 +631,48 @@ function TestSetForDerived2(create, handler) { assertThrows(function(){ "use strict"; o.p_nosetter = 50 }, TypeError) assertEquals("p_nosetter", key) assertEquals("", val) // not written at all + assertFalse(Object.prototype.hasOwnProperty.call(o, "p_nosetter")); assertThrows(function(){ o.p_nonconf = 53 }, TypeError) assertEquals("p_nonconf", key) + assertFalse(Object.prototype.hasOwnProperty.call(o, "p_nonconf")); assertThrows(function(){ o.p_throw = 51 }, "myexn") assertEquals("p_throw", key) + assertFalse(Object.prototype.hasOwnProperty.call(o, "p_throw")); assertThrows(function(){ o.p_setterthrow = 52 }, "myexn") assertEquals("p_setterthrow", key) + assertFalse(Object.prototype.hasOwnProperty.call(o, "p_setterthrow")); } -TestSetForDerived({ - getPropertyDescriptor: function(k) { + +TestSetForDerived( + function(k) { + // TODO(yangguo): issue 2398 - throwing an error causes formatting of + // the message string, which can be observable through this handler. + // We ignore keys that occur when formatting the message string. + if (k == "toString" || k == "valueOf") return; + key = k; switch (k) { case "p_writable": return {writable: true, configurable: true} case "p_nonwritable": return {writable: false, configurable: true} - case "p_setter":return {set: function(x) { val = x }, configurable: true} - case "p_nosetter": return {get: function() { return 1 }, configurable: true} - case "p_nonconf":return {} + case "p_setter": return { + set: function(x) { rec = this; val = x }, + configurable: true + } + case "p_nosetter": return { + get: function() { return 1 }, + configurable: true + } + case "p_nonconf": return {} case "p_throw": throw "myexn" case "p_setterthrow": return {set: function(x) { throw "myexn" }} default: return undefined } } -}) +) // Evil proxy-induced side-effects shouldn't crash. @@ -1630,8 +1653,8 @@ TestPropertyNames([], { getOwnPropertyNames: function() { return [] } }) -TestPropertyNames(["a", "zz", " ", "0"], { - getOwnPropertyNames: function() { return ["a", "zz", " ", 0] } +TestPropertyNames(["a", "zz", " ", "0", "toString"], { + getOwnPropertyNames: function() { return ["a", "zz", " ", 0, "toString"] } }) TestPropertyNames(["throw", "function "], { @@ -1678,8 +1701,8 @@ TestKeys([], { keys: function() { return [] } }) -TestKeys(["a", "zz", " ", "0"], { - keys: function() { return ["a", "zz", " ", 0] } +TestKeys(["a", "zz", " ", "0", "toString"], { + keys: function() { return ["a", "zz", " ", 0, "toString"] } }) TestKeys(["throw", "function "], { |