summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/v8/test/mjsunit/harmony
diff options
context:
space:
mode:
authorSergio Ahumada <sergio.ahumada@digia.com>2013-03-19 09:25:14 +0100
committerSergio Ahumada <sergio.ahumada@digia.com>2013-03-19 09:56:31 +0100
commit6313e1fe4c27755adde87e62db1c2f9fac534ae4 (patch)
treec57bb29f65e02fbfcc07895a8cc2903fff9300ba /src/3rdparty/v8/test/mjsunit/harmony
parentb5a49a260d03249c386f1b63c249089383dd81fa (diff)
parentcac65e7a222b848a735a974b0aeb43209b0cfa18 (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')
-rw-r--r--src/3rdparty/v8/test/mjsunit/harmony/block-conflicts.js3
-rw-r--r--src/3rdparty/v8/test/mjsunit/harmony/block-let-crankshaft.js2
-rw-r--r--src/3rdparty/v8/test/mjsunit/harmony/collections.js80
-rw-r--r--src/3rdparty/v8/test/mjsunit/harmony/debug-blockscopes.js4
-rw-r--r--src/3rdparty/v8/test/mjsunit/harmony/module-linking.js183
-rw-r--r--src/3rdparty/v8/test/mjsunit/harmony/module-parsing.js31
-rw-r--r--src/3rdparty/v8/test/mjsunit/harmony/module-recompile.js87
-rw-r--r--src/3rdparty/v8/test/mjsunit/harmony/module-resolution.js17
-rw-r--r--src/3rdparty/v8/test/mjsunit/harmony/object-observe.js591
-rw-r--r--src/3rdparty/v8/test/mjsunit/harmony/proxies-json.js178
-rw-r--r--src/3rdparty/v8/test/mjsunit/harmony/proxies.js53
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 "], {