Upgrade V8 to 5.1.281.57 DO NOT MERGE
FPIIM-449
Change-Id: Id981b686b4d587ac31697662eb98bb34be42ad90
(cherry picked from commit 3b9bc31999c9787eb726ecdbfd5796bfdec32a18)
diff --git a/test/mjsunit/es6/array-concat.js b/test/mjsunit/es6/array-concat.js
index bc9e1a0..fe320d6 100644
--- a/test/mjsunit/es6/array-concat.js
+++ b/test/mjsunit/es6/array-concat.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-proxies --harmony-reflect
-
(function testArrayConcatArity() {
"use strict";
assertEquals(1, Array.prototype.concat.length);
@@ -803,9 +801,10 @@
log.length = 0;
assertEquals([obj], Array.prototype.concat.apply(obj));
- assertEquals(1, log.length);
+ assertEquals(2, log.length); // An extra read for the constructor
for (var i in log) assertSame(target, log[i][1]);
- assertEquals(["get", target, Symbol.isConcatSpreadable, obj], log[0]);
+ assertEquals(["get", target, "constructor", obj], log[0]);
+ assertEquals(["get", target, Symbol.isConcatSpreadable, obj], log[1]);
})();
@@ -827,14 +826,15 @@
log.length = 0;
assertEquals(["a", "b"], Array.prototype.concat.apply(obj));
- assertEquals(6, log.length);
+ assertEquals(7, log.length);
for (var i in log) assertSame(target, log[i][1]);
- assertEquals(["get", target, Symbol.isConcatSpreadable, obj], log[0]);
- assertEquals(["get", target, "length", obj], log[1]);
- assertEquals(["has", target, "0"], log[2]);
- assertEquals(["get", target, "0", obj], log[3]);
- assertEquals(["has", target, "1"], log[4]);
- assertEquals(["get", target, "1", obj], log[5]);
+ assertEquals(["get", target, "constructor", obj], log[0]);
+ assertEquals(["get", target, Symbol.isConcatSpreadable, obj], log[1]);
+ assertEquals(["get", target, "length", obj], log[2]);
+ assertEquals(["has", target, "0"], log[3]);
+ assertEquals(["get", target, "0", obj], log[4]);
+ assertEquals(["has", target, "1"], log[5]);
+ assertEquals(["get", target, "1", obj], log[6]);
})();
diff --git a/test/mjsunit/es6/array-iterator.js b/test/mjsunit/es6/array-iterator.js
index 5fab0fb..d2d19b0 100644
--- a/test/mjsunit/es6/array-iterator.js
+++ b/test/mjsunit/es6/array-iterator.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: --allow-natives-syntax --harmony-tostring
+// Flags: --allow-natives-syntax
var NONE = 0;
@@ -160,7 +160,7 @@
assertArrayEquals(['next'],
Object.getOwnPropertyNames(ArrayIteratorPrototype));
assertHasOwnProperty(ArrayIteratorPrototype, 'next', DONT_ENUM);
- assertHasOwnProperty(ArrayIteratorPrototype, Symbol.iterator, DONT_ENUM);
+ assertFalse(ArrayIteratorPrototype.hasOwnProperty(Symbol.iterator));
assertEquals("[object Array Iterator]",
Object.prototype.toString.call(iterator));
diff --git a/test/mjsunit/es6/array-prototype-values.js b/test/mjsunit/es6/array-prototype-values.js
new file mode 100644
index 0000000..64162c4
--- /dev/null
+++ b/test/mjsunit/es6/array-prototype-values.js
@@ -0,0 +1,15 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Flags: --harmony-array-prototype-values
+
+// Functionality of the values iterator is tested elsewhere; this test
+// merely verifies that the 'values' property is set up correctly.
+var valuesDesc = Object.getOwnPropertyDescriptor(Array.prototype, 'values');
+assertEquals('object', typeof valuesDesc);
+assertSame(Array.prototype[Symbol.iterator], valuesDesc.value);
+assertTrue(valuesDesc.configurable);
+assertTrue(valuesDesc.writable);
+assertFalse(valuesDesc.enumerable);
+assertTrue(Array.prototype[Symbol.unscopables].values);
diff --git a/test/mjsunit/es6/array-tostring.js b/test/mjsunit/es6/array-tostring.js
index 397fde4..973b3c3 100644
--- a/test/mjsunit/es6/array-tostring.js
+++ b/test/mjsunit/es6/array-tostring.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-tostring
-
var global = this;
var funs = {
diff --git a/test/mjsunit/es6/block-eval-var-over-legacy-const.js b/test/mjsunit/es6/block-eval-var-over-legacy-const.js
deleted file mode 100644
index be1687b..0000000
--- a/test/mjsunit/es6/block-eval-var-over-legacy-const.js
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-sloppy --harmony-sloppy-let --harmony-sloppy-function
-// Flags: --legacy-const
-
-// Legacy-const-let conflict in a function throws, even if the legacy const
-// is in an eval
-
-// Throws at the top level of a function
-assertThrows(function() {
- let x = 1;
- eval('const x = 2');
-}, TypeError);
-
-// If the eval is in its own block scope, throws
-assertThrows(function() {
- let y = 1;
- { eval('const y = 2'); }
-}, TypeError);
-
-// If the let is in its own block scope, with the eval, throws
-assertThrows(function() {
- {
- let x = 1;
- eval('const x = 2');
- }
-}, TypeError);
-
-// Legal if the let is no longer visible
-assertDoesNotThrow(function() {
- {
- let x = 1;
- }
- eval('const x = 2');
-});
-
-// In global scope
-let caught = false;
-try {
- let z = 1;
- eval('const z = 2');
-} catch (e) {
- caught = true;
-}
-assertTrue(caught);
-
-// Let declarations beyond a function boundary don't conflict
-caught = false;
-try {
- let a = 1;
- (function() {
- eval('const a');
- })();
-} catch (e) {
- caught = true;
-}
-assertFalse(caught);
-
-// legacy const across with doesn't conflict
-caught = false;
-try {
- (function() {
- with ({x: 1}) {
- eval("const x = 2;");
- }
- })();
-} catch (e) {
- caught = true;
-}
-assertFalse(caught);
-
-// legacy const can still conflict with let across a with
-caught = false;
-try {
- (function() {
- let x;
- with ({x: 1}) {
- eval("const x = 2;");
- }
- })();
-} catch (e) {
- caught = true;
-}
-assertTrue(caught);
diff --git a/test/mjsunit/es6/block-let-contextual-sloppy.js b/test/mjsunit/es6/block-let-contextual-sloppy.js
index 20ca107..ac7bca1 100644
--- a/test/mjsunit/es6/block-let-contextual-sloppy.js
+++ b/test/mjsunit/es6/block-let-contextual-sloppy.js
@@ -2,10 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy --harmony-sloppy-let --harmony-destructuring-bind
-// Flags: --legacy-const
+// Flags: --harmony-sloppy --harmony-sloppy-let
-// let is usable as a variable with var or legacy const, not let or ES6 const
+// let is usable as a variable with var, but not let or ES6 const
(function (){
assertEquals(undefined, let);
@@ -50,13 +49,6 @@
assertEquals(1, obj.x);
})();
-(function () {
- let obj = {};
- const [let] = [function() { return obj; }];
- let().x = 1;
- assertEquals(1, obj.x);
-})();
-
(function() {
function let() {
return 1;
diff --git a/test/mjsunit/es6/built-in-accessor-names.js b/test/mjsunit/es6/built-in-accessor-names.js
index c5f8cec..8c29d36 100644
--- a/test/mjsunit/es6/built-in-accessor-names.js
+++ b/test/mjsunit/es6/built-in-accessor-names.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-tostring
-
'use strict';
function assertGetterName(expected, object, name) {
diff --git a/test/mjsunit/es6/classes-proxy.js b/test/mjsunit/es6/classes-proxy.js
index 09d12c2..4642df8 100644
--- a/test/mjsunit/es6/classes-proxy.js
+++ b/test/mjsunit/es6/classes-proxy.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --harmony-proxies --harmony-reflect
+// Flags: --allow-natives-syntax
function CreateConstructableProxy(handler) {
return new Proxy(function(){}, handler);
diff --git a/test/mjsunit/es6/classes-subclass-builtins.js b/test/mjsunit/es6/classes-subclass-builtins.js
index 313aad1..7669ef3 100644
--- a/test/mjsunit/es6/classes-subclass-builtins.js
+++ b/test/mjsunit/es6/classes-subclass-builtins.js
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --harmony-reflect --harmony-regexp-subclass
-// Flags: --expose-gc --strong-mode
+// Flags: --allow-natives-syntax --harmony-regexp-subclass
+// Flags: --expose-gc
"use strict";
@@ -78,11 +78,6 @@
constructor(...args) {
assertFalse(new.target === undefined);
super(...args);
- // Strong functions are not extensible, so don't add fields.
- if (args[args.length - 1].indexOf("use strong") >= 0) {
- assertThrows(()=>{ this.a = 10; }, TypeError);
- return;
- }
this.a = 42;
this.d = 4.2;
this.o = {foo:153};
@@ -95,26 +90,24 @@
assertNull(Object.getOwnPropertyDescriptor(sloppy_func, "caller").value);
assertEquals(undefined, Object.getOwnPropertyDescriptor(strict_func, "caller"));
- function CheckFunction(func, is_strong) {
+ function CheckFunction(func) {
assertEquals("function", typeof func);
assertTrue(func instanceof Object);
assertTrue(func instanceof Function);
assertTrue(func instanceof A);
checkPrototypeChain(func, [A, Function, Object]);
- if (!is_strong) {
- assertEquals(42, func.a);
- assertEquals(4.2, func.d);
- assertEquals(153, func.o.foo);
- assertTrue(undefined !== func.prototype);
- func.prototype.bar = "func.bar";
- var obj = new func();
- assertTrue(obj instanceof Object);
- assertTrue(obj instanceof func);
- assertEquals("object", typeof obj);
- assertEquals(113, obj.foo);
- assertEquals("func.bar", obj.bar);
- delete func.prototype.bar;
- }
+ assertEquals(42, func.a);
+ assertEquals(4.2, func.d);
+ assertEquals(153, func.o.foo);
+ assertTrue(undefined !== func.prototype);
+ func.prototype.bar = "func.bar";
+ var obj = new func();
+ assertTrue(obj instanceof Object);
+ assertTrue(obj instanceof func);
+ assertEquals("object", typeof obj);
+ assertEquals(113, obj.foo);
+ assertEquals("func.bar", obj.bar);
+ delete func.prototype.bar;
}
var source = "this.foo = 113;";
@@ -135,15 +128,6 @@
var strict_func1 = new A("'use strict'; return 312;");
assertTrue(%HaveSameMap(strict_func, strict_func1));
- // Strong function
- var strong_func = new A("'use strong'; " + source);
- assertFalse(%HaveSameMap(strong_func, sloppy_func));
- assertFalse(%HaveSameMap(strong_func, strict_func));
- CheckFunction(strong_func, true);
-
- var strong_func1 = new A("'use strong'; return 312;");
- assertTrue(%HaveSameMap(strong_func, strong_func1));
-
gc();
})();
@@ -592,11 +576,6 @@
constructor(...args) {
assertFalse(new.target === undefined);
super(...args);
- // Strong functions are not extensible, so don't add fields.
- if (args[args.length - 1].indexOf("use strong") >= 0) {
- assertThrows(()=>{ this.a = 10; }, TypeError);
- return;
- }
this.a = 42;
this.d = 4.2;
this.o = {foo:153};
@@ -610,35 +589,34 @@
assertEquals(undefined, Object.getOwnPropertyDescriptor(sloppy_func, "caller"));
assertEquals(undefined, Object.getOwnPropertyDescriptor(strict_func, "caller"));
- function CheckFunction(func, is_strong) {
+ function CheckFunction(func) {
assertEquals("function", typeof func);
assertTrue(func instanceof Object);
assertTrue(func instanceof Function);
assertTrue(func instanceof GeneratorFunction);
assertTrue(func instanceof A);
checkPrototypeChain(func, [A, GeneratorFunction, Function, Object]);
- if (!is_strong) {
- assertEquals(42, func.a);
- assertEquals(4.2, func.d);
- assertEquals(153, func.o.foo);
- assertTrue(undefined !== func.prototype);
- func.prototype.bar = "func.bar";
- var obj = func(); // Generator object.
- assertTrue(obj instanceof Object);
- assertTrue(obj instanceof func);
- assertEquals("object", typeof obj);
- assertEquals("func.bar", obj.bar);
- delete func.prototype.bar;
+ assertEquals(42, func.a);
+ assertEquals(4.2, func.d);
+ assertEquals(153, func.o.foo);
- assertPropertiesEqual({done: false, value: 1}, obj.next());
- assertPropertiesEqual({done: false, value: 1}, obj.next());
- assertPropertiesEqual({done: false, value: 2}, obj.next());
- assertPropertiesEqual({done: false, value: 3}, obj.next());
- assertPropertiesEqual({done: false, value: 5}, obj.next());
- assertPropertiesEqual({done: false, value: 8}, obj.next());
- assertPropertiesEqual({done: true, value: undefined}, obj.next());
- }
+ assertTrue(undefined !== func.prototype);
+ func.prototype.bar = "func.bar";
+ var obj = func(); // Generator object.
+ assertTrue(obj instanceof Object);
+ assertTrue(obj instanceof func);
+ assertEquals("object", typeof obj);
+ assertEquals("func.bar", obj.bar);
+ delete func.prototype.bar;
+
+ assertPropertiesEqual({done: false, value: 1}, obj.next());
+ assertPropertiesEqual({done: false, value: 1}, obj.next());
+ assertPropertiesEqual({done: false, value: 2}, obj.next());
+ assertPropertiesEqual({done: false, value: 3}, obj.next());
+ assertPropertiesEqual({done: false, value: 5}, obj.next());
+ assertPropertiesEqual({done: false, value: 8}, obj.next());
+ assertPropertiesEqual({done: true, value: undefined}, obj.next());
}
var source = "yield 1; yield 1; yield 2; yield 3; yield 5; yield 8;";
@@ -659,15 +637,6 @@
var strict_func1 = new A("'use strict'; yield 312;");
assertTrue(%HaveSameMap(strict_func, strict_func1));
- // Strong generator function
- var strong_func = new A("'use strong'; " + source);
- assertFalse(%HaveSameMap(strong_func, sloppy_func));
- assertFalse(%HaveSameMap(strong_func, strict_func));
- CheckFunction(strong_func, true);
-
- var strong_func1 = new A("'use strong'; yield 312;");
- assertTrue(%HaveSameMap(strong_func, strong_func1));
-
gc();
})();
@@ -950,7 +919,13 @@
var o = Reflect.construct(RegExp, [pattern], f);
assertEquals(["match", "tostring"], log);
- assertEquals(/biep/, o);
+ // TODO(littledan): Is the RegExp constructor correct to create
+ // the internal slots and do these type checks this way?
+ assertEquals("biep", %_RegExpSource(o));
+ assertThrows(() => Object.getOwnPropertyDescriptor(RegExp.prototype,
+ 'source').get(o),
+ TypeError);
+ assertEquals("/undefined/undefined", RegExp.prototype.toString.call(o));
assertTrue(o.__proto__ === p2);
assertTrue(f.prototype === p3);
})();
diff --git a/test/mjsunit/es6/classes.js b/test/mjsunit/es6/classes.js
index ac10f0e..4dabda8 100644
--- a/test/mjsunit/es6/classes.js
+++ b/test/mjsunit/es6/classes.js
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy --allow-natives-syntax
+// Flags: --harmony-sloppy --harmony-function-name --allow-natives-syntax
+// Flags: --harmony-do-expressions
(function TestBasics() {
var C = class C {}
@@ -22,13 +23,11 @@
class D2 { constructor() {} }
assertEquals('D2', D2.name);
- // TODO(arv): The logic for the name of anonymous functions in ES6 requires
- // the below to be 'E';
var E = class {}
- assertEquals('', E.name); // Should be 'E'.
+ assertEquals('E', E.name); // Should be 'E'.
var F = class { constructor() {} };
- assertEquals('', F.name); // Should be 'F'.
+ assertEquals('F', F.name); // Should be 'F'.
})();
@@ -996,3 +995,55 @@
testClassRestrictedProperties(
class extends Class { constructor() { super(); } });
})();
+
+
+(function testReturnFromClassLiteral() {
+
+ function usingDoExpressionInBody() {
+ let x = 42;
+ let dummy = function() {x};
+ try {
+ class C {
+ dummy() {C}
+ [do {return}]() {}
+ };
+ } finally {
+ return x;
+ }
+ }
+ assertEquals(42, usingDoExpressionInBody());
+
+ function usingDoExpressionInExtends() {
+ let x = 42;
+ let dummy = function() {x};
+ try {
+ class C extends (do {return}) { dummy() {C} };
+ } finally {
+ return x;
+ }
+ }
+ assertEquals(42, usingDoExpressionInExtends());
+
+ function usingYieldInBody() {
+ function* foo() {
+ class C {
+ [yield]() {}
+ }
+ }
+ var g = foo();
+ g.next();
+ return g.return(42).value;
+ }
+ assertEquals(42, usingYieldInBody());
+
+ function usingYieldInExtends() {
+ function* foo() {
+ class C extends (yield) {};
+ }
+ var g = foo();
+ g.next();
+ return g.return(42).value;
+ }
+ assertEquals(42, usingYieldInExtends());
+
+})();
diff --git a/test/mjsunit/es6/classof-proxy.js b/test/mjsunit/es6/classof-proxy.js
index c3bc985..0204361 100644
--- a/test/mjsunit/es6/classof-proxy.js
+++ b/test/mjsunit/es6/classof-proxy.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --harmony-proxies
+// Flags: --allow-natives-syntax
function test_function(o) {
if (%_ClassOf(o) === "Function") {
diff --git a/test/mjsunit/es6/collection-iterator.js b/test/mjsunit/es6/collection-iterator.js
index 18b3f1a..a92c9ae 100644
--- a/test/mjsunit/es6/collection-iterator.js
+++ b/test/mjsunit/es6/collection-iterator.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --harmony-tostring
+// Flags: --allow-natives-syntax
(function TestSetIterator() {
diff --git a/test/mjsunit/es6/collections.js b/test/mjsunit/es6/collections.js
index e410e22..1664a93 100644
--- a/test/mjsunit/es6/collections.js
+++ b/test/mjsunit/es6/collections.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: --expose-gc --allow-natives-syntax --harmony-tostring
+// Flags: --expose-gc --allow-natives-syntax
function assertSize(expected, collection) {
diff --git a/test/mjsunit/es6/completion.js b/test/mjsunit/es6/completion.js
index 05565bf..7559514 100644
--- a/test/mjsunit/es6/completion.js
+++ b/test/mjsunit/es6/completion.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy-let --no-legacy-const
+// Flags: --harmony-sloppy-let
function assertUndef(x) {
diff --git a/test/mjsunit/es6/debug-blockscopes.js b/test/mjsunit/es6/debug-blockscopes.js
index d3c3620..193ad70 100644
--- a/test/mjsunit/es6/debug-blockscopes.js
+++ b/test/mjsunit/es6/debug-blockscopes.js
@@ -26,7 +26,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --expose-debug-as debug --allow-natives-syntax
-// Flags: --debug-eval-readonly-locals
// The functions used for testing backtraces. They are at the top to make the
// testing of source line/column easier.
diff --git a/test/mjsunit/es6/debug-liveedit-new-target-1.js b/test/mjsunit/es6/debug-liveedit-new-target-1.js
index 043c5f1..8855742 100644
--- a/test/mjsunit/es6/debug-liveedit-new-target-1.js
+++ b/test/mjsunit/es6/debug-liveedit-new-target-1.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-reflect --expose-debug-as debug --allow-natives-syntax
+// Flags: --expose-debug-as debug --allow-natives-syntax
// Test that live-editing a frame that uses new.target fails.
diff --git a/test/mjsunit/es6/debug-promises/events.js b/test/mjsunit/es6/debug-promises/events.js
deleted file mode 100644
index 3fcb22f..0000000
--- a/test/mjsunit/es6/debug-promises/events.js
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --allow-natives-syntax --expose-debug-as debug
-
-Debug = debug.Debug;
-
-var eventsExpected = 16;
-var exception = null;
-var result = [];
-
-function updatePromise(promise, parentPromise, status, value) {
- var i;
- for (i = 0; i < result.length; ++i) {
- if (result[i].promise === promise) {
- result[i].parentPromise = parentPromise || result[i].parentPromise;
- result[i].status = status || result[i].status;
- result[i].value = value || result[i].value;
- break;
- }
- }
- assertTrue(i < result.length);
-}
-
-function listener(event, exec_state, event_data, data) {
- if (event != Debug.DebugEvent.PromiseEvent) return;
- try {
- eventsExpected--;
- assertTrue(event_data.promise().isPromise());
- if (event_data.status() === 0) {
- // New promise.
- assertEquals("pending", event_data.promise().status());
- result.push({ promise: event_data.promise().value(), status: 0 });
- assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
- } else if (event_data.status() !== undefined) {
- // Resolve/reject promise.
- updatePromise(event_data.promise().value(),
- undefined,
- event_data.status(),
- event_data.value().value());
- } else {
- // Chain promises.
- assertTrue(event_data.parentPromise().isPromise());
- updatePromise(event_data.promise().value(),
- event_data.parentPromise().value());
- assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
- }
- } catch (e) {
- print(e + e.stack)
- exception = e;
- }
-}
-
-Debug.setListener(listener);
-
-function resolver(resolve, reject) { resolve(); }
-
-var p1 = new Promise(resolver); // event
-var p2 = p1.then().then(); // event
-var p3 = new Promise(function(resolve, reject) { // event
- reject("rejected");
-});
-var p4 = p3.then(); // event
-var p5 = p1.then(); // event
-
-function assertAsync(b, s) {
- if (b) {
- print(s, "succeeded");
- } else {
- %AbortJS(s + " FAILED!");
- }
-}
-
-function testDone(iteration) {
- function checkResult() {
- if (eventsExpected === 0) {
- assertAsync(result.length === 6, "result.length");
-
- assertAsync(result[0].promise === p1, "result[0].promise");
- assertAsync(result[0].parentPromise === undefined,
- "result[0].parentPromise");
- assertAsync(result[0].status === 1, "result[0].status");
- assertAsync(result[0].value === undefined, "result[0].value");
-
- assertAsync(result[1].parentPromise === p1,
- "result[1].parentPromise");
- assertAsync(result[1].status === 1, "result[1].status");
-
- assertAsync(result[2].promise === p2, "result[2].promise");
-
- assertAsync(result[3].promise === p3, "result[3].promise");
- assertAsync(result[3].parentPromise === undefined,
- "result[3].parentPromise");
- assertAsync(result[3].status === -1, "result[3].status");
- assertAsync(result[3].value === "rejected", "result[3].value");
-
- assertAsync(result[4].promise === p4, "result[4].promise");
- assertAsync(result[4].parentPromise === p3,
- "result[4].parentPromise");
- assertAsync(result[4].status === -1, "result[4].status");
- assertAsync(result[4].value === "rejected", "result[4].value");
-
- assertAsync(result[5].promise === p5, "result[5].promise");
- assertAsync(result[5].parentPromise === p1,
- "result[5].parentPromise");
- assertAsync(result[5].status === 1, "result[5].status");
-
- assertAsync(exception === null, "exception === null");
- Debug.setListener(null);
- } else if (iteration > 10) {
- %AbortJS("Not all events were received!");
- } else {
- testDone(iteration + 1);
- }
- }
-
- var iteration = iteration || 0;
- %EnqueueMicrotask(checkResult);
-}
-
-testDone();
diff --git a/test/mjsunit/es6/debug-promises/resolve-after-aborted-try-finally.js b/test/mjsunit/es6/debug-promises/resolve-after-aborted-try-finally.js
deleted file mode 100644
index 918ae2a..0000000
--- a/test/mjsunit/es6/debug-promises/resolve-after-aborted-try-finally.js
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --expose-debug-as debug --allow-natives-syntax
-
-// Test debug events when we listen to all exceptions and
-// there is a catch handler for the exception thrown in a Promise.
-// We expect a normal Exception debug event to be triggered.
-
-Debug = debug.Debug;
-
-var events = [];
-
-function listener(event, exec_state, event_data, data) {
- if (event == Debug.DebugEvent.PromiseEvent) events.push(event_data.status());
-}
-
-Debug.setListener(listener);
-
-var p = new Promise(function(resolve, reject) {
- do {
- try {
- throw new Error("reject");
- } finally {
- break; // No rethrow.
- }
- } while (false);
- resolve();
-});
-
-assertEquals([0 /* create */, 1 /* resolve */], events);
diff --git a/test/mjsunit/es6/debug-promises/resolve-after-try-catch.js b/test/mjsunit/es6/debug-promises/resolve-after-try-catch.js
deleted file mode 100644
index 298201f..0000000
--- a/test/mjsunit/es6/debug-promises/resolve-after-try-catch.js
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --expose-debug-as debug --allow-natives-syntax
-
-// Test debug events when we listen to all exceptions and
-// there is a catch handler for the exception thrown in a Promise.
-// We expect a normal Exception debug event to be triggered.
-
-Debug = debug.Debug;
-
-var events = [];
-
-function listener(event, exec_state, event_data, data) {
- if (event == Debug.DebugEvent.PromiseEvent) events.push(event_data.status());
-}
-
-Debug.setListener(listener);
-
-var p = new Promise(function (resolve, reject) {
- try {
- throw new Error("reject");
- } catch (e) {
- }
- resolve();
-});
-
-assertEquals([0 /* create */, 1 /* resolve */], events);
diff --git a/test/mjsunit/es6/debug-promises/rethrow-in-try-finally.js b/test/mjsunit/es6/debug-promises/rethrow-in-try-finally.js
deleted file mode 100644
index b1e2ff9..0000000
--- a/test/mjsunit/es6/debug-promises/rethrow-in-try-finally.js
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --expose-debug-as debug --allow-natives-syntax
-
-// Test debug events when we listen to all exceptions and
-// there is a catch handler for the exception thrown in a Promise.
-// We expect a normal Exception debug event to be triggered.
-
-Debug = debug.Debug;
-
-var events = [];
-
-function listener(event, exec_state, event_data, data) {
- if (event == Debug.DebugEvent.PromiseEvent) events.push(event_data.status());
-}
-
-Debug.setListener(listener);
-
-var p = new Promise(function(resolve, reject) {
- try {
- throw new Error("reject");
- } finally {
- // Implicit rethrow.
- }
- resolve();
-});
-
-assertEquals([0 /* create */, -1 /* rethrown */], events);
diff --git a/test/mjsunit/es6/debug-promises/throw-with-throw-in-reject.js b/test/mjsunit/es6/debug-promises/throw-with-throw-in-reject.js
index 349d014..5cf49f2 100644
--- a/test/mjsunit/es6/debug-promises/throw-with-throw-in-reject.js
+++ b/test/mjsunit/es6/debug-promises/throw-with-throw-in-reject.js
@@ -31,6 +31,7 @@
};
MyPromise.prototype = new Promise(function() {});
+MyPromise.__proto__ = Promise;
p.constructor = MyPromise;
var q = p.chain(
diff --git a/test/mjsunit/es6/debug-promises/throw-with-undefined-reject.js b/test/mjsunit/es6/debug-promises/throw-with-undefined-reject.js
index 69ee01e..6fe3b17 100644
--- a/test/mjsunit/es6/debug-promises/throw-with-undefined-reject.js
+++ b/test/mjsunit/es6/debug-promises/throw-with-undefined-reject.js
@@ -2,18 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --expose-debug-as debug --allow-natives-syntax --promise-extra
-
-// Test debug events when an exception is thrown inside a Promise, which is
-// caught by a custom promise, which has no reject handler.
-// We expect two Exception debug events:
-// 1) when the exception is thrown in the promise q.
-// 2) when calling the undefined custom reject closure in MyPromise throws.
-
-Debug = debug.Debug;
-
-var expected_events = 2;
-var log = [];
+// A non-callable reject function throws eagerly
var p = new Promise(function(resolve, reject) {
log.push("resolve");
@@ -23,63 +12,11 @@
function MyPromise(resolver) {
var reject = undefined;
var resolve = function() { };
- log.push("construct");
resolver(resolve, reject);
};
MyPromise.prototype = new Promise(function() {});
+MyPromise.__proto__ = Promise;
p.constructor = MyPromise;
-var q = p.chain(
- function() {
- log.push("throw caught");
- throw new Error("caught"); // event
- });
-
-function listener(event, exec_state, event_data, data) {
- try {
- if (event == Debug.DebugEvent.Exception) {
- expected_events--;
- assertTrue(expected_events >= 0);
- if (expected_events == 1) {
- assertTrue(
- exec_state.frame(0).sourceLineText().indexOf('// event') > 0);
- assertEquals("caught", event_data.exception().message);
- } else if (expected_events == 0) {
- // All of the frames on the stack are from native Javascript.
- assertEquals(0, exec_state.frameCount());
- assertEquals("(var).reject is not a function",
- event_data.exception().message);
- } else {
- assertUnreachable();
- }
- assertSame(q, event_data.promise());
- }
- } catch (e) {
- %AbortJS(e + "\n" + e.stack);
- }
-}
-
-Debug.setBreakOnUncaughtException();
-Debug.setListener(listener);
-
-log.push("end main");
-
-function testDone(iteration) {
- function checkResult() {
- try {
- assertTrue(iteration < 10);
- if (expected_events === 0) {
- assertEquals(["resolve", "construct", "end main", "throw caught"], log);
- } else {
- testDone(iteration + 1);
- }
- } catch (e) {
- %AbortJS(e + "\n" + e.stack);
- }
- }
-
- %EnqueueMicrotask(checkResult);
-}
-
-testDone(0);
+assertThrows(()=> p.then(function() { }), TypeError);
diff --git a/test/mjsunit/es6/debug-step-destructuring-assignment.js b/test/mjsunit/es6/debug-step-destructuring-assignment.js
new file mode 100644
index 0000000..4fde928
--- /dev/null
+++ b/test/mjsunit/es6/debug-step-destructuring-assignment.js
@@ -0,0 +1,85 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+var exception = null;
+var Debug = debug.Debug;
+var break_count = 0;
+
+function listener(event, exec_state, event_data, data) {
+ if (event != Debug.DebugEvent.Break) return;
+ try {
+ var source = exec_state.frame(0).sourceLineText();
+ print(source);
+ assertTrue(source.indexOf(`// B${break_count++}`) > 0);
+ if (source.indexOf("assertEquals") > 0) {
+ exec_state.prepareStep(Debug.StepAction.StepNext);
+ } else {
+ exec_state.prepareStep(Debug.StepAction.StepIn);
+ }
+ } catch (e) {
+ exception = e;
+ print(e);
+ }
+};
+
+Debug.setListener(listener);
+
+function f() {
+ var a, b, c, d;
+ debugger; // B0
+ [ // B1
+ a, // B2
+ b, // B3
+ c = 3 // B4
+ ] = [1, 2];
+ assertEquals({a:1,b:2,c:3}, {a, b, c}); // B5
+
+ [ // B6
+ a, // B7
+ [
+ b, // B8
+ c // B9
+ ],
+ d // B10
+ ] = [5, [6, 7], 8];
+ assertEquals({a:5,b:6,c:7,d:8}, {a, b, c, d}); // B11
+
+ [ // B12
+ a, // B13
+ b, // B14
+ ...c // B15
+ ] = [1, 2, 3, 4];
+ assertEquals({a:1,b:2,c:[3,4]}, {a, b, c}); // B16
+
+ ({ // B17
+ a, // B18
+ b, // B19
+ c = 7 // B20
+ } = {a: 5, b: 6});
+ assertEquals({a:5,b:6,c:7}, {a, b, c}); // B21
+
+ ({ // B22
+ a, // B23
+ b = return1(), // B24
+ c = return1() // B25
+ } = {a: 5, b: 6});
+ assertEquals({a:5,b:6,c:1}, {a, b, c}); // B28
+
+ ({ // B29
+ x : a, // B30
+ y : b, // B31
+ z : c = 3 // B32
+ } = {x: 1, y: 2});
+ assertEquals({a:1,b:2,c:3}, {a, b, c}); // B33
+} // B34
+
+function return1() {
+ return 1; // B26
+} // B27
+
+f();
+Debug.setListener(null); // B35
+assertNull(exception);
diff --git a/test/mjsunit/es6/debug-step-destructuring-bind.js b/test/mjsunit/es6/debug-step-destructuring-bind.js
new file mode 100644
index 0000000..f670f52
--- /dev/null
+++ b/test/mjsunit/es6/debug-step-destructuring-bind.js
@@ -0,0 +1,110 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+var exception = null;
+var Debug = debug.Debug;
+var break_count = 0;
+
+function listener(event, exec_state, event_data, data) {
+ if (event != Debug.DebugEvent.Break) return;
+ try {
+ var source = exec_state.frame(0).sourceLineText();
+ print(source, break_count);
+ assertTrue(source.indexOf(`B${break_count++}`) > 0);
+ if (source.indexOf("assertEquals") > 0) {
+ exec_state.prepareStep(Debug.StepAction.StepNext);
+ } else {
+ exec_state.prepareStep(Debug.StepAction.StepIn);
+ }
+ } catch (e) {
+ exception = e;
+ print(e);
+ }
+};
+
+Debug.setListener(listener);
+
+var id = x => x; // B9 B10 B36 B37
+
+function test() {
+ debugger; // B0
+ function fx1([
+ a, // B2
+ b // B3
+ ]) {
+ assertEquals([1, 2], [a, b]); // B4
+ } // B5
+ fx1([1, 2, 3]); // B1
+
+ function f2([
+ a, // B7
+ b = id(3) // B8
+ ]) {
+ assertEquals([4, 3], [a, b]); // B11
+ } // B12
+ f2([4]); // B6
+
+ function f3({
+ x: a, // B14
+ y: b // B15
+ }) {
+ assertEquals([5, 6], [a, b]); // B16
+ } // B17
+ f3({y: 6, x: 5}); // B13
+
+ function f4([
+ a, // B19
+ {
+ b, // B20
+ c, // B21
+ }
+ ]) {
+ assertEquals([2, 4, 6], [a, b, c]); // B22
+ } // B23
+ f4([2, {c: 6, b: 4}]); // B18
+
+ function f5([
+ {
+ a, // B25
+ b = 7 // B26
+ },
+ c = 3 // B27
+ ] = [{a:1}]) {
+ assertEquals([1, 7, 3], [a, b, c]); // B28
+ } // B29
+ f5(); // B24
+
+ var name = "x"; // B30
+ function f6({
+ [id(name)]: a, // B34 B35
+ b = a // B38
+ }) {
+ assertEquals([9, 9], [a, b]); // B39
+ } // B40
+ var o6 = {}; // B31
+ o6[name] = 9; // B32
+ f6(o6); // B33
+
+ try {
+ throw [3, 4]; // B41
+ } catch ([
+ a, // B42
+ b, // B43
+ c = 6 // B44
+ ]) {
+ assertEquals([3, 4, 6], [a, b, c]); // B45
+ }
+
+ var {
+ x: a, // B46
+ y: b = 9 // B47
+ } = { x: 4 };
+ assertEquals([4, 9], [a, b]); // B48
+} // B49
+
+test();
+Debug.setListener(null); // B50
+assertNull(exception);
diff --git a/test/mjsunit/es6/debug-stepin-default-parameters.js b/test/mjsunit/es6/debug-stepin-default-parameters.js
new file mode 100644
index 0000000..aaac9f0
--- /dev/null
+++ b/test/mjsunit/es6/debug-stepin-default-parameters.js
@@ -0,0 +1,46 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+Debug = debug.Debug
+
+var exception = null;
+var log = [];
+
+function listener(event, exec_state, event_data, data) {
+ if (event != Debug.DebugEvent.Break) return;
+ try {
+ print(event_data.sourceLineText());
+ var entry = "";
+ for (var i = 0; i < exec_state.frameCount(); i++) {
+ entry += exec_state.frame(i).sourceLineText().substr(-1);
+ entry += exec_state.frame(i).sourceColumn();
+ }
+ log.push(entry);
+ exec_state.prepareStep(Debug.StepAction.StepIn);
+ } catch (e) {
+ exception = e;
+ }
+};
+
+function default_arg(x) {
+ return "default"; // d
+} // e
+
+function f(arg0 = default_arg()) { // f
+ return arg0; // g
+} // h
+
+
+Debug.setListener(listener);
+debugger; // a
+var result = f(); // b
+Debug.setListener(null); // c
+
+assertNull(exception);
+assertEquals("default", result);
+
+assertEquals(["a0","b13","f18b13","d2f18b13","e0f18b13","g2b13","h0b13","c0"],
+ log);
diff --git a/test/mjsunit/es6/debug-stepin-proxies.js b/test/mjsunit/es6/debug-stepin-proxies.js
new file mode 100644
index 0000000..4e71c79
--- /dev/null
+++ b/test/mjsunit/es6/debug-stepin-proxies.js
@@ -0,0 +1,61 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+Debug = debug.Debug
+
+var exception = null;
+var log = [];
+
+function listener(event, exec_state, event_data, data) {
+ if (event != Debug.DebugEvent.Break) return;
+ try {
+ print(event_data.sourceLineText());
+ var entry = "";
+ for (var i = 0; i < exec_state.frameCount(); i++) {
+ entry += exec_state.frame(i).sourceLineText().substr(-1);
+ entry += exec_state.frame(i).sourceColumn();
+ }
+ log.push(entry);
+ exec_state.prepareStep(Debug.StepAction.StepIn);
+ } catch (e) {
+ exception = e;
+ }
+};
+
+var target = {};
+var handler = {
+ has: function(target, name) {
+ return true; // h
+ }, // i
+ get: function(target, name) {
+ return 42; // j
+ }, // k
+ set: function(target, name, value) {
+ return false; // l
+ }, // m
+}
+
+var proxy = new Proxy(target, handler);
+
+Debug.setListener(listener);
+debugger; // a
+var has = "step" in proxy; // b
+var get = proxy.step; // c
+proxy.step = 43; // d
+
+Debug.setListener(null); // g
+
+assertNull(exception);
+assertTrue(has);
+assertEquals(42, get);
+
+assertEquals([
+ "a0",
+ "b17", "h4b20", "i2b20", // [[Has]]
+ "c15", "j4c15", "k2c15", // [[Get]]
+ "d0", "l4d11", "m2d11", // [[Set]]
+ "g0"
+], log);
diff --git a/test/mjsunit/es6/debug-stepin-string-template.js b/test/mjsunit/es6/debug-stepin-string-template.js
index f500fae..2d8c394 100644
--- a/test/mjsunit/es6/debug-stepin-string-template.js
+++ b/test/mjsunit/es6/debug-stepin-string-template.js
@@ -48,7 +48,8 @@
assertEquals([
"a0",
- "b0",
+ "b44",
+ "b13",
"d2b13",
"e0b13",
"b25",
diff --git a/test/mjsunit/es6/debug-stepin-tailcalls.js b/test/mjsunit/es6/debug-stepin-tailcalls.js
new file mode 100644
index 0000000..6020ba9
--- /dev/null
+++ b/test/mjsunit/es6/debug-stepin-tailcalls.js
@@ -0,0 +1,46 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --harmony-tailcalls
+
+"use strict";
+
+var Debug = debug.Debug
+var exception = null;
+var breaks = 0;
+
+function f(x) {
+ if (x > 0) { // B3 B5 B7 B9
+ return f(x - 1); // B4 B6 B8
+ }
+} // B10
+
+function g(x) {
+ return f(x); // B2
+}
+
+function h(x) {
+ debugger; // B0
+ g(x); // B1
+} // B11
+
+
+function listener(event, exec_state, event_data, data) {
+ if (event != Debug.DebugEvent.Break) return;
+ try {
+ print(event_data.sourceLineText());
+ assertTrue(event_data.sourceLineText().indexOf(`B${breaks++}`) > 0);
+ exec_state.prepareStep(Debug.StepAction.StepIn);
+ } catch (e) {
+ exception = e;
+ };
+};
+
+Debug.setListener(listener);
+
+h(3);
+
+Debug.setListener(null); // B12
+assertNull(exception);
+assertEquals(13, breaks);
diff --git a/test/mjsunit/es6/debug-stepnext-for.js b/test/mjsunit/es6/debug-stepnext-for.js
index 932840a..9d5641a 100644
--- a/test/mjsunit/es6/debug-stepnext-for.js
+++ b/test/mjsunit/es6/debug-stepnext-for.js
@@ -91,7 +91,7 @@
// based on other values.
var expected = [
// Entry
- "a2","b2",
+ "a2",
// Empty for-in-var: get enumerable
"c16",
// Empty for-in: get enumerable
@@ -108,12 +108,12 @@
"i12","i10","i11","I4","i11","I4","i11","I4","i11",
// For-of-let: [Symbol.iterator](), next(), body, next(), ...
"j16","j14","j15","J4","j15","J4","j15","J4","j15",
- // For-var: var decl, condition, body, next, condition, body, ...
- "k7","k20","K4","k26","k20","K4","k26","k20","K4","k26","k20",
+ // For-var: init, condition, body, next, condition, body, ...
+ "k15","k20","K4","k26","k20","K4","k26","k20","K4","k26","k20",
// For: init, condition, body, next, condition, body, ...
"l7","l16","L4","l22","l16","L4","l22","l16","L4","l22","l16",
// For-let: init, condition, body, next, condition, body, ...
- "m7","m20","M4","m26","m20","M4","m26","m20","M4","m26","m20",
+ "m15","m20","M4","m26","m20","M4","m26","m20","M4","m26","m20",
// Exit.
"y0","z0",
]
diff --git a/test/mjsunit/es6/debug-stepout-tailcalls.js b/test/mjsunit/es6/debug-stepout-tailcalls.js
new file mode 100644
index 0000000..db0878d
--- /dev/null
+++ b/test/mjsunit/es6/debug-stepout-tailcalls.js
@@ -0,0 +1,45 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --harmony-tailcalls
+
+"use strict";
+
+var Debug = debug.Debug
+var exception = null;
+var breaks = 0;
+
+function f(x) {
+ if (x > 0) {
+ return f(x - 1); // Tail call
+ }
+ debugger; // Break 0
+}
+
+function g(x) {
+ return f(x); // Tail call
+}
+
+function h(x) {
+ g(x); // Not tail call
+} // Break 1
+
+
+function listener(event, exec_state, event_data, data) {
+ if (event != Debug.DebugEvent.Break) return;
+ try {
+ assertTrue(event_data.sourceLineText().indexOf(`Break ${breaks++}`) > 0);
+ exec_state.prepareStep(Debug.StepAction.StepOut);
+ } catch (e) {
+ exception = e;
+ };
+};
+
+Debug.setListener(listener);
+
+h(3);
+
+Debug.setListener(null); // Break 2
+assertNull(exception);
+assertEquals(3, breaks);
diff --git a/test/mjsunit/es6/default-parameters-debug.js b/test/mjsunit/es6/default-parameters-debug.js
new file mode 100644
index 0000000..30e19c4
--- /dev/null
+++ b/test/mjsunit/es6/default-parameters-debug.js
@@ -0,0 +1,58 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+listenerComplete = false;
+breakPointCount = 0;
+
+function listener(event, exec_state, event_data, data) {
+ if (event == Debug.DebugEvent.Break) {
+ breakPointCount++;
+ if (breakPointCount == 1) {
+ // Break point in initializer for parameter `a`, invoked by
+ // initializer for parameter `b`
+ assertEquals('default', exec_state.frame(1).evaluate('mode').value());
+
+ // initializer for `b` can't refer to `b`
+ assertThrows(function() {
+ exec_state.frame(1).evaluate('b').value();
+ }, ReferenceError);
+
+ assertThrows(function() {
+ exec_state.frame(1).evaluate('c');
+ }, ReferenceError);
+ } else if (breakPointCount == 2) {
+ // Break point in IIFE initializer for parameter `c`
+ assertEquals('modeFn', exec_state.frame(1).evaluate('a.name').value());
+ assertEquals('default', exec_state.frame(1).evaluate('b').value());
+ assertThrows(function() {
+ exec_state.frame(1).evaluate('c');
+ }, ReferenceError);
+ } else if (breakPointCount == 3) {
+ // Break point in function body --- `c` parameter is shadowed
+ assertEquals('modeFn', exec_state.frame(0).evaluate('a.name').value());
+ assertEquals('default', exec_state.frame(0).evaluate('b').value());
+ assertEquals('local', exec_state.frame(0).evaluate('d').value());
+ }
+ }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function f(a = function modeFn(mode) { debugger; return mode; },
+ b = a("default"),
+ c = (function() { debugger; })()) {
+ var d = 'local';
+ debugger;
+};
+
+f();
+
+// Make sure that the debug event listener vas invoked.
+assertEquals(3, breakPointCount);
diff --git a/test/mjsunit/es6/default-parameters-destructuring.js b/test/mjsunit/es6/default-parameters-destructuring.js
new file mode 100644
index 0000000..50071f0
--- /dev/null
+++ b/test/mjsunit/es6/default-parameters-destructuring.js
@@ -0,0 +1,110 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+(function TestSloppyEvalScoping() {
+ var x = 1;
+
+ function f41({[eval("var x = 2; 'a'")]: w}, z = x) { return z; }
+ assertEquals(1, f41({}));
+ assertEquals(1, f41({a: 0}));
+ function f42({[eval("var x = 2; 'a'")]: w}, z = eval("x")) { return z; }
+ assertEquals(1, f42({}));
+ assertEquals(1, f42({a: 0}));
+ function f43({a: w = eval("var x = 2")}, z = x) { return z; }
+ assertEquals(1, f43({}));
+ assertEquals(1, f43({a: 0}));
+ function f44({a: w = eval("var x = 2")}, z = eval("x")) { return z; }
+ assertEquals(1, f44({}));
+ assertEquals(1, f44({a: 0}));
+
+ function f5({a = eval("var x = 2"), b = x}) { return b; }
+ assertEquals(2, f5({}));
+ assertEquals(1, f5({a: 0}));
+ function f6({a = eval("var x = 2"), b = eval("x")}) { return b; }
+ assertEquals(2, f6({}));
+ assertEquals(1, f6({a: 0}));
+ function f71({[eval("var x = 2; 'a'")]: w, b = x}) { return b; }
+ assertEquals(2, f71({}));
+ assertEquals(2, f71({a: 0}));
+ function f72({[eval("var x = 2; 'a'")]: w, b = eval("x")}) { return b; }
+ assertEquals(2, f72({}));
+ assertEquals(2, f72({a: 0}));
+ function f73({a: w = eval("var x = 2"), b = x}) { return b; }
+ assertEquals(2, f73({}));
+ assertEquals(1, f73({a: 0}));
+ function f74({a: w = eval("var x = 2"), b = eval("x")}) { return b; }
+ assertEquals(2, f74({}));
+ assertEquals(1, f74({a: 0}));
+
+ var g41 = ({[eval("var x = 2; 'a'")]: w}, z = x) => { return z; };
+ assertEquals(1, g41({}));
+ assertEquals(1, g41({a: 0}));
+ var g42 = ({[eval("var x = 2; 'a'")]: w}, z = eval("x")) => { return z; };
+ assertEquals(1, g42({}));
+ assertEquals(1, g42({a: 0}));
+ var g43 = ({a: w = eval("var x = 2")}, z = x) => { return z; };
+ assertEquals(1, g43({}));
+ assertEquals(1, g43({a: 0}));
+ var g44 = ({a: w = eval("var x = 2")}, z = eval("x")) => { return z; };
+ assertEquals(1, g44({}));
+ assertEquals(1, g44({a: 0}));
+
+ var g5 = ({a = eval("var x = 2"), b = x}) => { return b; };
+ assertEquals(2, g5({}));
+ assertEquals(1, g5({a: 0}));
+ var g6 = ({a = eval("var x = 2"), b = eval("x")}) => { return b; };
+ assertEquals(2, g6({}));
+ assertEquals(1, g6({a: 0}));
+ var g71 = ({[eval("var x = 2; 'a'")]: w, b = x}) => { return b; };
+ assertEquals(2, g71({}));
+ assertEquals(2, g71({a: 0}));
+ var g72 = ({[eval("var x = 2; 'a'")]: w, b = eval("x")}) => { return b; };
+ assertEquals(2, g72({}));
+ assertEquals(2, g72({a: 0}));
+ var g73 = ({a: w = eval("var x = 2"), b = x}) => { return b; };
+ assertEquals(2, g73({}));
+ assertEquals(1, g73({a: 0}));
+ var g74 = ({a: w = eval("var x = 2"), b = eval("x")}) => { return b; };
+ assertEquals(2, g74({}));
+ assertEquals(1, g74({a: 0}));
+})();
+
+
+(function TestStrictEvalScoping() {
+ 'use strict';
+ var x = 1;
+
+ function f41({[eval("var x = 2; 'a'")]: w}, z = x) { return z; }
+ assertEquals(1, f41({}));
+ assertEquals(1, f41({a: 0}));
+ function f42({[eval("var x = 2; 'a'")]: w}, z = eval("x")) { return z; }
+ assertEquals(1, f42({}));
+ assertEquals(1, f42({a: 0}));
+ function f43({a: w = eval("var x = 2")}, z = x) { return z; }
+ assertEquals(1, f43({}));
+ assertEquals(1, f43({a: 0}));
+ function f44({a: w = eval("var x = 2")}, z = eval("x")) { return z; }
+ assertEquals(1, f44({}));
+ assertEquals(1, f44({a: 0}));
+
+ function f5({a = eval("var x = 2"), b = x}) { return b; }
+ assertEquals(1, f5({}));
+ assertEquals(1, f5({a: 0}));
+ function f6({a = eval("var x = 2"), b = eval("x")}) { return b; }
+ assertEquals(1, f6({}));
+ assertEquals(1, f6({a: 0}));
+ function f71({[eval("var x = 2; 'a'")]: w, b = x}) { return b; }
+ assertEquals(1, f71({}));
+ assertEquals(1, f71({a: 0}));
+ function f72({[eval("var x = 2; 'a'")]: w, b = eval("x")}) { return b; }
+ assertEquals(1, f72({}));
+ assertEquals(1, f72({a: 0}));
+ function f73({a: w = eval("var x = 2"), b = x}) { return b; }
+ assertEquals(1, f73({}));
+ assertEquals(1, f73({a: 0}));
+ function f74({a: w = eval("var x = 2"), b = eval("x")}) { return b; }
+ assertEquals(1, f74({}));
+ assertEquals(1, f74({a: 0}));
+})();
diff --git a/test/mjsunit/es6/default-parameters.js b/test/mjsunit/es6/default-parameters.js
new file mode 100644
index 0000000..4e0bf54
--- /dev/null
+++ b/test/mjsunit/es6/default-parameters.js
@@ -0,0 +1,363 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+(function TestDefaults() {
+ function f1(x = 1) { return x }
+ assertEquals(1, f1());
+ assertEquals(1, f1(undefined));
+ assertEquals(2, f1(2));
+ assertEquals(null, f1(null));
+
+ function f2(x, y = x) { return x + y; }
+ assertEquals(8, f2(4));
+ assertEquals(8, f2(4, undefined));
+ assertEquals(6, f2(4, 2));
+
+ function f3(x = 1, y) { return x + y; }
+ assertEquals(8, f3(5, 3));
+ assertEquals(3, f3(undefined, 2));
+ assertEquals(6, f3(4, 2));
+
+ function f4(x = () => 1) { return x() }
+ assertEquals(1, f4());
+ assertEquals(1, f4(undefined));
+ assertEquals(2, f4(() => 2));
+ assertThrows(() => f4(null), TypeError);
+
+ function f5(x, y = () => x) { return x + y(); }
+ assertEquals(8, f5(4));
+ assertEquals(8, f5(4, undefined));
+ assertEquals(6, f5(4, () => 2));
+
+ function f6(x = {a: 1, m() { return 2 }}) { return x.a + x.m(); }
+ assertEquals(3, f6());
+ assertEquals(3, f6(undefined));
+ assertEquals(5, f6({a: 2, m() { return 3 }}));
+
+ var g1 = (x = 1) => { return x };
+ assertEquals(1, g1());
+ assertEquals(1, g1(undefined));
+ assertEquals(2, g1(2));
+ assertEquals(null, g1(null));
+
+ var g2 = (x, y = x) => { return x + y; };
+ assertEquals(8, g2(4));
+ assertEquals(8, g2(4, undefined));
+ assertEquals(6, g2(4, 2));
+
+ var g3 = (x = 1, y) => { return x + y; };
+ assertEquals(8, g3(5, 3));
+ assertEquals(3, g3(undefined, 2));
+ assertEquals(6, g3(4, 2));
+
+ var g4 = (x = () => 1) => { return x() };
+ assertEquals(1, g4());
+ assertEquals(1, g4(undefined));
+ assertEquals(2, g4(() => 2));
+ assertThrows(() => g4(null), TypeError);
+
+ var g5 = (x, y = () => x) => { return x + y(); };
+ assertEquals(8, g5(4));
+ assertEquals(8, g5(4, undefined));
+ assertEquals(6, g5(4, () => 2));
+
+ var g6 = (x = {a: 1, m() { return 2 }}) => { return x.a + x.m(); };
+ assertEquals(3, g6());
+ assertEquals(3, g6(undefined));
+ assertEquals(5, g6({a: 2, m() { return 3 }}));
+}());
+
+
+(function TestEvalInParameters() {
+ function f1(x = eval(0)) { return x }
+ assertEquals(0, f1());
+ function f2(x = () => eval(1)) { return x() }
+ assertEquals(1, f2());
+})();
+
+
+(function TestParameterScopingSloppy() {
+ var x = 1;
+
+ function f1(a = x) { var x = 2; return a; }
+ assertEquals(1, f1());
+ function f2(a = x) { function x() {}; return a; }
+ assertEquals(1, f2());
+ function f3(a = eval("x")) { var x; return a; }
+ assertEquals(1, f3());
+ function f31(a = eval("'use strict'; x")) { var x; return a; }
+ assertEquals(1, f31());
+ function f4(a = function() { return x }) { var x; return a(); }
+ assertEquals(1, f4());
+ function f5(a = () => x) { var x; return a(); }
+ assertEquals(1, f5());
+ function f6(a = () => eval("x")) { var x; return a(); }
+ assertEquals(1, f6());
+ function f61(a = () => { 'use strict'; return eval("x") }) { var x; return a(); }
+ assertEquals(1, f61());
+ function f62(a = () => eval("'use strict'; x")) { var x; return a(); }
+ assertEquals(1, f62());
+
+ var g1 = (a = x) => { var x = 2; return a; };
+ assertEquals(1, g1());
+ var g2 = (a = x) => { function x() {}; return a; };
+ assertEquals(1, g2());
+ var g3 = (a = eval("x")) => { var x; return a; };
+ assertEquals(1, g3());
+ var g31 = (a = eval("'use strict'; x")) => { var x; return a; };
+ assertEquals(1, g31());
+ var g4 = (a = function() { return x }) => { var x; return a(); };
+ assertEquals(1, g4());
+ var g5 = (a = () => x) => { var x; return a(); };
+ assertEquals(1, g5());
+ var g6 = (a = () => eval("x")) => { var x; return a(); };
+ assertEquals(1, g6());
+ var g61 = (a = () => { 'use strict'; return eval("x") }) => { var x; return a(); };
+ assertEquals(1, g61());
+ var g62 = (a = () => eval("'use strict'; x")) => { var x; return a(); };
+ assertEquals(1, g62());
+
+ var f11 = function f(x = f) { var f; return x; }
+ assertSame(f11, f11());
+ var f12 = function f(x = f) { function f() {}; return x; }
+ assertSame(f12, f12());
+ var f13 = function f(f = 7, x = f) { return x; }
+ assertSame(7, f13());
+
+ var o1 = {f: function(x = this) { return x; }};
+ assertSame(o1, o1.f());
+ assertSame(1, o1.f(1));
+})();
+
+(function TestParameterScopingStrict() {
+ "use strict";
+ var x = 1;
+
+ function f1(a = x) { let x = 2; return a; }
+ assertEquals(1, f1());
+ function f2(a = x) { const x = 2; return a; }
+ assertEquals(1, f2());
+ function f3(a = x) { function x() {}; return a; }
+ assertEquals(1, f3());
+ function f4(a = eval("x")) { var x; return a; }
+ assertEquals(1, f4());
+ function f5(a = () => eval("x")) { var x; return a(); }
+ assertEquals(1, f5());
+
+ var g1 = (a = x) => { let x = 2; return a; };
+ assertEquals(1, g1());
+ var g2 = (a = x) => { const x = 2; return a; };
+ assertEquals(1, g2());
+ var g3 = (a = x) => { function x() {}; return a; };
+ assertEquals(1, g3());
+ var g4 = (a = eval("x")) => { var x; return a; };
+ assertEquals(1, g4());
+ var g5 = (a = () => eval("x")) => { var x; return a(); };
+ assertEquals(1, g5());
+
+ var f11 = function f(x = f) { let f; return x; }
+ assertSame(f11, f11());
+ var f12 = function f(x = f) { const f = 0; return x; }
+ assertSame(f12, f12());
+ var f13 = function f(x = f) { function f() {}; return x; }
+ assertSame(f13, f13());
+})();
+
+(function TestSloppyEvalScoping() {
+ var x = 1;
+
+ function f1(y = eval("var x = 2")) { with ({}) { return x; } }
+ assertEquals(1, f1());
+ function f2(y = eval("var x = 2"), z = x) { return z; }
+ assertEquals(1, f2());
+ assertEquals(1, f2(0));
+ function f3(y = eval("var x = 2"), z = eval("x")) { return z; }
+ assertEquals(1, f3());
+ assertEquals(1, f3(0));
+ function f8(y = (eval("var x = 2"), x)) { return y; }
+ assertEquals(2, f8());
+ assertEquals(0, f8(0));
+
+ function f11(z = eval("var y = 2")) { return y; }
+ assertThrows(f11, ReferenceError);
+ function f12(z = eval("var y = 2"), b = y) {}
+ assertThrows(f12, ReferenceError);
+ function f13(z = eval("var y = 2"), b = eval("y")) {}
+ assertThrows(f13, ReferenceError);
+
+ function f21(f = () => x) { eval("var x = 2"); return f() }
+ assertEquals(1, f21());
+ assertEquals(3, f21(() => 3));
+ function f22(f = () => eval("x")) { eval("var x = 2"); return f() }
+ assertEquals(1, f22());
+ assertEquals(3, f22(() => 3));
+
+ var g1 = (y = eval("var x = 2")) => { with ({}) { return x; } };
+ assertEquals(1, g1());
+ var g2 = (y = eval("var x = 2"), z = x) => { return z; };
+ assertEquals(1, g2());
+ assertEquals(1, g2(0));
+ var g3 = (y = eval("var x = 2"), z = eval("x")) => { return z; };
+ assertEquals(1, g3());
+ assertEquals(1, g3(0));
+ var g8 = (y = (eval("var x = 2"), x)) => { return y; };
+ assertEquals(2, g8());
+ assertEquals(0, g8(0));
+
+ var g11 = (z = eval("var y = 2")) => { return y; };
+ assertThrows(g11, ReferenceError);
+ var g12 = (z = eval("var y = 2"), b = y) => {};
+ assertThrows(g12, ReferenceError);
+ var g13 = (z = eval("var y = 2"), b = eval("y")) => {};
+ assertThrows(g13, ReferenceError);
+
+ var g21 = (f = () => x) => { eval("var x = 2"); return f() };
+ assertEquals(1, g21());
+ assertEquals(3, g21(() => 3));
+ var g22 = (f = () => eval("x")) => { eval("var x = 2"); return f() };
+ assertEquals(1, g22());
+ assertEquals(3, g22(() => 3));
+})();
+
+
+(function TestStrictEvalScoping() {
+ 'use strict';
+ var x = 1;
+
+ function f1(y = eval("var x = 2")) { return x; }
+ assertEquals(1, f1());
+ function f2(y = eval("var x = 2"), z = x) { return z; }
+ assertEquals(1, f2());
+ assertEquals(1, f2(0));
+ function f3(y = eval("var x = 2"), z = eval("x")) { return z; }
+ assertEquals(1, f3());
+ assertEquals(1, f3(0));
+ function f8(y = (eval("var x = 2"), x)) { return y; }
+ assertEquals(1, f8());
+ assertEquals(0, f8(0));
+
+ function f11(z = eval("var y = 2")) { return y; }
+ assertThrows(f11, ReferenceError);
+ function f12(z = eval("var y = 2"), b = y) {}
+ assertThrows(f12, ReferenceError);
+ function f13(z = eval("var y = 2"), b = eval("y")) {}
+ assertThrows(f13, ReferenceError);
+
+ function f21(f = () => x) { eval("var x = 2"); return f() }
+ assertEquals(1, f21());
+ assertEquals(3, f21(() => 3));
+ function f22(f = () => eval("x")) { eval("var x = 2"); return f() }
+ assertEquals(1, f22());
+ assertEquals(3, f22(() => 3));
+})();
+
+(function TestParameterTDZSloppy() {
+ function f1(a = x, x) { return a }
+ assertThrows(() => f1(undefined, 4), ReferenceError);
+ assertEquals(4, f1(4, 5));
+ function f2(a = eval("x"), x) { return a }
+ assertThrows(() => f2(undefined, 4), ReferenceError);
+ assertEquals(4, f2(4, 5));
+ function f3(a = eval("'use strict'; x"), x) { return a }
+ assertThrows(() => f3(undefined, 4), ReferenceError);
+ assertEquals(4, f3(4, 5));
+ function f4(a = () => x, x) { return a() }
+ assertEquals(4, f4(() => 4, 5));
+ function f5(a = () => eval("x"), x) { return a() }
+ assertEquals(4, f5(() => 4, 5));
+ function f6(a = () => eval("'use strict'; x"), x) { return a() }
+ assertEquals(4, f6(() => 4, 5));
+
+ function f11(a = x, x = 2) { return a }
+ assertThrows(() => f11(), ReferenceError);
+ assertThrows(() => f11(undefined), ReferenceError);
+ assertThrows(() => f11(undefined, 4), ReferenceError);
+ assertEquals(4, f1(4, 5));
+ function f12(a = eval("x"), x = 2) { return a }
+ assertThrows(() => f12(), ReferenceError);
+ assertThrows(() => f12(undefined), ReferenceError);
+ assertThrows(() => f12(undefined, 4), ReferenceError);
+ assertEquals(4, f12(4, 5));
+ function f13(a = eval("'use strict'; x"), x = 2) { return a }
+ assertThrows(() => f13(), ReferenceError);
+ assertThrows(() => f13(undefined), ReferenceError);
+ assertThrows(() => f13(undefined, 4), ReferenceError);
+ assertEquals(4, f13(4, 5));
+
+ function f21(x = function() { return a }, ...a) { return x()[0] }
+ assertEquals(4, f21(undefined, 4));
+ function f22(x = () => a, ...a) { return x()[0] }
+ assertEquals(4, f22(undefined, 4));
+ function f23(x = () => eval("a"), ...a) { return x()[0] }
+ assertEquals(4, f23(undefined, 4));
+ function f24(x = () => {'use strict'; return eval("a") }, ...a) {
+ return x()[0]
+ }
+ assertEquals(4, f24(undefined, 4));
+ function f25(x = () => eval("'use strict'; a"), ...a) { return x()[0] }
+ assertEquals(4, f25(undefined, 4));
+
+ var g1 = (x = function() { return a }, ...a) => { return x()[0] };
+ assertEquals(4, g1(undefined, 4));
+ var g2 = (x = () => a, ...a) => { return x()[0] };
+ assertEquals(4, g2(undefined, 4));
+})();
+
+(function TestParameterTDZStrict() {
+ "use strict";
+
+ function f1(a = eval("x"), x) { return a }
+ assertThrows(() => f1(undefined, 4), ReferenceError);
+ assertEquals(4, f1(4, 5));
+ function f2(a = () => eval("x"), x) { return a() }
+ assertEquals(4, f2(() => 4, 5));
+
+ function f11(a = eval("x"), x = 2) { return a }
+ assertThrows(() => f11(), ReferenceError);
+ assertThrows(() => f11(undefined), ReferenceError);
+ assertThrows(() => f11(undefined, 4), ReferenceError);
+ assertEquals(4, f11(4, 5));
+
+ function f21(x = () => eval("a"), ...a) { return x()[0] }
+ assertEquals(4, f21(undefined, 4));
+})();
+
+(function TestArgumentsForNonSimpleParameters() {
+ function f1(x = 900) { arguments[0] = 1; return x }
+ assertEquals(9, f1(9));
+ assertEquals(900, f1());
+ function f2(x = 1001) { x = 2; return arguments[0] }
+ assertEquals(10, f2(10));
+ assertEquals(undefined, f2());
+}());
+
+
+(function TestFunctionLength() {
+ assertEquals(0, (function(x = 1) {}).length);
+ assertEquals(0, (function(x = 1, ...a) {}).length);
+ assertEquals(1, (function(x, y = 1) {}).length);
+ assertEquals(1, (function(x, y = 1, ...a) {}).length);
+ assertEquals(2, (function(x, y, z = 1) {}).length);
+ assertEquals(2, (function(x, y, z = 1, ...a) {}).length);
+ assertEquals(1, (function(x, y = 1, z) {}).length);
+ assertEquals(1, (function(x, y = 1, z, ...a) {}).length);
+ assertEquals(1, (function(x, y = 1, z, v = 2) {}).length);
+ assertEquals(1, (function(x, y = 1, z, v = 2, ...a) {}).length);
+})();
+
+(function TestDirectiveThrows() {
+ "use strict";
+
+ assertThrows(function(){ eval("function(x=1){'use strict';}") }, SyntaxError);
+ assertThrows(function(){ eval("(x=1) => {'use strict';}") }, SyntaxError);
+ assertThrows(
+ function(){ eval("(class{foo(x=1) {'use strict';}});") }, SyntaxError);
+
+ assertThrows(
+ function(){ eval("function(a, x=1){'use strict';}") }, SyntaxError);
+ assertThrows(function(){ eval("(a, x=1) => {'use strict';}") }, SyntaxError);
+ assertThrows(
+ function(){ eval("(class{foo(a, x=1) {'use strict';}});") }, SyntaxError);
+})();
diff --git a/test/mjsunit/es6/destructuring-assignment-lazy.js b/test/mjsunit/es6/destructuring-assignment-lazy.js
new file mode 100644
index 0000000..fdae30e
--- /dev/null
+++ b/test/mjsunit/es6/destructuring-assignment-lazy.js
@@ -0,0 +1,14 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --min-preparse-length=0
+
+function f() {
+ var a, b;
+ [ a, b ] = [1, 2];
+ assertEquals(1, a);
+ assertEquals(2, b);
+}
+
+f();
diff --git a/test/mjsunit/es6/destructuring-assignment.js b/test/mjsunit/es6/destructuring-assignment.js
new file mode 100644
index 0000000..df9bb0e
--- /dev/null
+++ b/test/mjsunit/es6/destructuring-assignment.js
@@ -0,0 +1,480 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// script-level tests
+var ox, oy = {}, oz;
+({
+ x: ox,
+ y: oy.value,
+ y2: oy["value2"],
+ z: ({ set v(val) { oz = val; } }).v
+} = {
+ x: "value of x",
+ y: "value of y1",
+ y2: "value of y2",
+ z: "value of z"
+});
+assertEquals("value of x", ox);
+assertEquals("value of y1", oy.value);
+assertEquals("value of y2", oy.value2);
+assertEquals("value of z", oz);
+
+[ox, oy.value, oy["value2"], ...{ set v(val) { oz = val; } }.v] = [
+ 1007,
+ 798432,
+ 555,
+ 1, 2, 3, 4, 5
+];
+assertEquals(ox, 1007);
+assertEquals(oy.value, 798432);
+assertEquals(oy.value2, 555);
+assertEquals(oz, [1, 2, 3, 4, 5]);
+
+
+(function testInFunction() {
+ var x, y = {}, z;
+ ({
+ x: x,
+ y: y.value,
+ y2: y["value2"],
+ z: ({ set v(val) { z = val; } }).v
+ } = {
+ x: "value of x",
+ y: "value of y1",
+ y2: "value of y2",
+ z: "value of z"
+ });
+ assertEquals("value of x", x);
+ assertEquals("value of y1", y.value);
+ assertEquals("value of y2", y.value2);
+ assertEquals("value of z", z);
+
+ [x, y.value, y["value2"], ...{ set v(val) { z = val; } }.v] = [
+ 1007,
+ 798432,
+ 555,
+ 1, 2, 3, 4, 5
+ ];
+ assertEquals(x, 1007);
+ assertEquals(y.value, 798432);
+ assertEquals(y.value2, 555);
+ assertEquals(z, [1, 2, 3, 4, 5]);
+})();
+
+
+(function testArrowFunctionInitializers() {
+ var fn = (config = {
+ value: defaults.value,
+ nada: { nada: defaults.nada } = { nada: "nothing" }
+ } = { value: "BLAH" }) => config;
+ var defaults = {};
+ assertEquals({ value: "BLAH" }, fn());
+ assertEquals("BLAH", defaults.value);
+ assertEquals("nothing", defaults.nada);
+})();
+
+
+(function testArrowFunctionInitializers2() {
+ var fn = (config = [
+ defaults.value,
+ { nada: defaults.nada } = { nada: "nothing" }
+ ] = ["BLAH"]) => config;
+ var defaults = {};
+ assertEquals(["BLAH"], fn());
+ assertEquals("BLAH", defaults.value);
+ assertEquals("nothing", defaults.nada);
+})();
+
+
+(function testFunctionInitializers() {
+ function fn(config = {
+ value: defaults.value,
+ nada: { nada: defaults.nada } = { nada: "nothing" }
+ } = { value: "BLAH" }) {
+ return config;
+ }
+ var defaults = {};
+ assertEquals({ value: "BLAH" }, fn());
+ assertEquals("BLAH", defaults.value);
+ assertEquals("nothing", defaults.nada);
+})();
+
+
+(function testFunctionInitializers2() {
+ function fn(config = [
+ defaults.value,
+ { nada: defaults.nada } = { nada: "nothing" }
+ ] = ["BLAH"]) { return config; }
+ var defaults = {};
+ assertEquals(["BLAH"], fn());
+ assertEquals("BLAH", defaults.value);
+ assertEquals("nothing", defaults.nada);
+})();
+
+
+(function testDeclarationInitializers() {
+ var defaults = {};
+ var { value } = { value: defaults.value } = { value: "BLAH" };
+ assertEquals("BLAH", value);
+ assertEquals("BLAH", defaults.value);
+})();
+
+
+(function testDeclarationInitializers2() {
+ var defaults = {};
+ var [value] = [defaults.value] = ["BLAH"];
+ assertEquals("BLAH", value);
+ assertEquals("BLAH", defaults.value);
+})();
+
+
+(function testObjectLiteralProperty() {
+ var ext = {};
+ var obj = {
+ a: { b: ext.b, c: ext["c"], d: { set v(val) { ext.d = val; } }.v } = {
+ b: "b", c: "c", d: "d" }
+ };
+ assertEquals({ b: "b", c: "c", d: "d" }, ext);
+ assertEquals({ a: { b: "b", c: "c", d: "d" } }, obj);
+})();
+
+
+(function testArrayLiteralProperty() {
+ var ext = {};
+ var obj = [
+ ...[ ext.b, ext["c"], { set v(val) { ext.d = val; } }.v ] = [
+ "b", "c", "d" ]
+ ];
+ assertEquals({ b: "b", c: "c", d: "d" }, ext);
+ assertEquals([ "b", "c", "d" ], obj);
+})();
+
+
+// TODO(caitp): add similar test for ArrayPatterns, once Proxies support
+// delegating symbol-keyed get/set.
+(function testObjectPatternOperationOrder() {
+ var steps = [];
+ var store = {};
+ function computePropertyName(name) {
+ steps.push("compute name: " + name);
+ return name;
+ }
+ function loadValue(descr, value) {
+ steps.push("load: " + descr + " > " + value);
+ return value;
+ }
+ function storeValue(descr, name, value) {
+ steps.push("store: " + descr + " = " + value);
+ store[name] = value;
+ }
+ var result = {
+ get a() { assertUnreachable(); },
+ set a(value) { storeValue("result.a", "a", value); },
+ get b() { assertUnreachable(); },
+ set b(value) { storeValue("result.b", "b", value); }
+ };
+
+ ({
+ obj: {
+ x: result.a = 10,
+ [computePropertyName("y")]: result.b = false,
+ } = {}
+ } = { obj: {
+ get x() { return loadValue(".temp.obj.x", undefined); },
+ set x(value) { assertUnreachable(); },
+ get y() { return loadValue(".temp.obj.y", undefined); },
+ set y(value) { assertUnreachable(); }
+ }});
+
+ assertPropertiesEqual({
+ a: 10,
+ b: false
+ }, store);
+
+ assertArrayEquals([
+ "load: .temp.obj.x > undefined",
+ "store: result.a = 10",
+
+ "compute name: y",
+ "load: .temp.obj.y > undefined",
+ "store: result.b = false"
+ ], steps);
+
+ steps = [];
+
+ ({
+ obj: {
+ x: result.a = 50,
+ [computePropertyName("y")]: result.b = "hello",
+ } = {}
+ } = { obj: {
+ get x() { return loadValue(".temp.obj.x", 20); },
+ set x(value) { assertUnreachable(); },
+ get y() { return loadValue(".temp.obj.y", true); },
+ set y(value) { assertUnreachable(); }
+ }});
+
+ assertPropertiesEqual({
+ a: 20,
+ b: true
+ }, store);
+
+ assertArrayEquals([
+ "load: .temp.obj.x > 20",
+ "store: result.a = 20",
+ "compute name: y",
+ "load: .temp.obj.y > true",
+ "store: result.b = true",
+ ], steps);
+})();
+
+// Credit to Mike Pennisi and other Test262 contributors for originally writing
+// the testse the following are based on.
+(function testArrayElision() {
+ var value = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+ var a, obj = {};
+ var result = [, a, , obj.b, , ...obj["rest"]] = value;
+
+ assertEquals(result, value);
+ assertEquals(2, a);
+ assertEquals(4, obj.b);
+ assertArrayEquals([6, 7, 8, 9], obj.rest);
+})();
+
+(function testArrayElementInitializer() {
+ function test(value, initializer, expected) {
+ var a, obj = {};
+ var initialized = false;
+ var shouldBeInitialized = value[0] === undefined;
+ assertEquals(value, [ a = (initialized = true, initializer) ] = value);
+ assertEquals(expected, a);
+ assertEquals(shouldBeInitialized, initialized);
+
+ var initialized2 = false;
+ assertEquals(value, [ obj.a = (initialized2 = true, initializer) ] = value);
+ assertEquals(expected, obj.a);
+ assertEquals(shouldBeInitialized, initialized2);
+ }
+
+ test([], "BAM!", "BAM!");
+ test([], "BOOP!", "BOOP!");
+ test([null], 123, null);
+ test([undefined], 456, 456);
+ test([,], "PUPPIES", "PUPPIES");
+
+ (function accept_IN() {
+ var value = [], x;
+ assertEquals(value, [ x = 'x' in {} ] = value);
+ assertEquals(false, x);
+ })();
+
+ (function ordering() {
+ var x = 0, a, b, value = [];
+ assertEquals(value, [ a = x += 1, b = x *= 2 ] = value);
+ assertEquals(1, a);
+ assertEquals(2, b);
+ assertEquals(2, x);
+ })();
+
+ (function yieldExpression() {
+ var value = [], it, result, x;
+ it = (function*() {
+ result = [ x = yield ] = value;
+ })();
+ var next = it.next();
+
+ assertEquals(undefined, result);
+ assertEquals(undefined, next.value);
+ assertEquals(false, next.done);
+ assertEquals(undefined, x);
+
+ next = it.next(86);
+
+ assertEquals(value, result);
+ assertEquals(undefined, next.value);
+ assertEquals(true, next.done);
+ assertEquals(86, x);
+ })();
+
+ (function yieldIdentifier() {
+ var value = [], yield = "BOOP!", x;
+ assertEquals(value, [ x = yield ] = value);
+ assertEquals("BOOP!", x);
+ })();
+
+ assertThrows(function let_TDZ() {
+ "use strict";
+ var x;
+ [ x = y ] = [];
+ let y;
+ }, ReferenceError);
+})();
+
+
+(function testArrayElementNestedPattern() {
+ assertThrows(function nestedArrayRequireObjectCoercibleNull() {
+ var x; [ [ x ] ] = [ null ];
+ }, TypeError);
+
+ assertThrows(function nestedArrayRequireObjectCoercibleUndefined() {
+ var x; [ [ x ] ] = [ undefined ];
+ }, TypeError);
+
+ assertThrows(function nestedArrayRequireObjectCoercibleUndefined2() {
+ var x; [ [ x ] ] = [ ];
+ }, TypeError);
+
+ assertThrows(function nestedArrayRequireObjectCoercibleUndefined3() {
+ var x; [ [ x ] ] = [ , ];
+ }, TypeError);
+
+ assertThrows(function nestedObjectRequireObjectCoercibleNull() {
+ var x; [ { x } ] = [ null ];
+ }, TypeError);
+
+ assertThrows(function nestedObjectRequireObjectCoercibleUndefined() {
+ var x; [ { x } ] = [ undefined ];
+ }, TypeError);
+
+ assertThrows(function nestedObjectRequireObjectCoercibleUndefined2() {
+ var x; [ { x } ] = [ ];
+ }, TypeError);
+
+ assertThrows(function nestedObjectRequireObjectCoercibleUndefined3() {
+ var x; [ { x } ] = [ , ];
+ }, TypeError);
+
+ (function nestedArray() {
+ var x, value = [ [ "zap", "blonk" ] ];
+ assertEquals(value, [ [ , x ] ] = value);
+ assertEquals("blonk", x);
+ })();
+
+ (function nestedObject() {
+ var x, value = [ { a: "zap", b: "blonk" } ];
+ assertEquals(value, [ { b: x } ] = value);
+ assertEquals("blonk", x);
+ })();
+})();
+
+(function testArrayRestElement() {
+ (function testBasic() {
+ var x, rest, array = [1, 2, 3];
+ assertEquals(array, [x, ...rest] = array);
+ assertEquals(1, x);
+ assertEquals([2, 3], rest);
+
+ array = [4, 5, 6];
+ assertEquals(array, [, ...rest] = array);
+ assertEquals([5, 6], rest);
+
+ })();
+
+ (function testNestedRestObject() {
+ var value = [1, 2, 3], x;
+ assertEquals(value, [...{ 1: x }] = value);
+ assertEquals(2, x);
+ })();
+
+ (function iterable() {
+ var count = 0;
+ var x, y, z;
+ function* g() {
+ count++;
+ yield;
+ count++;
+ yield;
+ count++;
+ yield;
+ }
+ var it = g();
+ assertEquals(it, [...x] = it);
+ assertEquals([undefined, undefined, undefined], x);
+ assertEquals(3, count);
+
+ it = [g()];
+ assertEquals(it, [ [...y] ] = it);
+ assertEquals([undefined, undefined, undefined], y);
+ assertEquals(6, count);
+
+ it = { a: g() };
+ assertEquals(it, { a: [...z] } = it);
+ assertEquals([undefined, undefined, undefined], z);
+ assertEquals(9, count);
+ })();
+})();
+
+(function testRequireObjectCoercible() {
+ assertThrows(() => ({} = undefined), TypeError);
+ assertThrows(() => ({} = null), TypeError);
+ assertThrows(() => [] = undefined, TypeError);
+ assertThrows(() => [] = null, TypeError);
+ assertEquals("test", ({} = "test"));
+ assertEquals("test", [] = "test");
+ assertEquals(123, ({} = 123));
+})();
+
+(function testConstReassignment() {
+ "use strict";
+ const c = "untouchable";
+ assertThrows(() => { [ c ] = [ "nope!" ]; }, TypeError);
+ assertThrows(() => { [ [ c ] ] = [ [ "nope!" ] ]; }, TypeError);
+ assertThrows(() => { [ { c } ] = [ { c: "nope!" } ]; }, TypeError);
+ assertThrows(() => { ({ c } = { c: "nope!" }); }, TypeError);
+ assertThrows(() => { ({ a: { c } } = { a: { c: "nope!" } }); }, TypeError);
+ assertThrows(() => { ({ a: [ c ] } = { a: [ "nope!" ] }); }, TypeError);
+ assertEquals("untouchable", c);
+})();
+
+(function testForIn() {
+ var log = [];
+ var x = {};
+ var object = {
+ "Apenguin": 1,
+ "\u{1F382}cake": 2,
+ "Bpuppy": 3,
+ "Cspork": 4
+ };
+ for ([x.firstLetter, ...x.rest] in object) {
+ if (x.firstLetter === "A") {
+ assertEquals(["p", "e", "n", "g", "u", "i", "n"], x.rest);
+ continue;
+ }
+ if (x.firstLetter === "C") {
+ assertEquals(["s", "p", "o", "r", "k"], x.rest);
+ break;
+ }
+ log.push({ firstLetter: x.firstLetter, rest: x.rest });
+ }
+ assertEquals([
+ { firstLetter: "\u{1F382}", rest: ["c", "a", "k", "e"] },
+ { firstLetter: "B", rest: ["p", "u", "p", "p", "y"] },
+ ], log);
+})();
+
+(function testForOf() {
+ var log = [];
+ var x = {};
+ var names = [
+ "Apenguin",
+ "\u{1F382}cake",
+ "Bpuppy",
+ "Cspork"
+ ];
+ for ([x.firstLetter, ...x.rest] of names) {
+ if (x.firstLetter === "A") {
+ assertEquals(["p", "e", "n", "g", "u", "i", "n"], x.rest);
+ continue;
+ }
+ if (x.firstLetter === "C") {
+ assertEquals(["s", "p", "o", "r", "k"], x.rest);
+ break;
+ }
+ log.push({ firstLetter: x.firstLetter, rest: x.rest });
+ }
+ assertEquals([
+ { firstLetter: "\u{1F382}", rest: ["c", "a", "k", "e"] },
+ { firstLetter: "B", rest: ["p", "u", "p", "p", "y"] },
+ ], log);
+})();
diff --git a/test/mjsunit/es6/destructuring-parameters-literalcount-nolazy.js b/test/mjsunit/es6/destructuring-parameters-literalcount-nolazy.js
new file mode 100644
index 0000000..0317509
--- /dev/null
+++ b/test/mjsunit/es6/destructuring-parameters-literalcount-nolazy.js
@@ -0,0 +1,40 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Flags: --no-lazy --allow-natives-syntax
+
+
+var t1 = [1];
+var t2 = [2];
+var t3 = [3];
+var t4 = [4];
+var t5 = [5];
+function g({x = {a:10,b:20}},
+ {y = [1,2,3],
+ n = [],
+ p = /abc/}) {
+ assertSame(10, x.a);
+ assertSame(20, x.b);
+ assertSame(2, y[1]);
+ assertSame(0, n.length);
+ assertTrue(p.test("abc"));
+}
+g({},{});
+%OptimizeFunctionOnNextCall(g);
+g({},{});
+
+
+var h = ({x = {a:10,b:20}},
+ {y = [1,2,3],
+ n = [],
+ p = /abc/ }) => {
+ assertSame(10, x.a);
+ assertSame(20, x.b);
+ assertSame(2, y[1]);
+ assertSame(0, n.length);
+ assertTrue(p.test("abc"));
+ };
+h({},{});
+%OptimizeFunctionOnNextCall(h);
+h({},{});
diff --git a/test/mjsunit/es6/destructuring-parameters-literalcount.js b/test/mjsunit/es6/destructuring-parameters-literalcount.js
new file mode 100644
index 0000000..77a3226
--- /dev/null
+++ b/test/mjsunit/es6/destructuring-parameters-literalcount.js
@@ -0,0 +1,40 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Flags: --allow-natives-syntax
+
+
+var t1 = [1];
+var t2 = [2];
+var t3 = [3];
+var t4 = [4];
+var t5 = [5];
+function g({x = {a:10,b:20}},
+ {y = [1,2,3],
+ n = [],
+ p = /abc/}) {
+ assertSame(10, x.a);
+ assertSame(20, x.b);
+ assertSame(2, y[1]);
+ assertSame(0, n.length);
+ assertTrue(p.test("abc"));
+}
+g({},{});
+%OptimizeFunctionOnNextCall(g);
+g({},{});
+
+
+var h = ({x = {a:10,b:20}},
+ {y = [1,2,3],
+ n = [],
+ p = /abc/ }) => {
+ assertSame(10, x.a);
+ assertSame(20, x.b);
+ assertSame(2, y[1]);
+ assertSame(0, n.length);
+ assertTrue(p.test("abc"));
+ };
+h({},{});
+%OptimizeFunctionOnNextCall(h);
+h({},{});
diff --git a/test/mjsunit/es6/destructuring.js b/test/mjsunit/es6/destructuring.js
new file mode 100644
index 0000000..1f16c45
--- /dev/null
+++ b/test/mjsunit/es6/destructuring.js
@@ -0,0 +1,1191 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function TestObjectLiteralPattern() {
+ var { x : x, y : y, get, set } = { x : 1, y : 2, get: 3, set: 4 };
+ assertEquals(1, x);
+ assertEquals(2, y);
+ assertEquals(3, get);
+ assertEquals(4, set);
+
+ var {z} = { z : 3 };
+ assertEquals(3, z);
+
+
+ var sum = 0;
+ for (var {z} = { z : 3 }; z != 0; z--) {
+ sum += z;
+ }
+ assertEquals(6, sum);
+
+
+ var log = [];
+ var o = {
+ get x() {
+ log.push("x");
+ return 0;
+ },
+ get y() {
+ log.push("y");
+ return {
+ get z() { log.push("z"); return 1; }
+ }
+ }
+ };
+ var { x : x0, y : { z : z1 }, x : x1 } = o;
+ assertSame(0, x0);
+ assertSame(1, z1);
+ assertSame(0, x1);
+ assertArrayEquals(["x", "y", "z", "x"], log);
+}());
+
+
+(function TestObjectLiteralPatternInitializers() {
+ var { x : x, y : y = 2 } = { x : 1 };
+ assertEquals(1, x);
+ assertEquals(2, y);
+
+ var {z = 3} = {};
+ assertEquals(3, z);
+
+ var sum = 0;
+ for (var {z = 3} = {}; z != 0; z--) {
+ sum += z;
+ }
+ assertEquals(6, sum);
+
+ var log = [];
+ var o = {
+ get x() {
+ log.push("x");
+ return undefined;
+ },
+ get y() {
+ log.push("y");
+ return {
+ get z() { log.push("z"); return undefined; }
+ }
+ }
+ };
+ var { x : x0 = 0, y : { z : z1 = 1}, x : x1 = 0} = o;
+ assertSame(0, x0);
+ assertSame(1, z1);
+ assertSame(0, x1);
+ assertArrayEquals(["x", "y", "z", "x"], log);
+}());
+
+
+(function TestObjectLiteralPatternLexicalInitializers() {
+ 'use strict';
+ let { x : x, y : y = 2 } = { x : 1 };
+ assertEquals(1, x);
+ assertEquals(2, y);
+
+ let {z = 3} = {};
+ assertEquals(3, z);
+
+ let log = [];
+ let o = {
+ get x() {
+ log.push("x");
+ return undefined;
+ },
+ get y() {
+ log.push("y");
+ return {
+ get z() { log.push("z"); return undefined; }
+ }
+ }
+ };
+
+ let { x : x0 = 0, y : { z : z1 = 1 }, x : x1 = 5} = o;
+ assertSame(0, x0);
+ assertSame(1, z1);
+ assertSame(5, x1);
+ assertArrayEquals(["x", "y", "z", "x"], log);
+
+ let sum = 0;
+ for (let {x = 0, z = 3} = {}; z != 0; z--) {
+ assertEquals(0, x);
+ sum += z;
+ }
+ assertEquals(6, sum);
+}());
+
+
+(function TestObjectLiteralPatternLexical() {
+ 'use strict';
+ let { x : x, y : y } = { x : 1, y : 2 };
+ assertEquals(1, x);
+ assertEquals(2, y);
+
+ let {z} = { z : 3 };
+ assertEquals(3, z);
+
+ let log = [];
+ let o = {
+ get x() {
+ log.push("x");
+ return 0;
+ },
+ get y() {
+ log.push("y");
+ return {
+ get z() { log.push("z"); return 1; }
+ }
+ }
+ };
+ let { x : x0, y : { z : z1 }, x : x1 } = o;
+ assertSame(0, x0);
+ assertSame(1, z1);
+ assertSame(0, x1);
+ assertArrayEquals(["x", "y", "z", "x"], log);
+
+ let sum = 0;
+ for (let {x, z} = { x : 0, z : 3 }; z != 0; z--) {
+ assertEquals(0, x);
+ sum += z;
+ }
+ assertEquals(6, sum);
+}());
+
+
+(function TestObjectLiteralPatternLexicalConst() {
+ 'use strict';
+ const { x : x, y : y } = { x : 1, y : 2 };
+ assertEquals(1, x);
+ assertEquals(2, y);
+
+ assertThrows(function() { x++; }, TypeError);
+ assertThrows(function() { y++; }, TypeError);
+
+ const {z} = { z : 3 };
+ assertEquals(3, z);
+
+ for (const {x, z} = { x : 0, z : 3 }; z != 3 || x != 0;) {
+ assertTrue(false);
+ }
+}());
+
+
+(function TestFailingMatchesSloppy() {
+ var {x, y} = {};
+ assertSame(undefined, x);
+ assertSame(undefined, y);
+
+ var { x : { z1 }, y2} = { x : {}, y2 : 42 }
+ assertSame(undefined, z1);
+ assertSame(42, y2);
+}());
+
+
+(function TestFailingMatchesStrict() {
+ 'use strict';
+ var {x, y} = {};
+ assertSame(undefined, x);
+ assertSame(undefined, y);
+
+ var { x : { z1 }, y2} = { x : {}, y2 : 42 }
+ assertSame(undefined, z1);
+ assertSame(42, y2);
+
+ {
+ let {x1,y1} = {};
+ assertSame(undefined, x1);
+ assertSame(undefined, y1);
+
+ let { x : { z1 }, y2} = { x : {}, y2 : 42 }
+ assertSame(undefined, z1);
+ assertSame(42, y2);
+ }
+}());
+
+
+(function TestTDZInIntializers() {
+ 'use strict';
+ {
+ let {x, y = x} = {x : 42, y : 27};
+ assertSame(42, x);
+ assertSame(27, y);
+ }
+
+ {
+ let {x, y = x + 1} = { x : 42 };
+ assertSame(42, x);
+ assertSame(43, y);
+ }
+ assertThrows(function() {
+ let {x = y, y} = { y : 42 };
+ }, ReferenceError);
+
+ {
+ let {x, y = eval("x+1")} = {x:42};
+ assertEquals(42, x);
+ assertEquals(43, y);
+ }
+
+ {
+ let {x, y = () => eval("x+1")} = {x:42};
+ assertEquals(42, x);
+ assertEquals(43, y());
+ }
+
+ {
+ let {x = function() {return y+1;}, y} = {y:42};
+ assertEquals(43, x());
+ assertEquals(42, y);
+ }
+ {
+ let {x = function() {return eval("y+1");}, y} = {y:42};
+ assertEquals(43, x());
+ assertEquals(42, y);
+ }
+}());
+
+
+(function TestSideEffectsInInitializers() {
+ var callCount = 0;
+ function f(v) { callCount++; return v; }
+
+ callCount = 0;
+ var { x = f(42) } = { x : 27 };
+ assertSame(27, x);
+ assertEquals(0, callCount);
+
+ callCount = 0;
+ var { x = f(42) } = {};
+ assertSame(42, x);
+ assertEquals(1, callCount);
+}());
+
+
+(function TestAssignmentExprInInitializers() {
+ {
+ let x, y;
+ {
+ let { x = y = 1 } = {};
+ assertSame(x, 1);
+ assertSame(y, 1);
+ }
+ assertSame(undefined, x);
+ assertSame(1, y);
+ }
+
+ {
+ let x, y;
+ {
+ let { x: x = y = 1 } = {};
+ assertSame(1, x);
+ assertSame(1, y);
+ }
+ assertSame(undefined, x);
+ assertSame(1, y);
+ }
+
+ {
+ let x, y;
+ {
+ let [ x = y = 1 ] = [];
+ assertSame(1, x);
+ assertSame(1, y);
+ }
+ assertSame(undefined, x);
+ assertSame(1, y);
+ }
+
+ {
+ let x, y;
+ (function({ x = y = 1 }) {}({}));
+ assertSame(undefined, x);
+ assertSame(1, y);
+ }
+
+ {
+ let x, y;
+ (function({ x: x = y = 1 }) {}({}));
+ assertSame(undefined, x);
+ assertSame(1, y);
+ }
+
+ {
+ let x, y;
+ (function([ x = y = 1 ]) {}([]));
+ assertSame(undefined, x);
+ assertSame(1, y);
+ }
+}());
+
+
+(function TestMultipleAccesses() {
+ assertThrows(
+ "'use strict';"+
+ "const {x,x} = {x:1};",
+ SyntaxError);
+
+ assertThrows(
+ "'use strict';"+
+ "let {x,x} = {x:1};",
+ SyntaxError);
+
+ (function() {
+ var {x,x = 2} = {x : 1};
+ assertSame(1, x);
+ }());
+
+ assertThrows(function () {
+ 'use strict';
+ let {x = (function() { x = 2; }())} = {};
+ }, ReferenceError);
+
+ (function() {
+ 'use strict';
+ let {x = (function() { x = 2; }())} = {x:1};
+ assertSame(1, x);
+ }());
+}());
+
+
+(function TestComputedNames() {
+ var x = 1;
+ var {[x]:y} = {1:2};
+ assertSame(2, y);
+
+ (function(){
+ 'use strict';
+ let {[x]:y} = {1:2};
+ assertSame(2, y);
+ }());
+
+ var callCount = 0;
+ function foo(v) { callCount++; return v; }
+
+ (function() {
+ callCount = 0;
+ var {[foo("abc")]:x} = {abc:42};
+ assertSame(42, x);
+ assertEquals(1, callCount);
+ }());
+
+ (function() {
+ 'use strict';
+ callCount = 0;
+ let {[foo("abc")]:x} = {abc:42};
+ assertSame(42, x);
+ assertEquals(1, callCount);
+ }());
+
+ (function() {
+ callCount = 0;
+ var {[foo("abc")]:x} = {};
+ assertSame(undefined, x);
+ assertEquals(1, callCount);
+ }());
+
+ (function() {
+ 'use strict';
+ callCount = 0;
+ let {[foo("abc")]:x} = {};
+ assertSame(undefined, x);
+ assertEquals(1, callCount);
+ }());
+
+ for (val of [null, undefined]) {
+ callCount = 0;
+ assertThrows(function() {
+ var {[foo()]:x} = val;
+ }, TypeError);
+ assertEquals(0, callCount);
+
+ callCount = 0;
+ assertThrows(function() {
+ 'use strict';
+ let {[foo()]:x} = val;
+ }, TypeError);
+ assertEquals(0, callCount);
+ }
+
+ var log = [];
+ var o = {
+ get x() { log.push("get x"); return 1; },
+ get y() { log.push("get y"); return 2; }
+ }
+ function f(v) { log.push("f " + v); return v; }
+
+ (function() {
+ log = [];
+ var { [f('x')]:x, [f('y')]:y } = o;
+ assertSame(1, x);
+ assertSame(2, y);
+ assertArrayEquals(["f x", "get x", "f y", "get y"], log);
+ }());
+
+ (function() {
+ 'use strict';
+ log = [];
+ let { [f('x')]:x, [f('y')]:y } = o;
+ assertSame(1, x);
+ assertSame(2, y);
+ assertArrayEquals(["f x", "get x", "f y", "get y"], log);
+ }());
+
+ (function() {
+ 'use strict';
+ log = [];
+ const { [f('x')]:x, [f('y')]:y } = o;
+ assertSame(1, x);
+ assertSame(2, y);
+ assertArrayEquals(["f x", "get x", "f y", "get y"], log);
+ }());
+}());
+
+
+(function TestExceptions() {
+ for (var val of [null, undefined]) {
+ assertThrows(function() { var {} = val; }, TypeError);
+ assertThrows(function() { var {x} = val; }, TypeError);
+ assertThrows(function() { var { x : {} } = { x : val }; }, TypeError);
+ assertThrows(function() { 'use strict'; let {} = val; }, TypeError);
+ assertThrows(function() { 'use strict'; let {x} = val; }, TypeError);
+ assertThrows(function() { 'use strict'; let { x : {} } = { x : val }; },
+ TypeError);
+ }
+}());
+
+
+(function TestArrayLiteral() {
+ var [a, b, c] = [1, 2, 3];
+ assertSame(1, a);
+ assertSame(2, b);
+ assertSame(3, c);
+}());
+
+(function TestIterators() {
+ var log = [];
+ function* f() {
+ log.push("1");
+ yield 1;
+ log.push("2");
+ yield 2;
+ log.push("3");
+ yield 3;
+ log.push("done");
+ };
+
+ (function() {
+ log = [];
+ var [a, b, c] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertSame(3, c);
+ assertArrayEquals(["1", "2", "3"], log);
+ }());
+
+ (function() {
+ log = [];
+ var [a, b, c, d] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertSame(3, c);
+ assertSame(undefined, d);
+ assertArrayEquals(["1", "2", "3", "done"], log);
+ }());
+
+ (function() {
+ log = [];
+ var [a, , c] = f();
+ assertSame(1, a);
+ assertSame(3, c);
+ assertArrayEquals(["1", "2", "3"], log);
+ }());
+
+ (function() {
+ log = [];
+ var [a, , c, d] = f();
+ assertSame(1, a);
+ assertSame(3, c);
+ assertSame(undefined, d);
+ assertArrayEquals(["1", "2", "3", "done"], log);
+ }());
+
+ (function() {
+ log = [];
+ // last comma is not an elision.
+ var [a, b,] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertArrayEquals(["1", "2"], log);
+ }());
+
+ (function() {
+ log = [];
+ // last comma is not an elision, but the comma before the last is.
+ var [a, b, ,] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertArrayEquals(["1", "2", "3"], log);
+ }());
+
+ (function() {
+ log = [];
+ var [a, ...rest] = f();
+ assertSame(1, a);
+ assertArrayEquals([2,3], rest);
+ assertArrayEquals(["1", "2", "3", "done"], log);
+ }());
+
+ (function() {
+ log = [];
+ var [a, b, c, ...rest] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertSame(3, c);
+ assertArrayEquals([], rest);
+ assertArrayEquals(["1", "2", "3", "done"], log);
+ }());
+
+ (function() {
+ log = [];
+ var [a, b, c, d, ...rest] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertSame(3, c);
+ assertSame(undefined, d);
+ assertArrayEquals([], rest);
+ assertArrayEquals(["1", "2", "3", "done"], log);
+ }());
+}());
+
+
+(function TestIteratorsLexical() {
+ 'use strict';
+ var log = [];
+ function* f() {
+ log.push("1");
+ yield 1;
+ log.push("2");
+ yield 2;
+ log.push("3");
+ yield 3;
+ log.push("done");
+ };
+
+ (function() {
+ log = [];
+ let [a, b, c] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertSame(3, c);
+ assertArrayEquals(["1", "2", "3"], log);
+ }());
+
+ (function() {
+ log = [];
+ let [a, b, c, d] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertSame(3, c);
+ assertSame(undefined, d);
+ assertArrayEquals(["1", "2", "3", "done"], log);
+ }());
+
+ (function() {
+ log = [];
+ let [a, , c] = f();
+ assertSame(1, a);
+ assertSame(3, c);
+ assertArrayEquals(["1", "2", "3"], log);
+ }());
+
+ (function() {
+ log = [];
+ let [a, , c, d] = f();
+ assertSame(1, a);
+ assertSame(3, c);
+ assertSame(undefined, d);
+ assertArrayEquals(["1", "2", "3", "done"], log);
+ }());
+
+ (function() {
+ log = [];
+ // last comma is not an elision.
+ let [a, b,] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertArrayEquals(["1", "2"], log);
+ }());
+
+ (function() {
+ log = [];
+ // last comma is not an elision, but the comma before the last is.
+ let [a, b, ,] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertArrayEquals(["1", "2", "3"], log);
+ }());
+
+ (function() {
+ log = [];
+ let [a, ...rest] = f();
+ assertSame(1, a);
+ assertArrayEquals([2,3], rest);
+ assertArrayEquals(["1", "2", "3", "done"], log);
+ }());
+
+ (function() {
+ log = [];
+ let [a, b, c, ...rest] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertSame(3, c);
+ assertArrayEquals([], rest);
+ assertArrayEquals(["1", "2", "3", "done"], log);
+ }());
+
+ (function() {
+ log = [];
+ let [a, b, c, d, ...rest] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertSame(3, c);
+ assertSame(undefined, d);
+ assertArrayEquals([], rest);
+ assertArrayEquals(["1", "2", "3", "done"], log);
+ }());
+}());
+
+(function TestIteratorsRecursive() {
+ var log = [];
+ function* f() {
+ log.push("1");
+ yield {x : 1, y : 2};
+ log.push("2");
+ yield [42, 27, 30];
+ log.push("3");
+ yield "abc";
+ log.push("done");
+ };
+
+ (function() {
+ var [{x, y}, [a, b]] = f();
+ assertSame(1, x);
+ assertSame(2, y);
+ assertSame(42, a);
+ assertSame(27, b);
+ assertArrayEquals(["1", "2"], log);
+ }());
+
+ (function() {
+ 'use strict';
+ log = [];
+ let [{x, y}, [a, b]] = f();
+ assertSame(1, x);
+ assertSame(2, y);
+ assertSame(42, a);
+ assertSame(27, b);
+ assertArrayEquals(["1", "2"], log);
+ }());
+}());
+
+
+(function TestForEachLexical() {
+ 'use strict';
+ let a = [{x:1, y:-1}, {x:2,y:-2}, {x:3,y:-3}];
+ let sumX = 0;
+ let sumY = 0;
+ let fs = [];
+ for (let {x,y} of a) {
+ sumX += x;
+ sumY += y;
+ fs.push({fx : function() { return x; }, fy : function() { return y }});
+ }
+ assertSame(6, sumX);
+ assertSame(-6, sumY);
+ assertSame(3, fs.length);
+ for (let i = 0; i < fs.length; i++) {
+ let {fx,fy} = fs[i];
+ assertSame(i+1, fx());
+ assertSame(-(i+1), fy());
+ }
+
+ var o = { __proto__:null, 'a1':1, 'b2':2 };
+ let sx = '';
+ let sy = '';
+ for (let [x,y] in o) {
+ sx += x;
+ sy += y;
+ }
+ assertEquals('ab', sx);
+ assertEquals('12', sy);
+}());
+
+
+(function TestForEachVars() {
+ var a = [{x:1, y:-1}, {x:2,y:-2}, {x:3,y:-3}];
+ var sumX = 0;
+ var sumY = 0;
+ var fs = [];
+ for (var {x,y} of a) {
+ sumX += x;
+ sumY += y;
+ fs.push({fx : function() { return x; }, fy : function() { return y }});
+ }
+ assertSame(6, sumX);
+ assertSame(-6, sumY);
+ assertSame(3, fs.length);
+ for (var i = 0; i < fs.length; i++) {
+ var {fx,fy} = fs[i];
+ assertSame(3, fx());
+ assertSame(-3, fy());
+ }
+
+ var o = { __proto__:null, 'a1':1, 'b2':2 };
+ var sx = '';
+ var sy = '';
+ for (var [x,y] in o) {
+ sx += x;
+ sy += y;
+ }
+ assertEquals('ab', sx);
+ assertEquals('12', sy);
+}());
+
+
+(function TestParameters() {
+ function f({a, b}) { return a - b; }
+ assertEquals(1, f({a : 6, b : 5}));
+
+ function f1(c, {a, b}) { return c + a - b; }
+ assertEquals(8, f1(7, {a : 6, b : 5}));
+
+ function f2({c, d}, {a, b}) { return c - d + a - b; }
+ assertEquals(7, f2({c : 7, d : 1}, {a : 6, b : 5}));
+
+ function f3([{a, b}]) { return a - b; }
+ assertEquals(1, f3([{a : 6, b : 5}]));
+
+ var g = ({a, b}) => { return a - b; };
+ assertEquals(1, g({a : 6, b : 5}));
+
+ var g1 = (c, {a, b}) => { return c + a - b; };
+ assertEquals(8, g1(7, {a : 6, b : 5}));
+
+ var g2 = ({c, d}, {a, b}) => { return c - d + a - b; };
+ assertEquals(7, g2({c : 7, d : 1}, {a : 6, b : 5}));
+
+ var g3 = ([{a, b}]) => { return a - b; };
+ assertEquals(1, g3([{a : 6, b : 5}]));
+}());
+
+
+(function TestExpressionsInParameters() {
+ function f0(x = eval(0)) { return x }
+ assertEquals(0, f0());
+ function f1({a = eval(1)}) { return a }
+ assertEquals(1, f1({}));
+ function f2([x = eval(2)]) { return x }
+ assertEquals(2, f2([]));
+ function f3({[eval(7)]: x}) { return x }
+ assertEquals(3, f3({7: 3}));
+})();
+
+
+(function TestParameterScoping() {
+ var x = 1;
+
+ function f1({a = x}) { var x = 2; return a; }
+ assertEquals(1, f1({}));
+ function f2({a = x}) { function x() {}; return a; }
+ assertEquals(1, f2({}));
+ (function() {
+ 'use strict';
+ function f3({a = x}) { let x = 2; return a; }
+ assertEquals(1, f3({}));
+ function f4({a = x}) { const x = 2; return a; }
+ assertEquals(1, f4({}));
+ function f5({a = x}) { function x() {}; return a; }
+ assertEquals(1, f5({}));
+ })();
+ function f6({a = eval("x")}) { var x; return a; }
+ assertEquals(1, f6({}));
+ (function() {
+ 'use strict';
+ function f61({a = eval("x")}) { var x; return a; }
+ assertEquals(1, f61({}));
+ })();
+ function f62({a = eval("'use strict'; x")}) { var x; return a; }
+ assertEquals(1, f62({}));
+ function f7({a = function() { return x }}) { var x; return a(); }
+ assertEquals(1, f7({}));
+ function f8({a = () => x}) { var x; return a(); }
+ assertEquals(1, f8({}));
+ function f9({a = () => eval("x")}) { var x; return a(); }
+ assertEquals(1, f9({}));
+ (function TestInitializedWithEvalArrowStrict() {
+ 'use strict';
+ function f91({a = () => eval("x")}) { var x; return a(); }
+ assertEquals(1, f91({}));
+ })();
+ function f92({a = () => { 'use strict'; return eval("x") }}) { var x; return a(); }
+ assertEquals(1, f92({}));
+ function f93({a = () => eval("'use strict'; x")}) { var x; return a(); }
+ assertEquals(1, f93({}));
+
+ var g1 = ({a = x}) => { var x = 2; return a; };
+ assertEquals(1, g1({}));
+ var g2 = ({a = x}) => { function x() {}; return a; };
+ assertEquals(1, g2({}));
+ (function() {
+ 'use strict';
+ var g3 = ({a = x}) => { let x = 2; return a; };
+ assertEquals(1, g3({}));
+ var g4 = ({a = x}) => { const x = 2; return a; };
+ assertEquals(1, g4({}));
+ var g5 = ({a = x}) => { function x() {}; return a; };
+ assertEquals(1, g5({}));
+ })();
+ var g6 = ({a = eval("x")}) => { var x; return a; };
+ assertEquals(1, g6({}));
+ (function() {
+ 'use strict';
+ var g61 = ({a = eval("x")}) => { var x; return a; };
+ assertEquals(1, g61({}));
+ })();
+ var g62 = ({a = eval("'use strict'; x")}) => { var x; return a; };
+ assertEquals(1, g62({}));
+ var g7 = ({a = function() { return x }}) => { var x; return a(); };
+ assertEquals(1, g7({}));
+ var g8 = ({a = () => x}) => { var x; return a(); };
+ assertEquals(1, g8({}));
+ var g9 = ({a = () => eval("x")}) => { var x; return a(); };
+ assertEquals(1, g9({}));
+ (function() {
+ 'use strict';
+ var g91 = ({a = () => eval("x")}) => { var x; return a(); };
+ assertEquals(1, g91({}));
+ var g92 = ({a = () => { return eval("x") }}) => { var x; return a(); };
+ assertEquals(1, g92({}));
+ })();
+ var g93 = ({a = () => eval("'use strict'; x")}) => { var x; return a(); };
+ assertEquals(1, g93({}));
+
+ var f11 = function f({x = f}) { var f; return x; }
+ assertSame(f11, f11({}));
+ var f12 = function f({x = f}) { function f() {}; return x; }
+ assertSame(f12, f12({}));
+ (function() {
+ 'use strict';
+ var f13 = function f({x = f}) { let f; return x; }
+ assertSame(f13, f13({}));
+ var f14 = function f({x = f}) { const f = 0; return x; }
+ assertSame(f14, f14({}));
+ var f15 = function f({x = f}) { function f() {}; return x; }
+ assertSame(f15, f15({}));
+ })();
+ var f16 = function f({f = 7, x = f}) { return x; }
+ assertSame(7, f16({}));
+
+ var y = 'a';
+ function f20({[y]: x}) { var y = 'b'; return x; }
+ assertEquals(1, f20({a: 1, b: 2}));
+ function f21({[eval('y')]: x}) { var y = 'b'; return x; }
+ assertEquals(1, f21({a: 1, b: 2}));
+ var g20 = ({[y]: x}) => { var y = 'b'; return x; };
+ assertEquals(1, g20({a: 1, b: 2}));
+ var g21 = ({[eval('y')]: x}) => { var y = 'b'; return x; };
+ assertEquals(1, g21({a: 1, b: 2}));
+})();
+
+
+(function TestParameterDestructuringTDZ() {
+ function f1({a = x}, x) { return a }
+ assertThrows(() => f1({}, 4), ReferenceError);
+ assertEquals(4, f1({a: 4}, 5));
+ function f2({a = eval("x")}, x) { return a }
+ assertThrows(() => f2({}, 4), ReferenceError);
+ assertEquals(4, f2({a: 4}, 5));
+ (function() {
+ 'use strict';
+ function f3({a = eval("x")}, x) { return a }
+ assertThrows(() => f3({}, 4), ReferenceError);
+ assertEquals(4, f3({a: 4}, 5));
+ })();
+ function f4({a = eval("'use strict'; x")}, x) { return a }
+ assertThrows(() => f4({}, 4), ReferenceError);
+ assertEquals(4, f4({a: 4}, 5));
+
+ function f5({a = () => x}, x) { return a() }
+ assertEquals(4, f5({a: () => 4}, 5));
+ function f6({a = () => eval("x")}, x) { return a() }
+ assertEquals(4, f6({a: () => 4}, 5));
+ (function() {
+ 'use strict';
+ function f7({a = () => eval("x")}, x) { return a() }
+ assertEquals(4, f7({a: () => 4}, 5));
+ })();
+ function f8({a = () => eval("'use strict'; x")}, x) { return a() }
+ assertEquals(4, f8({a: () => 4}, 5));
+
+ function f11({a = b}, {b}) { return a }
+ assertThrows(() => f11({}, {b: 4}), ReferenceError);
+ assertEquals(4, f11({a: 4}, {b: 5}));
+ function f12({a = eval("b")}, {b}) { return a }
+ assertThrows(() => f12({}, {b: 4}), ReferenceError);
+ assertEquals(4, f12({a: 4}, {b: 5}));
+ (function() {
+ 'use strict';
+ function f13({a = eval("b")}, {b}) { return a }
+ assertThrows(() => f13({}, {b: 4}), ReferenceError);
+ assertEquals(4, f13({a: 4}, {b: 5}));
+ })();
+ function f14({a = eval("'use strict'; b")}, {b}) { return a }
+ assertThrows(() => f14({}, {b: 4}), ReferenceError);
+ assertEquals(4, f14({a: 4}, {b: 5}));
+
+ function f15({a = () => b}, {b}) { return a() }
+ assertEquals(4, f15({a: () => 4}, {b: 5}));
+ function f16({a = () => eval("b")}, {b}) { return a() }
+ assertEquals(4, f16({a: () => 4}, {b: 5}));
+ (function() {
+ 'use strict';
+ function f17({a = () => eval("b")}, {b}) { return a() }
+ assertEquals(4, f17({a: () => 4}, {b: 5}));
+ })();
+ function f18({a = () => eval("'use strict'; b")}, {b}) { return a() }
+ assertEquals(4, f18({a: () => 4}, {b: 5}));
+
+ // TODO(caitp): TDZ for rest parameters is not working yet.
+ // function f30({x = a}, ...a) { return x[0] }
+ // assertThrows(() => f30({}), ReferenceError);
+ // assertEquals(4, f30({a: [4]}, 5));
+ // function f31({x = eval("a")}, ...a) { return x[0] }
+ // assertThrows(() => f31({}), ReferenceError);
+ // assertEquals(4, f31({a: [4]}, 5));
+ // function f32({x = eval("a")}, ...a) { 'use strict'; return x[0] }
+ // assertThrows(() => f32({}), ReferenceError);
+ // assertEquals(4, f32({a: [4]}, 5));
+ // function f33({x = eval("'use strict'; a")}, ...a) { return x[0] }
+ // assertThrows(() => f33({}), ReferenceError);
+ // assertEquals(4, f33({a: [4]}, 5));
+
+ function f34({x = function() { return a }}, ...a) { return x()[0] }
+ assertEquals(4, f34({}, 4));
+ function f35({x = () => a}, ...a) { return x()[0] }
+ assertEquals(4, f35({}, 4));
+ function f36({x = () => eval("a")}, ...a) { return x()[0] }
+ assertEquals(4, f36({}, 4));
+ (function() {
+ 'use strict';
+ function f37({x = () => eval("a")}, ...a) { return x()[0] }
+ assertEquals(4, f37({}, 4));
+ })();
+ function f38({x = () => { 'use strict'; return eval("a") }}, ...a) { return x()[0] }
+ assertEquals(4, f38({}, 4));
+ function f39({x = () => eval("'use strict'; a")}, ...a) { return x()[0] }
+ assertEquals(4, f39({}, 4));
+
+ // var g30 = ({x = a}, ...a) => {};
+ // assertThrows(() => g30({}), ReferenceError);
+ // var g31 = ({x = eval("a")}, ...a) => {};
+ // assertThrows(() => g31({}), ReferenceError);
+ // var g32 = ({x = eval("a")}, ...a) => { 'use strict'; };
+ // assertThrows(() => g32({}), ReferenceError);
+ // var g33 = ({x = eval("'use strict'; a")}, ...a) => {};
+ // assertThrows(() => g33({}), ReferenceError);
+ var g34 = ({x = function() { return a }}, ...a) => { return x()[0] };
+ assertEquals(4, g34({}, 4));
+ var g35 = ({x = () => a}, ...a) => { return x()[0] };
+ assertEquals(4, g35({}, 4));
+})();
+
+
+(function TestDuplicatesInParameters() {
+ assertThrows("'use strict';function f(x,x){}", SyntaxError);
+ assertThrows("'use strict';function f({x,x}){}", SyntaxError);
+ assertThrows("'use strict';function f(x, {x}){}", SyntaxError);
+ assertThrows("'use strict';var f = (x,x) => {};", SyntaxError);
+ assertThrows("'use strict';var f = ({x,x}) => {};", SyntaxError);
+ assertThrows("'use strict';var f = (x, {x}) => {};", SyntaxError);
+
+ function ok1(x) { var x; return x; };
+ assertEquals(1, ok1(1));
+ function ok2(x) { 'use strict'; { let x = 2; return x; } };
+ assertEquals(2, ok2(1));
+}());
+
+
+(function TestShadowingOfParameters() {
+ function f1({x}) { var x = 2; return x }
+ assertEquals(2, f1({x: 1}));
+ function f2({x}) { { var x = 2; } return x; }
+ assertEquals(2, f2({x: 1}));
+ function f3({x}) { var y = x; var x = 2; return y; }
+ assertEquals(1, f3({x: 1}));
+ function f4({x}) { { var y = x; var x = 2; } return y; }
+ assertEquals(1, f4({x: 1}));
+ function f5({x}, g = () => x) { var x = 2; return g(); }
+ assertEquals(1, f5({x: 1}));
+ function f6({x}, g = () => x) { { var x = 2; } return g(); }
+ assertEquals(1, f6({x: 1}));
+ function f7({x}) { var g = () => x; var x = 2; return g(); }
+ assertEquals(2, f7({x: 1}));
+ function f8({x}) { { var g = () => x; var x = 2; } return g(); }
+ assertEquals(2, f8({x: 1}));
+ function f9({x}, g = () => eval("x")) { var x = 2; return g(); }
+ assertEquals(1, f9({x: 1}));
+
+ function f10({x}, y) { var y; return y }
+ assertEquals(2, f10({x: 6}, 2));
+ function f11({x}, y) { var z = y; var y = 2; return z; }
+ assertEquals(1, f11({x: 6}, 1));
+ function f12(y, g = () => y) { var y = 2; return g(); }
+ assertEquals(1, f12(1));
+ function f13({x}, y, [z], v) { var x, y, z; return x*y*z*v }
+ assertEquals(210, f13({x: 2}, 3, [5], 7));
+
+ function f20({x}) { function x() { return 2 }; return x(); }
+ assertEquals(2, f20({x: 1}));
+ // Function hoisting is blocked by the conflicting x declaration
+ function f21({x}) { { function x() { return 2 } } return x(); }
+ assertThrows(() => f21({x: 1}), TypeError);
+
+ var g1 = ({x}) => { var x = 2; return x };
+ assertEquals(2, g1({x: 1}));
+ var g2 = ({x}) => { { var x = 2; } return x; };
+ assertEquals(2, g2({x: 1}));
+ var g3 = ({x}) => { var y = x; var x = 2; return y; };
+ assertEquals(1, g3({x: 1}));
+ var g4 = ({x}) => { { var y = x; var x = 2; } return y; };
+ assertEquals(1, g4({x: 1}));
+ var g5 = ({x}, g = () => x) => { var x = 2; return g(); };
+ assertEquals(1, g5({x: 1}));
+ var g6 = ({x}, g = () => x) => { { var x = 2; } return g(); };
+ assertEquals(1, g6({x: 1}));
+ var g7 = ({x}) => { var g = () => x; var x = 2; return g(); };
+ assertEquals(2, g7({x: 1}));
+ var g8 = ({x}) => { { var g = () => x; var x = 2; } return g(); };
+ assertEquals(2, g8({x: 1}));
+ var g9 = ({x}, g = () => eval("x")) => { var x = 2; return g(); };
+ assertEquals(1, g9({x: 1}));
+
+ var g10 = ({x}, y) => { var y; return y };
+ assertEquals(2, g10({x: 6}, 2));
+ var g11 = ({x}, y) => { var z = y; var y = 2; return z; };
+ assertEquals(1, g11({x: 6}, 1));
+ var g12 = (y, g = () => y) => { var y = 2; return g(); };
+ assertEquals(1, g12(1));
+ var g13 = ({x}, y, [z], v) => { var x, y, z; return x*y*z*v };
+ assertEquals(210, g13({x: 2}, 3, [5], 7));
+
+ var g20 = ({x}) => { function x() { return 2 }; return x(); }
+ assertEquals(2, g20({x: 1}));
+ var g21 = ({x}) => { { function x() { return 2 } } return x(); }
+ assertThrows(() => g21({x: 1}), TypeError);
+
+ assertThrows("'use strict'; function f(x) { let x = 0; }; f({});", SyntaxError);
+ assertThrows("'use strict'; function f({x}) { let x = 0; }; f({});", SyntaxError);
+ assertThrows("'use strict'; function f(x) { const x = 0; }; f({});", SyntaxError);
+ assertThrows("'use strict'; function f({x}) { const x = 0; }; f({});", SyntaxError);
+
+ assertThrows("'use strict'; let g = (x) => { let x = 0; }; f({});", SyntaxError);
+ assertThrows("'use strict'; let g = ({x}) => { let x = 0; }; f({});", SyntaxError);
+ assertThrows("'use strict'; let g = (x) => { const x = 0; }; f({});", SyntaxError);
+ assertThrows("'use strict'; let g = ({x}) => { const x = 0; }; f({});", SyntaxError);
+}());
+
+
+(function TestArgumentsForNonSimpleParameters() {
+ function f1({}, x) { arguments[1] = 0; return x }
+ assertEquals(6, f1({}, 6));
+ function f2({}, x) { x = 2; return arguments[1] }
+ assertEquals(7, f2({}, 7));
+ function f3(x, {}) { arguments[0] = 0; return x }
+ assertEquals(6, f3(6, {}));
+ function f4(x, {}) { x = 2; return arguments[0] }
+ assertEquals(7, f4(7, {}));
+ function f5(x, ...a) { arguments[0] = 0; return x }
+ assertEquals(6, f5(6, {}));
+ function f6(x, ...a) { x = 2; return arguments[0] }
+ assertEquals(6, f6(6, {}));
+ function f7({a: x}) { x = 2; return arguments[0].a }
+ assertEquals(5, f7({a: 5}));
+ function f8(x, ...a) { a = []; return arguments[1] }
+ assertEquals(6, f8(5, 6));
+}());
+
+
+(function TestForInOfTDZ() {
+ assertThrows("'use strict'; let x = {}; for (let [x, y] of [x]);", ReferenceError);
+ assertThrows("'use strict'; let x = {}; for (let [y, x] of [x]);", ReferenceError);
+ assertThrows("'use strict'; let x = {}; for (let [x, y] in {x});", ReferenceError);
+ assertThrows("'use strict'; let x = {}; for (let [y, x] in {x});", ReferenceError);
+}());
+
+
+(function TestFunctionLength() {
+ assertEquals(1, (function({}) {}).length);
+ assertEquals(1, (function([]) {}).length);
+ assertEquals(1, (function({x}) {}).length);
+ assertEquals(1, (function({}, ...a) {}).length);
+ assertEquals(1, (function({x}, {y} = {}) {}).length);
+ assertEquals(1, (function({x}, {y} = {}, ...a) {}).length);
+ assertEquals(2, (function(x, {y}, {z} = {}) {}).length);
+ assertEquals(2, (function({x}, {}, {z} = {}, ...a) {}).length);
+ assertEquals(1, (function(x, {y} = {}, {z}) {}).length);
+ assertEquals(1, (function({x}, {y} = {}, {z}, ...a) {}).length);
+ assertEquals(1, (function(x, {y} = {}, {z}, {v} = {}) {}).length);
+ assertEquals(1, (function({x}, {y} = {}, {z}, {v} = {}, ...a) {}).length);
+})();
+
+
+(function TestDirectiveThrows() {
+ "use strict";
+
+ assertThrows(function(){ eval("function({}){'use strict';}") }, SyntaxError);
+ assertThrows(function(){ eval("({}) => {'use strict';}") }, SyntaxError);
+ assertThrows(
+ function(){ eval("(class{foo({}) {'use strict';}});") }, SyntaxError);
+
+ assertThrows(
+ function(){ eval("function(a, {}){'use strict';}") }, SyntaxError);
+ assertThrows(function(){ eval("(a, {}) => {'use strict';}") }, SyntaxError);
+ assertThrows(
+ function(){ eval("(class{foo(a, {}) {'use strict';}});") }, SyntaxError);
+})();
+
+
+(function TestLegacyConstDestructuringInForLoop() {
+ var result;
+ for (const {foo} of [{foo: 1}]) { result = foo; }
+ assertEquals(1, result);
+})();
+
+
+(function TestCatch() {
+ "use strict";
+
+ // For testing proper scoping.
+ var foo = "hello", bar = "world", baz = 42;
+
+ try {
+ throw {foo: 1, bar: 2};
+ } catch ({foo, bar, baz = 3}) {
+ assertEquals(1, foo);
+ assertEquals(2, bar);
+ assertEquals(3, baz);
+ }
+
+ try {
+ throw [1, 2, 3];
+ } catch ([foo, ...bar]) {
+ assertEquals(1, foo);
+ assertEquals([2, 3], bar);
+ }
+
+ assertEquals("hello", foo);
+ assertEquals("world", bar);
+ assertEquals(42, baz);
+
+ assertEquals(undefined, eval('try {throw {foo: 1, bar: 2}} catch({foo}) {}'));
+ assertEquals(undefined, eval('try {throw [1, 2, 3]} catch([x]) {}'));
+})();
diff --git a/test/mjsunit/es6/generators-objects.js b/test/mjsunit/es6/generators-objects.js
index f304738..a0c3b80 100644
--- a/test/mjsunit/es6/generators-objects.js
+++ b/test/mjsunit/es6/generators-objects.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: --allow-natives-syntax --harmony-tostring
+// Flags: --allow-natives-syntax
// Test instantations of generators.
diff --git a/test/mjsunit/es6/instanceof-proxies.js b/test/mjsunit/es6/instanceof-proxies.js
index cc720ad..86b104c 100644
--- a/test/mjsunit/es6/instanceof-proxies.js
+++ b/test/mjsunit/es6/instanceof-proxies.js
@@ -3,7 +3,7 @@
// found in the LICENSE file.
-// Flags: --harmony-proxies --allow-natives-syntax
+// Flags: --allow-natives-syntax
// Test instanceof with proxies.
diff --git a/test/mjsunit/es6/iteration-semantics.js b/test/mjsunit/es6/iteration-semantics.js
index 6466ac5..558fb83 100644
--- a/test/mjsunit/es6/iteration-semantics.js
+++ b/test/mjsunit/es6/iteration-semantics.js
@@ -25,8 +25,6 @@
// (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-proxies
-
// Test for-of semantics.
"use strict";
diff --git a/test/mjsunit/es6/json.js b/test/mjsunit/es6/json.js
index 3fad083..4c1ada8 100644
--- a/test/mjsunit/es6/json.js
+++ b/test/mjsunit/es6/json.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-tostring
-
function testJSONToString() {
assertEquals('[object JSON]', "" + JSON);
assertEquals("JSON", JSON[Symbol.toStringTag]);
diff --git a/test/mjsunit/es6/math-trunc.js b/test/mjsunit/es6/math-trunc.js
index 9231576..c925b5b 100644
--- a/test/mjsunit/es6/math-trunc.js
+++ b/test/mjsunit/es6/math-trunc.js
@@ -25,25 +25,78 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-assertEquals("Infinity", String(1/Math.trunc(0)));
-assertEquals("-Infinity", String(1/Math.trunc(-0)));
-assertEquals("Infinity", String(1/Math.trunc(Math.PI/4)));
-assertEquals("-Infinity", String(1/Math.trunc(-Math.sqrt(2)/2)));
-assertEquals(100, Math.trunc(100));
-assertEquals(-199, Math.trunc(-199));
-assertEquals(100, Math.trunc(100.1));
-assertTrue(isNaN(Math.trunc("abc")));
-assertTrue(isNaN(Math.trunc({})));
-assertEquals(0, Math.trunc([]));
-assertEquals(1, Math.trunc([1]));
-assertEquals(-100, Math.trunc([-100.1]));
-assertTrue(isNaN(Math.trunc([1, 1])));
-assertEquals(-100, Math.trunc({ toString: function() { return "-100.3"; } }));
-assertEquals(10, Math.trunc({ toString: function() { return 10.1; } }));
-assertEquals(-1, Math.trunc({ valueOf: function() { return -1.1; } }));
-assertEquals("-Infinity",
- String(1/Math.trunc({ valueOf: function() { return "-0.1"; } })));
-assertEquals("-Infinity", String(Math.trunc(-Infinity)));
-assertEquals("Infinity", String(Math.trunc(Infinity)));
-assertEquals("-Infinity", String(Math.trunc("-Infinity")));
-assertEquals("Infinity", String(Math.trunc("Infinity")));
+// Flags: --allow-natives-syntax
+
+var test_id = 0;
+
+function testTrunc(expected, input) {
+ var test = new Function('n',
+ '"' + (test_id++) + '";return Math.trunc(n)');
+ assertEquals(expected, test(input));
+ assertEquals(expected, test(input));
+ assertEquals(expected, test(input));
+ %OptimizeFunctionOnNextCall(test);
+ assertEquals(expected, test(input));
+
+ var test_double_input = new Function(
+ 'n',
+ '"' + (test_id++) + '";return Math.trunc(+n)');
+ assertEquals(expected, test_double_input(input));
+ assertEquals(expected, test_double_input(input));
+ assertEquals(expected, test_double_input(input));
+ %OptimizeFunctionOnNextCall(test_double_input);
+ assertEquals(expected, test_double_input(input));
+
+ var test_double_output = new Function(
+ 'n',
+ '"' + (test_id++) + '";return Math.trunc(n) + -0.0');
+ assertEquals(expected, test_double_output(input));
+ assertEquals(expected, test_double_output(input));
+ assertEquals(expected, test_double_output(input));
+ %OptimizeFunctionOnNextCall(test_double_output);
+ assertEquals(expected, test_double_output(input));
+}
+
+function test() {
+ // Ensure that a negative zero coming from Math.trunc is properly handled
+ // by other operations.
+ function itrunc(x) {
+ return 1 / Math.trunc(x);
+ }
+ assertEquals(Infinity, itrunc(0));
+ assertEquals(-Infinity, itrunc(-0));
+ assertEquals(Infinity, itrunc(Math.PI / 4));
+ assertEquals(-Infinity, itrunc(-Math.sqrt(2) / 2));
+ assertEquals(-Infinity, itrunc({valueOf: function() { return "-0.1"; }}));
+ %OptimizeFunctionOnNextCall(itrunc);
+
+ testTrunc(100, 100);
+ testTrunc(-199, -199);
+ testTrunc(100, 100.1);
+ testTrunc(4503599627370495.0, 4503599627370495.0);
+ testTrunc(4503599627370496.0, 4503599627370496.0);
+ testTrunc(-4503599627370495.0, -4503599627370495.0);
+ testTrunc(-4503599627370496.0, -4503599627370496.0);
+ testTrunc(9007199254740991.0, 9007199254740991.0);
+ testTrunc(-9007199254740991.0, -9007199254740991.0);
+ testTrunc(0, []);
+ testTrunc(1, [1]);
+ testTrunc(-100, [-100.1]);
+ testTrunc(-100, {toString: function() { return "-100.3"; }});
+ testTrunc(10, {toString: function() { return 10.1; }});
+ testTrunc(-1, {valueOf: function() { return -1.1; }});
+ testTrunc(-Infinity, -Infinity);
+ testTrunc(Infinity, Infinity);
+ testTrunc(-Infinity, "-Infinity");
+ testTrunc(Infinity, "Infinity");
+
+ assertTrue(isNaN(Math.trunc("abc")));
+ assertTrue(isNaN(Math.trunc({})));
+ assertTrue(isNaN(Math.trunc([1, 1])));
+}
+
+// Test in a loop to cover the custom IC and GC-related issues.
+for (var i = 0; i < 10; i++) {
+ test();
+ new Array(i * 10000);
+}
diff --git a/test/mjsunit/es6/math.js b/test/mjsunit/es6/math.js
index 3f76f11..cb43bd5 100644
--- a/test/mjsunit/es6/math.js
+++ b/test/mjsunit/es6/math.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-tostring
-
function testMathToString() {
assertEquals('[object Math]', "" + Math);
assertEquals("Math", Math[Symbol.toStringTag]);
diff --git a/test/mjsunit/es6/new-target.js b/test/mjsunit/es6/new-target.js
index 8a06ff6..4be1254 100644
--- a/test/mjsunit/es6/new-target.js
+++ b/test/mjsunit/es6/new-target.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-reflect --harmony-destructuring-bind
-
(function TestClass() {
'use strict';
diff --git a/test/mjsunit/es6/no-unicode-regexp-flag.js b/test/mjsunit/es6/no-unicode-regexp-flag.js
index 035627c..82d070e 100644
--- a/test/mjsunit/es6/no-unicode-regexp-flag.js
+++ b/test/mjsunit/es6/no-unicode-regexp-flag.js
@@ -7,7 +7,7 @@
// mjsunit/es6/regexp-flags tests that the property is there when the
// flag is on.
-// Flags: --harmony-regexps --no-harmony-unicode-regexps
+// Flags: --no-harmony-unicode-regexps
'use strict';
diff --git a/test/mjsunit/es6/object-tostring.js b/test/mjsunit/es6/object-tostring.js
index 4d6090f..29d07f2 100644
--- a/test/mjsunit/es6/object-tostring.js
+++ b/test/mjsunit/es6/object-tostring.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-tostring --harmony-proxies
-
var global = this;
var funs = {
diff --git a/test/mjsunit/es6/pattern-brand-check.js b/test/mjsunit/es6/pattern-brand-check.js
new file mode 100644
index 0000000..9b0c011
--- /dev/null
+++ b/test/mjsunit/es6/pattern-brand-check.js
@@ -0,0 +1,54 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-regexp-subclass
+
+function createNonRegExp(calls) {
+ return {
+ get [Symbol.match]() {
+ calls.push("@@match");
+ return undefined;
+ },
+ get [Symbol.replace]() {
+ calls.push("@@replace");
+ return undefined;
+ },
+ get [Symbol.search]() {
+ calls.push("@@search");
+ return undefined;
+ },
+ get [Symbol.split]() {
+ calls.push("@@split");
+ return undefined;
+ },
+ [Symbol.toPrimitive]() {
+ calls.push("@@toPrimitive");
+ return "";
+ }
+ };
+}
+
+(function testStringMatchBrandCheck() {
+ var calls = [];
+ "".match(createNonRegExp(calls));
+ assertEquals(["@@match", "@@toPrimitive"], calls);
+})();
+
+(function testStringSearchBrandCheck() {
+ var calls = [];
+ "".search(createNonRegExp(calls));
+ assertEquals(["@@search", "@@toPrimitive"], calls);
+})();
+
+(function testStringSplitBrandCheck() {
+ var calls = [];
+ "".split(createNonRegExp(calls));
+ assertEquals(["@@split", "@@toPrimitive"], calls);
+})();
+
+(function testStringReplaceBrandCheck() {
+ var calls = [];
+ "".replace(createNonRegExp(calls), "");
+ assertEquals(["@@replace", "@@toPrimitive"], calls);
+})();
diff --git a/test/mjsunit/es6/promises.js b/test/mjsunit/es6/promises.js
index e4c8b38..4eb539c 100644
--- a/test/mjsunit/es6/promises.js
+++ b/test/mjsunit/es6/promises.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: --allow-natives-syntax --harmony-tostring --promise-extra
+// Flags: --allow-natives-syntax --promise-extra
// Make sure we don't rely on functions patchable by monkeys.
var call = Function.prototype.call.call.bind(Function.prototype.call)
diff --git a/test/mjsunit/es6/proxies-accesschecks.js b/test/mjsunit/es6/proxies-accesschecks.js
new file mode 100644
index 0000000..f5b90dc
--- /dev/null
+++ b/test/mjsunit/es6/proxies-accesschecks.js
@@ -0,0 +1,13 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var realm = Realm.create();
+
+this.__proto__ = new Proxy({}, {
+ getPrototypeOf() { assertUnreachable() },
+ get() { assertUnreachable() }
+});
+
+var other_type_error = Realm.eval(realm, "TypeError");
+assertThrows(() => Realm.eval(realm, "Realm.global(0).foo"), other_type_error);
diff --git a/test/mjsunit/es6/proxies-apply.js b/test/mjsunit/es6/proxies-apply.js
new file mode 100644
index 0000000..a94541c
--- /dev/null
+++ b/test/mjsunit/es6/proxies-apply.js
@@ -0,0 +1,120 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function testNonCallable() {
+ var proxy = new Proxy({},{});
+ assertThrows(function(){ proxy() }, TypeError);
+
+ var proxy2 = new Proxy(proxy, {});
+ assertThrows(function(){ proxy2() }, TypeError);
+})();
+
+(function testCallProxyFallbackNoArguments() {
+ var called = false;
+ var target = function() {
+ called = true;
+ }
+ var proxy = new Proxy(target, {});
+ assertFalse(called);
+ proxy();
+ assertTrue(called);
+
+ called = false;
+ var proxy2 = new Proxy(proxy, {});
+ assertFalse(called);
+ proxy2();
+ assertTrue(called);
+})();
+
+(function testCallProxyFallback1Argument() {
+ var called = false;
+ var target = function(a) {
+ called = true;
+ assertEquals('1', a);
+ }
+ var proxy = new Proxy(target, {});
+ assertFalse(called);
+ proxy('1');
+ assertTrue(called);
+})();
+
+(function testCallProxyFallback2Arguments() {
+ var called = false;
+ var target = function(a, b) {
+ called = true;
+ assertEquals('1', a);
+ assertEquals('2', b);
+ }
+ var proxy = new Proxy(target, {});
+ assertFalse(called);
+ proxy('1', '2');
+ assertTrue(called);
+})();
+
+(function testCallProxyFallbackChangedReceiver() {
+ var apply_receiver = {receiver:true};
+ var seen_receiver = undefined;
+ var target = function() {
+ seen_receiver = this;
+ }
+ var proxy = new Proxy(target, {});
+ assertEquals(undefined, seen_receiver);
+ Reflect.apply(proxy, apply_receiver, [1,2,3,4]);
+ assertSame(apply_receiver, seen_receiver);
+})();
+
+(function testCallProxyTrap() {
+ var called_target = false;
+ var called_handler = false;
+ var target = function(a, b) {
+ called_target = true;
+ assertEquals(1, a);
+ assertEquals(2, b);
+ }
+ var handler = {
+ apply: function(target, this_arg, args) {
+ target.apply(this_arg, args);
+ called_handler = true;
+ }
+ }
+ var proxy = new Proxy(target, handler);
+ assertFalse(called_target);
+ assertFalse(called_handler);
+ Reflect.apply(proxy, {rec:1}, [1,2]);
+ assertTrue(called_target);
+ assertTrue(called_handler);
+})();
+
+
+(function testCallProxyNonCallableTarget() {
+ var values = [NaN, 1.5, 100, /RegExp/, "string", {}, [], Symbol(),
+ new Map(), new Set(), new WeakMap(), new WeakSet()];
+ values.forEach(target => {
+ target = Object(target);
+ var proxy = new Proxy(target, { apply() { assertUnreachable(); } });
+ assertThrows(() => { proxy(); }, TypeError);
+ assertThrows(() => { ({ proxy }).proxy(); }, TypeError);
+ assertThrows(() => { Reflect.apply(proxy, null, []); }, TypeError);
+ assertThrows(() => { Reflect.apply(proxy, { proxy }, []); }, TypeError);
+ assertThrows(() => {
+ Function.prototype.call.apply(proxy, [null]);
+ }, TypeError);
+ assertThrows(() => {
+ Function.prototype.apply.apply(proxy, [null, []]);
+ }, TypeError);
+
+ var proxy_to_proxy = new Proxy(proxy, { apply() { assertUnreachable(); } });
+ assertThrows(() => { proxy_to_proxy(); }, TypeError);
+ assertThrows(() => { ({ proxy_to_proxy }).proxy_to_proxy(); }, TypeError);
+ assertThrows(() => { Reflect.apply(proxy_to_proxy, null, []); }, TypeError);
+ assertThrows(() => { Reflect.apply(proxy_to_proxy, { proxy }, []); },
+ TypeError);
+ assertThrows(() => {
+ Function.prototype.call.apply(proxy_to_proxy, [null]);
+ }, TypeError);
+ assertThrows(() => {
+ Function.prototype.apply.apply(proxy_to_proxy, [null, []]);
+ }, TypeError);
+ });
+})();
diff --git a/test/mjsunit/es6/proxies-bind.js b/test/mjsunit/es6/proxies-bind.js
new file mode 100644
index 0000000..83876a0
--- /dev/null
+++ b/test/mjsunit/es6/proxies-bind.js
@@ -0,0 +1,135 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Tests the interaction of Function.prototype.bind with proxies.
+
+
+// (Helper)
+
+var log = [];
+var logger = {};
+var handler = new Proxy({}, logger);
+
+logger.get = function(t, trap, r) {
+ return function() {
+ log.push([trap, ...arguments]);
+ return Reflect[trap](...arguments);
+ }
+};
+
+
+// Simple case
+
+var target = function(a, b, c) { "use strict"; return this };
+var proxy = new Proxy(target, handler);
+var this_value = Symbol();
+
+log.length = 0;
+result = Function.prototype.bind.call(proxy, this_value, "foo");
+assertEquals(2, result.length);
+assertEquals(target.__proto__, result.__proto__);
+assertEquals(this_value, result());
+assertEquals(5, log.length);
+for (var i in log) assertSame(target, log[i][1]);
+assertEquals(["getPrototypeOf", target], log[0]);
+assertEquals(["getOwnPropertyDescriptor", target, "length"], log[1]);
+assertEquals(["get", target, "length", proxy], log[2]);
+assertEquals(["get", target, "name", proxy], log[3]);
+assertEquals(["apply", target, this_value, ["foo"]], log[4]);
+assertEquals(new target(), new result());
+
+
+// Custom prototype
+
+log.length = 0;
+target.__proto__ = {radio: "gaga"};
+result = Function.prototype.bind.call(proxy, this_value, "foo");
+assertEquals(2, result.length);
+assertSame(target.__proto__, result.__proto__);
+assertEquals(this_value, result());
+assertEquals(5, log.length);
+for (var i in log) assertSame(target, log[i][1]);
+assertEquals(["getPrototypeOf", target], log[0]);
+assertEquals(["getOwnPropertyDescriptor", target, "length"], log[1]);
+assertEquals(["get", target, "length", proxy], log[2]);
+assertEquals(["get", target, "name", proxy], log[3]);
+assertEquals(["apply", target, this_value, ["foo"]], log[4]);
+
+
+// Custom length
+
+handler = {
+ get() {return 42},
+ getOwnPropertyDescriptor() {return {configurable: true}}
+};
+proxy = new Proxy(target, handler);
+
+result = Function.prototype.bind.call(proxy, this_value, "foo");
+assertEquals(41, result.length);
+assertEquals(this_value, result());
+
+
+// Long length
+
+handler = {
+ get() {return Math.pow(2, 100)},
+ getOwnPropertyDescriptor() {return {configurable: true}}
+};
+proxy = new Proxy(target, handler);
+
+result = Function.prototype.bind.call(proxy, this_value, "foo");
+assertEquals(Math.pow(2, 100) - 1, result.length);
+assertEquals(this_value, result());
+
+
+// Very long length
+
+handler = {
+ get() {return 1/0},
+ getOwnPropertyDescriptor() {return {configurable: true}}
+};
+proxy = new Proxy(target, handler);
+
+result = Function.prototype.bind.call(proxy, this_value, "foo");
+assertEquals(1/0, result.length);
+assertEquals(this_value, result());
+
+
+// Non-integer length
+
+handler = {
+ get() {return 4.2},
+ getOwnPropertyDescriptor() {return {configurable: true}}
+};
+proxy = new Proxy(target, handler);
+
+result = Function.prototype.bind.call(proxy, this_value, "foo");
+assertEquals(3, result.length);
+assertEquals(this_value, result());
+
+
+// Undefined length
+
+handler = {
+ get() {},
+ getOwnPropertyDescriptor() {return {configurable: true}}
+};
+proxy = new Proxy(target, handler);
+
+result = Function.prototype.bind.call(proxy, this_value, "foo");
+assertEquals(0, result.length);
+assertEquals(this_value, result());
+
+
+// Non-callable
+
+assertThrows(() => Function.prototype.bind.call(new Proxy({}, {})), TypeError);
+assertThrows(() => Function.prototype.bind.call(new Proxy([], {})), TypeError);
+
+
+// Non-constructable
+
+result = Function.prototype.bind.call(() => 42, this_value, "foo");
+assertEquals(42, result());
+assertThrows(() => new result());
diff --git a/test/mjsunit/es6/proxies-construct.js b/test/mjsunit/es6/proxies-construct.js
new file mode 100644
index 0000000..344c50a
--- /dev/null
+++ b/test/mjsunit/es6/proxies-construct.js
@@ -0,0 +1,156 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function testNonConstructable() {
+ var proxy = new Proxy({},{});
+ assertThrows(function(){ new proxy() }, TypeError);
+
+ var proxy2 = new Proxy(proxy, {});
+ assertThrows(function(){ proxy2() }, TypeError);
+})();
+
+(function testFailingConstructRevoked() {
+ var pair = Proxy.revocable(Array, {});
+ var instance = new pair.proxy();
+ pair.revoke();
+ assertThrows(function(){ new pair.proxy() }, TypeError);
+})();
+
+(function testFailingGetTrap() {
+ var handler = {
+ get() {
+ throw TypeError();
+ }
+ }
+ var proxy = new Proxy({},{});
+ var proxy2 = new Proxy({}, proxy);
+ assertThrows(function(){ new proxy2() }, TypeError);
+})();
+
+(function testConstructFallback() {
+ var called = false;
+ function Target() {
+ called = true;
+ this.property1 = 'value1';
+ };
+ Target.prototype = {};
+ var proxy = new Proxy(Target, {});
+
+ assertFalse(called);
+ var instance = new proxy();
+ assertTrue(called);
+ assertEquals('value1', instance.property1);
+ assertSame(Target.prototype, Reflect.getPrototypeOf(instance));
+
+ var proxy2 = new Proxy(proxy, {});
+ called = false;
+ var instance2 = new proxy2();
+ assertTrue(called);
+ assertEquals('value1', instance2.property1);
+ assertSame(Target.prototype, Reflect.getPrototypeOf(instance));
+})();
+
+(function testConstructTrapDirectReturn() {
+ function Target(a, b) {
+ this.sum = a + b;
+ };
+ var handler = {
+ construct(t, c, args) {
+ return { sum: 42 };
+ }
+ };
+ var proxy = new Proxy(Target, handler);
+ assertEquals(42, (new proxy(1, 2)).sum);
+})();
+
+(function testConstructTrap() {
+ function Target(arg1, arg2) {
+ this.arg1 = arg1;
+ this.arg2 = arg2;
+ }
+ var seen_target, seen_arguments, seen_new_target;
+ var handler = {
+ construct(target, args, new_target) {
+ seen_target = target;
+ seen_arguments = args;
+ seen_new_target = new_target;
+ return Reflect.construct(target, args, new_target);
+ }
+ }
+ var proxy = new Proxy(Target, handler);
+ var instance = new proxy('a', 'b');
+ assertEquals(Target, seen_target);
+ assertEquals(['a','b'], seen_arguments);
+ assertEquals(proxy, seen_new_target);
+ assertEquals('a', instance.arg1);
+ assertEquals('b', instance.arg2);
+
+ var instance2 = Reflect.construct(proxy, ['a1', 'b1'], Array);
+ assertEquals(Target, seen_target);
+ assertEquals(['a1', 'b1'], seen_arguments);
+ assertEquals(Array, seen_new_target);
+ assertEquals('a1', instance2.arg1);
+ assertEquals('b1', instance2.arg2);
+})();
+
+(function testConstructCrossRealm() {
+ var realm1 = Realm.create();
+ var handler = {
+ construct(target, args, new_target) {
+ return args;
+ }
+ };
+ var OtherProxy = Realm.eval(realm1, "Proxy");
+ var otherArrayPrototype = Realm.eval(realm1, 'Array.prototype');
+
+ // Proxy and handler are from this realm.
+ var proxy = new Proxy(Array, handler);
+ var result = new proxy();
+ assertSame(Array.prototype, Reflect.getPrototypeOf(result));
+
+ // Proxy is from this realm, handler is from realm1.
+ var otherProxy = new OtherProxy(Array, handler);
+ var otherResult = new otherProxy();
+ assertSame(Array.prototype, Reflect.getPrototypeOf(otherResult));
+
+ // Proxy and handler are from realm1.
+ var otherProxy2 = Realm.eval(realm1, 'new Proxy('+
+ 'Array, { construct(target, args, new_target) { return args }} )');
+ var otherResult2 = new otherProxy2();
+ assertSame(Array.prototype, Reflect.getPrototypeOf(otherResult2));
+})();
+
+(function testReflectConstructCrossReal() {
+ var realm1 = Realm.create();
+ var realm2 = Realm.create();
+ var realm3 = Realm.create();
+ var realm4 = Realm.create();
+
+ var argsRealm1 = Realm.eval(realm1, '[]');
+ var ProxyRealm2 = Realm.eval(realm2, 'Proxy');
+ var constructorRealm3 = Realm.eval(realm3, '(function(){})');
+ var handlerRealm4 = Realm.eval(realm4,
+ '({ construct(target, args, new_target) {return args} })');
+
+ var proxy = new ProxyRealm2(constructorRealm3, handlerRealm4);
+
+ // Check that the arguments array returned by handlerRealm4 is created in the
+ // realm of the Reflect.construct function.
+ var result = Reflect.construct(proxy, argsRealm1);
+ assertSame(Array.prototype, Reflect.getPrototypeOf(result));
+
+ var ReflectConstructRealm1 = Realm.eval(realm1, 'Reflect.construct');
+ var result2 = ReflectConstructRealm1(proxy, argsRealm1);
+ assertSame(Realm.eval(realm1, 'Array.prototype'),
+ Reflect.getPrototypeOf(result2));
+
+ var result3 = ReflectConstructRealm1(proxy, []);
+ assertSame(Realm.eval(realm1, 'Array.prototype'),
+ Reflect.getPrototypeOf(result3));
+
+ var ReflectConstructRealm2 = Realm.eval(realm2, 'Reflect.construct');
+ var result4 = ReflectConstructRealm2(proxy, argsRealm1);
+ assertSame(Realm.eval(realm2, 'Array.prototype'),
+ Reflect.getPrototypeOf(result4));
+})();
diff --git a/test/mjsunit/es6/proxies-cross-realm-exception.js b/test/mjsunit/es6/proxies-cross-realm-exception.js
new file mode 100644
index 0000000..ffba5c2
--- /dev/null
+++ b/test/mjsunit/es6/proxies-cross-realm-exception.js
@@ -0,0 +1,53 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+// Do not read out the prototype from a cross-realm object.
+var realm = Realm.create();
+
+__proto__ = {};
+assertEquals(null,
+ Realm.eval(realm, "3; Reflect.getPrototypeOf(Realm.global(0))"));
+assertFalse(Realm.eval(realm, "3; Realm.global(0) instanceof Object"));
+
+__proto__ = new Proxy({}, { getPrototypeOf() { assertUnreachable() } });
+assertEquals(null,
+ Realm.eval(realm, "1; Reflect.getPrototypeOf(Realm.global(0))"));
+assertFalse(Realm.eval(realm, "1; Realm.global(0) instanceof Object"));
+
+// Test that the instannceof check works in optimized code.
+var test = Realm.eval(realm,
+ "()=>{1.1; return Realm.global(0) instanceof Object; }");
+assertFalse(test());
+test();
+test();
+%OptimizeFunctionOnNextCall(test);
+assertFalse(test());
+
+__proto__ = {};
+__proto__ = new Proxy({}, { get(t, p, r) { assertUnreachable() } });
+assertEquals(null,
+ Realm.eval(realm, "2; Reflect.getPrototypeOf(Realm.global(0))"));
+assertFalse(Realm.eval(realm, "2; Realm.global(0) instanceof Object"));
+
+
+__proto__ = {};
+__proto__.__proto__ = new Proxy({}, {
+ getPrototypeOf() { assertUnreachable() }
+});
+assertEquals(null,
+ Realm.eval(realm, "4; Reflect.getPrototypeOf(Realm.global(0))"));
+assertFalse(Realm.eval(realm, "4; Realm.global(0) instanceof Object"));
+
+// 2-level proxy indirection
+__proto__ = {};
+__proto__ = new Proxy({},
+ new Proxy({}, {
+ get() { assertUnreachable() }
+ })
+);
+assertEquals(null,
+ Realm.eval(realm, "5; Reflect.getPrototypeOf(Realm.global(0))"));
+assertFalse(Realm.eval(realm, "5; Realm.global(0) instanceof Object"));
diff --git a/test/mjsunit/es6/proxies-define-property.js b/test/mjsunit/es6/proxies-define-property.js
new file mode 100644
index 0000000..14c95bf
--- /dev/null
+++ b/test/mjsunit/es6/proxies-define-property.js
@@ -0,0 +1,82 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Check basic call to trap.
+
+var g_target, g_name, g_desc;
+var handler = {
+ defineProperty: function(target, name, desc) {
+ g_target = target;
+ g_name = name;
+ g_desc = desc;
+ return true;
+ }
+}
+var target = {}
+var proxy = new Proxy(target, handler);
+var desc = { value: 1, writable: true, configurable: true, enumerable: true };
+Object.defineProperty(proxy, "foo", desc);
+assertSame(target, g_target);
+assertEquals("foo", g_name);
+assertEquals(desc, g_desc);
+
+// Check specific steps in the spec
+
+// Step 4: revoked handler
+var pair = Proxy.revocable(target, handler);
+Object.defineProperty(proxy, "foo2", desc);
+assertSame(target, g_target);
+assertEquals("foo2", g_name);
+assertEquals(desc, g_desc);
+pair.revoke();
+assertThrows('Object.defineProperty(pair.proxy, "bar", desc);', TypeError);
+
+// Step 6: Trap isn't callable.
+handler.defineProperty = 1;
+assertThrows("Object.defineProperty(proxy, 'foo', {value: 2})", TypeError);
+
+// Step 7: Trap is undefined.
+handler.defineProperty = undefined;
+Object.defineProperty(proxy, "prop1", desc);
+assertEquals(desc, Object.getOwnPropertyDescriptor(target, "prop1"));
+var target2 = {};
+var proxy2 = new Proxy(target2, {});
+Object.defineProperty(proxy2, "prop2", desc);
+assertEquals(desc, Object.getOwnPropertyDescriptor(target2, "prop2"));
+
+// Step 9: Property name is passed to the trap as a string.
+handler.defineProperty = function(t, name, d) { g_name = name; return true; };
+Object.defineProperty(proxy, 0, desc);
+assertTrue(typeof g_name === "string");
+assertEquals("0", g_name);
+
+// Step 10: Trap returns false.
+handler.defineProperty = function(t, n, d) { return false; }
+assertThrows("Object.defineProperty(proxy, 'foo', desc)", TypeError);
+
+// Step 15a: Trap returns true for adding a property to a non-extensible target.
+handler.defineProperty = function(t, n, d) { return true; }
+Object.preventExtensions(target);
+assertThrows("Object.defineProperty(proxy, 'foo', desc)", TypeError);
+
+// Step 15b: Trap returns true for adding a non-configurable property.
+target = {};
+proxy = new Proxy(target, handler);
+desc = {value: 1, writable: true, configurable: false, enumerable: true};
+assertThrows("Object.defineProperty(proxy, 'foo', desc)", TypeError);
+// No exception is thrown if a non-configurable property exists on the target.
+Object.defineProperty(target, "nonconf",
+ {value: 1, writable: true, configurable: false});
+Object.defineProperty(proxy, "nonconf", {value: 2, configurable: false});
+
+// Step 16a: Trap returns true for non-compatible property descriptor.
+Object.defineProperty(target, "foo",
+ {value: 1, writable: false, configurable: false});
+assertThrows("Object.defineProperty(proxy, 'foo', {value: 2})", TypeError);
+
+// Step 16b: Trap returns true for overwriting a configurable property
+// with a non-configurable descriptor.
+target.bar = "baz";
+assertThrows("Object.defineProperty(proxy, 'bar', {configurable: false})",
+ TypeError);
diff --git a/test/mjsunit/es6/proxies-delete-property.js b/test/mjsunit/es6/proxies-delete-property.js
new file mode 100644
index 0000000..7a46b9b
--- /dev/null
+++ b/test/mjsunit/es6/proxies-delete-property.js
@@ -0,0 +1,188 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+var properties =
+ ["bla", "0", 1, Symbol(), {[Symbol.toPrimitive]() {return "a"}}];
+
+
+function TestForwarding(handler, myDelete, shouldThrow) {
+ var target = {};
+ var proxy = new Proxy(target, handler);
+
+ assertFalse(target.hasOwnProperty("doesnotexist"));
+ assertTrue(myDelete(proxy, "doesnotexist"));
+
+ for (p of properties) {
+ target[p] = 42;
+ assertTrue(myDelete(proxy, p));
+ assertFalse(target.hasOwnProperty(p));
+ }
+
+ for (p of properties) {
+ Object.defineProperty(target, p, {value: 42, configurable: false});
+ if (shouldThrow) {
+ assertThrows(() => myDelete(proxy, p), TypeError);
+ } else {
+ assertFalse(myDelete(proxy, p));
+ }
+ assertTrue(target.hasOwnProperty(p));
+ }
+};
+
+
+(function () {
+ // No trap.
+
+ var handler = {};
+
+ TestForwarding(handler,
+ (o, p) => delete o[p], false);
+ TestForwarding(handler,
+ (o, p) => Reflect.deleteProperty(o, p), false);
+ TestForwarding(handler,
+ (o, p) => {"use strict"; return delete o[p]}, true);
+ TestForwarding(handler,
+ (o, p) => {"use strict"; return Reflect.deleteProperty(o, p)}, false);
+})();
+
+
+(function () {
+ // "Undefined" trap.
+
+ var handler = { deleteProperty: null };
+
+ TestForwarding(handler,
+ (o, p) => delete o[p], false);
+ TestForwarding(handler,
+ (o, p) => Reflect.deleteProperty(o, p), false);
+ TestForwarding(handler,
+ (o, p) => {"use strict"; return delete o[p]}, true);
+ TestForwarding(handler,
+ (o, p) => {"use strict"; return Reflect.deleteProperty(o, p)}, false);
+})();
+
+
+(function () {
+ // Invalid trap.
+
+ var target = {};
+ var handler = { deleteProperty: true };
+ var proxy = new Proxy(target, handler);
+
+ assertThrows(() => delete proxy[0], TypeError);
+ assertThrows(() => Reflect.deleteProperty(proxy, 0), TypeError);
+})();
+
+
+function TestTrappingTrueish(myDelete) {
+ var handler = { deleteProperty() {return 42} };
+ var target = {};
+ var proxy = new Proxy(target, handler);
+
+ // Trap returns trueish and target doesn't own property.
+ for (p of properties) {
+ assertTrue(myDelete(proxy, p));
+ }
+
+ // Trap returns trueish and target property is configurable.
+ for (p of properties) {
+ target[p] = 42;
+ assertTrue(myDelete(proxy, p));
+ }
+
+ // Trap returns trueish but target property is not configurable.
+ for (p of properties) {
+ Object.defineProperty(target, p, {value: 42, configurable: false});
+ assertThrows(() => myDelete(proxy, p), TypeError);
+ }
+};
+
+
+TestTrappingTrueish(
+ (o, p) => delete o[p]);
+TestTrappingTrueish(
+ (o, p) => Reflect.deleteProperty(o, p));
+TestTrappingTrueish(
+ (o, p) => {"use strict"; return delete o[p]});
+TestTrappingTrueish(
+ (o, p) => {"use strict"; return Reflect.deleteProperty(o, p)});
+
+
+function TestTrappingTrueish2(myDelete) {
+ var handler = {
+ deleteProperty(target, p) {
+ Object.defineProperty(target, p, {configurable: false});
+ return 42
+ }
+ };
+ var target = {};
+ var proxy = new Proxy(target, handler);
+
+ // Trap returns trueish but target property is not configurable. In contrast
+ // to above, here the target property was configurable before the trap call.
+ for (p of properties) {
+ target[p] = 42;
+ assertThrows(() => myDelete(proxy, p), TypeError);
+ }
+};
+
+
+TestTrappingTrueish2(
+ (o, p) => delete o[p]);
+TestTrappingTrueish2(
+ (o, p) => Reflect.deleteProperty(o, p));
+TestTrappingTrueish2(
+ (o, p) => {"use strict"; return delete o[p]});
+TestTrappingTrueish2(
+ (o, p) => {"use strict"; return Reflect.deleteProperty(o, p)});
+
+
+function TestTrappingFalsish(myDelete, shouldThrow) {
+ var handler = { deleteProperty() {return ""} };
+ var target = {};
+ var proxy = new Proxy(target, handler);
+
+ var properties =
+ ["bla", "0", 1, Symbol(), {[Symbol.toPrimitive]() {return "a"}}];
+
+ // Trap returns falsish and target doesn't own property.
+ for (p of properties) {
+ if (shouldThrow) {
+ assertThrows(() => myDelete(proxy, p), TypeError);
+ } else {
+ assertFalse(myDelete(proxy, p));
+ }
+ }
+
+ // Trap returns falsish and target property is configurable.
+ for (p of properties) {
+ target[p] = 42;
+ if (shouldThrow) {
+ assertThrows(() => myDelete(proxy, p), TypeError);
+ } else {
+ assertFalse(myDelete(proxy, p));
+ }
+ }
+
+ // Trap returns falsish and target property is not configurable.
+ for (p of properties) {
+ Object.defineProperty(target, p, {value: 42, configurable: false});
+ if (shouldThrow) {
+ assertThrows(() => myDelete(proxy, p), TypeError);
+ } else {
+ assertFalse(myDelete(proxy, p));
+ }
+ }
+};
+
+
+TestTrappingFalsish(
+ (o, p) => delete o[p], false);
+TestTrappingFalsish(
+ (o, p) => Reflect.deleteProperty(o, p), false);
+TestTrappingFalsish(
+ (o, p) => {"use strict"; return delete o[p]}, true);
+TestTrappingFalsish(
+ (o, p) => {"use strict"; return Reflect.deleteProperty(o, p)}, false);
diff --git a/test/mjsunit/es6/proxies-example-membrane.js b/test/mjsunit/es6/proxies-example-membrane.js
new file mode 100644
index 0000000..dd373b7
--- /dev/null
+++ b/test/mjsunit/es6/proxies-example-membrane.js
@@ -0,0 +1,308 @@
+// Copyright 2011 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.
+
+
+// A simple membrane. Adapted from:
+// http://wiki.ecmascript.org/doku.php?id=harmony:proxies#a_simple_membrane
+
+function createSimpleMembrane(target) {
+ let enabled = true;
+
+ function wrap(obj) {
+ if (obj !== Object(obj)) return obj;
+
+ let handler = new Proxy({}, {get: function(_, key) {
+ if (!enabled) throw new Error("disabled");
+ switch (key) {
+ case "apply":
+ return (_, that, args) => {
+ try {
+ return wrap(Reflect.apply(
+ obj, wrap(that), args.map((x) => wrap(x))));
+ } catch(e) {
+ throw wrap(e);
+ }
+ }
+ case "construct":
+ return (_, args, newt) => {
+ try {
+ return wrap(Reflect.construct(
+ obj, args.map((x) => wrap(x)), wrap(newt)));
+ } catch(e) {
+ throw wrap(e);
+ }
+ }
+ default:
+ return (_, ...args) => {
+ try {
+ return wrap(Reflect[key](obj, ...(args.map(wrap))));
+ } catch(e) {
+ throw wrap(e);
+ }
+ }
+ }
+ }});
+
+ return new Proxy(obj, handler);
+ }
+
+ const gate = Object.freeze({
+ enable: () => enabled = true,
+ disable: () => enabled = false
+ });
+
+ return Object.freeze({
+ wrapper: wrap(target),
+ gate: gate
+ });
+}
+
+
+// Test the simple membrane.
+{
+ var o = {
+ a: 6,
+ b: {bb: 8},
+ f: function(x) { return x },
+ g: function(x) { return x.a },
+ h: function(x) { this.q = x }
+ };
+ o[2] = {c: 7};
+ var m = createSimpleMembrane(o);
+ var w = m.wrapper;
+ var f = w.f;
+ var x = f(66);
+ var x = f({a: 1});
+ var x = w.f({a: 1});
+ var a = x.a;
+ assertEquals(6, w.a);
+ assertEquals(8, w.b.bb);
+ assertEquals(7, w[2]["c"]);
+ assertEquals(undefined, w.c);
+ assertEquals(1, w.f(1));
+ assertEquals(1, w.f({a: 1}).a);
+ assertEquals(2, w.g({a: 2}));
+ assertEquals(3, (w.r = {a: 3}).a);
+ assertEquals(3, w.r.a);
+ assertEquals(3, o.r.a);
+ w.h(3);
+ assertEquals(3, w.q);
+ assertEquals(3, o.q);
+ assertEquals(4, (new w.h(4)).q);
+
+ var wb = w.b;
+ var wr = w.r;
+ var wf = w.f;
+ var wf3 = w.f(3);
+ var wfx = w.f({a: 6});
+ var wgx = w.g({a: {aa: 7}});
+ var wh4 = new w.h(4);
+ m.gate.disable();
+ assertEquals(3, wf3);
+ assertThrows(function() { w.a }, Error);
+ assertThrows(function() { w.r }, Error);
+ assertThrows(function() { w.r = {a: 4} }, Error);
+ assertThrows(function() { o.r.a }, Error);
+ assertEquals("object", typeof o.r);
+ assertEquals(5, (o.r = {a: 5}).a);
+ assertEquals(5, o.r.a);
+ assertThrows(function() { w[1] }, Error);
+ assertThrows(function() { w.c }, Error);
+ assertThrows(function() { wb.bb }, Error);
+ assertThrows(function() { wr.a }, Error);
+ assertThrows(function() { wf(4) }, Error);
+ assertThrows(function() { wfx.a }, Error);
+ assertThrows(function() { wgx.aa }, Error);
+ assertThrows(function() { wh4.q }, Error);
+
+ m.gate.enable();
+ assertEquals(6, w.a);
+ assertEquals(5, w.r.a);
+ assertEquals(5, o.r.a);
+ assertEquals(7, w.r = 7);
+ assertEquals(7, w.r);
+ assertEquals(7, o.r);
+ assertEquals(8, w.b.bb);
+ assertEquals(7, w[2]["c"]);
+ assertEquals(undefined, w.c);
+ assertEquals(8, wb.bb);
+ assertEquals(3, wr.a);
+ assertEquals(4, wf(4));
+ assertEquals(3, wf3);
+ assertEquals(6, wfx.a);
+ assertEquals(7, wgx.aa);
+ assertEquals(4, wh4.q);
+}
+
+
+
+// An identity-preserving membrane. Adapted from:
+// http://wiki.ecmascript.org/doku.php?id=harmony:proxies#an_identity-preserving_membrane
+
+function createMembrane(target) {
+ const wet2dry = 0;
+ const dry2wet = 1;
+
+ function flip(dir) { return (dir + 1) % 2 }
+
+ let maps = [new WeakMap(), new WeakMap()];
+
+ let revoked = false;
+
+ function wrap(dir, obj) {
+ if (obj !== Object(obj)) return obj;
+
+ let wrapper = maps[dir].get(obj);
+ if (wrapper) return wrapper;
+
+ let handler = new Proxy({}, {get: function(_, key) {
+ if (revoked) throw new Error("revoked");
+ switch (key) {
+ case "apply":
+ return (_, that, args) => {
+ try {
+ return wrap(dir, Reflect.apply(
+ obj, wrap(flip(dir), that),
+ args.map((x) => wrap(flip(dir), x))));
+ } catch(e) {
+ throw wrap(dir, e);
+ }
+ }
+ case "construct":
+ return (_, args, newt) => {
+ try {
+ return wrap(dir, Reflect.construct(
+ obj, args.map((x) => wrap(flip(dir), x)),
+ wrap(flip(dir), newt)));
+ } catch(e) {
+ throw wrap(dir, e);
+ }
+ }
+ default:
+ return (_, ...args) => {
+ try {
+ return wrap(dir, Reflect[key](
+ obj, ...(args.map((x) => wrap(flip(dir), x)))))
+ } catch(e) {
+ throw wrap(dir, e);
+ }
+ }
+ }
+ }});
+
+ wrapper = new Proxy(obj, handler);
+ maps[dir].set(obj, wrapper);
+ maps[flip(dir)].set(wrapper, obj);
+ return wrapper;
+ }
+
+ const gate = Object.freeze({
+ revoke: () => revoked = true
+ });
+
+ return Object.freeze({
+ wrapper: wrap(wet2dry, target),
+ gate: gate
+ });
+}
+
+
+// Test the identity-preserving membrane.
+{
+ var receiver
+ var argument
+ var o = {
+ a: 6,
+ b: {bb: 8},
+ f: function(x) {receiver = this; argument = x; return x},
+ g: function(x) {receiver = this; argument = x; return x.a},
+ h: function(x) {receiver = this; argument = x; this.q = x},
+ s: function(x) {receiver = this; argument = x; this.x = {y: x}; return this}
+ }
+ o[2] = {c: 7}
+ var m = createMembrane(o)
+ var w = m.wrapper
+ var f = w.f
+ var x = f(66)
+ var x = f({a: 1})
+ var x = w.f({a: 1})
+ var a = x.a
+ assertEquals(6, w.a)
+ assertEquals(8, w.b.bb)
+ assertEquals(7, w[2]["c"])
+ assertEquals(undefined, w.c)
+ assertEquals(1, w.f(1))
+ assertSame(o, receiver)
+ assertEquals(1, w.f({a: 1}).a)
+ assertSame(o, receiver)
+ assertEquals(2, w.g({a: 2}))
+ assertSame(o, receiver)
+ assertSame(w, w.f(w))
+ assertSame(o, receiver)
+ assertSame(o, argument)
+ assertSame(o, w.f(o))
+ assertSame(o, receiver)
+ // Note that argument !== o, since o isn't dry, so gets wrapped wet again.
+ assertEquals(3, (w.r = {a: 3}).a)
+ assertEquals(3, w.r.a)
+ assertEquals(3, o.r.a)
+ w.h(3)
+ assertEquals(3, w.q)
+ assertEquals(3, o.q)
+ assertEquals(4, (new w.h(4)).q)
+ assertEquals(5, w.s(5).x.y)
+ assertSame(o, receiver)
+
+ var wb = w.b
+ var wr = w.r
+ var wf = w.f
+ var wf3 = w.f(3)
+ var wfx = w.f({a: 6})
+ var wgx = w.g({a: {aa: 7}})
+ var wh4 = new w.h(4)
+ var ws5 = w.s(5)
+ var ws5x = ws5.x
+ m.gate.revoke()
+ assertEquals(3, wf3)
+ assertThrows(function() { w.a }, Error)
+ assertThrows(function() { w.r }, Error)
+ assertThrows(function() { w.r = {a: 4} }, Error)
+ assertThrows(function() { o.r.a }, Error)
+ assertEquals("object", typeof o.r)
+ assertEquals(5, (o.r = {a: 5}).a)
+ assertEquals(5, o.r.a)
+ assertThrows(function() { w[1] }, Error)
+ assertThrows(function() { w.c }, Error)
+ assertThrows(function() { wb.bb }, Error)
+ assertEquals(3, wr.a)
+ assertThrows(function() { wf(4) }, Error)
+ assertEquals(6, wfx.a)
+ assertEquals(7, wgx.aa)
+ assertThrows(function() { wh4.q }, Error)
+ assertThrows(function() { ws5.x }, Error)
+ assertThrows(function() { ws5x.y }, Error)
+}
diff --git a/test/mjsunit/es6/proxies-for.js b/test/mjsunit/es6/proxies-for.js
new file mode 100644
index 0000000..5b81845
--- /dev/null
+++ b/test/mjsunit/es6/proxies-for.js
@@ -0,0 +1,218 @@
+// Copyright 2011 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.
+
+// Helper.
+
+function TestWithProxies(test, x, y, z) {
+ test(function(h){ return new Proxy({}, h) }, x, y, z)
+}
+
+
+// Iterate over a proxy.
+
+function TestForIn(properties, handler) {
+ TestWithProxies(TestForIn2, properties, handler)
+}
+
+function TestForIn2(create, properties, handler) {
+ var p = create(handler)
+ var found = []
+ for (var x in p) found.push(x)
+ assertArrayEquals(properties, found)
+}
+
+TestForIn(["0", "a"], {
+ ownKeys() { return ["0", "a"] },
+ has(target, property) { return true },
+ getOwnPropertyDescriptor() { return { enumerable: true, configurable: true }}
+})
+
+TestForIn(["null", "a"], {
+ ownKeys() { return this.enumerate() },
+ enumerate() { return ["null", "a"] },
+ has(target, property) { return true },
+ getOwnPropertyDescriptor() { return { enumerable: true, configurable: true }}
+})
+
+
+// Iterate over an object with a proxy prototype.
+
+function TestForInDerived(properties, handler) {
+ TestWithProxies(TestForInDerived2, properties, handler)
+}
+
+function TestForInDerived2(create, properties, handler) {
+ var p = create(handler)
+ var o = Object.create(p)
+ o.z = 0
+ var found = []
+ for (var x in o) found.push(x)
+ assertArrayEquals(["z"].concat(properties), found)
+
+ var oo = Object.create(o)
+ oo.y = 0
+ var found = []
+ for (var x in oo) found.push(x)
+ assertArrayEquals(["y", "z"].concat(properties), found)
+}
+
+TestForInDerived(["0", "a"], {
+ ownKeys: function() { return ["0", "a"] },
+ has: function(t, k) { return k == "0" || k == "a" },
+ getOwnPropertyDescriptor() { return { enumerable: true, configurable: true }}
+})
+
+TestForInDerived(["null", "a"], {
+ ownKeys: function() { return this.enumerate() },
+ enumerate: function() { return ["null", "a"] },
+ has: function(t, k) { return k == "null" || k == "a" },
+ getOwnPropertyDescriptor() { return { enumerable: true, configurable: true }}
+})
+
+
+
+// Throw exception in ownKeys trap.
+
+function TestForInThrow(handler) {
+ TestWithProxies(TestForInThrow2, handler)
+}
+
+function TestForInThrow2(create, handler) {
+ var p = create(handler)
+ var o = Object.create(p)
+ assertThrowsEquals(function(){ for (var x in p) {} }, "myexn")
+ assertThrowsEquals(function(){ for (var x in o) {} }, "myexn")
+}
+
+TestForInThrow({
+ ownKeys: function() { throw "myexn" }
+})
+
+TestForInThrow({
+ ownKeys: function() { return this.enumerate() },
+ enumerate: function() { throw "myexn" }
+})
+
+TestForInThrow(new Proxy({}, {
+ get: function(pr, pk) {
+ return function() { throw "myexn" }
+ }
+}));
+
+
+function keys(object) {
+ var keys = [];
+ for (var k in object) {
+ keys.push(k);
+ }
+ return keys;
+}
+
+(function testKeysProxyOnProtoEmpty() {
+ var p = new Proxy({}, {
+ ownKeys() { return []; },
+ });
+ var o = [0];
+ o.__proto__ = p;
+ assertEquals(["0"], keys(o));
+
+ delete o[0];
+ assertEquals([], keys(o));
+})();
+
+(function testKeysProxyOnProto() {
+ var handler = {ownKeys() { return ["0"]; }};
+ var proxy = new Proxy({}, handler);
+ var object = [0];
+ object.__proto__ = proxy;
+ assertEquals(["0"], keys(object));
+
+ // The Proxy doesn't set his ownKeys enumerable.
+ delete object[0];
+ assertEquals([], keys(object));
+
+ // The [[Has]] trap has no influence on which are enumerable properties are
+ // shown in for-in.
+ handler.has = function() { return true };
+ assertEquals([], keys(object));
+
+ handler.getOwnPropertyDescriptor = function() {
+ return {enumerable: true, configurable: true}
+ }
+ assertEquals(["0"], keys(object));
+})();
+
+(function testKeysProxyProto() {
+ var target = {t1:true, t2:true};
+ var handler = {};
+ var proxy = new Proxy(target, handler);
+
+ assertEquals(["t1", "t2"], keys(proxy));
+
+ target.__proto__ = {p1:true, p2:true};
+ assertEquals(["t1", "t2", "p1", "p2"], keys(proxy));
+
+ handler.getPrototypeOf = function(target) {
+ return {p3:true, p4:true};
+ };
+ // for-in walks the prototype chain for the [[Has]] / Enumerable check.
+ assertEquals(["t1", "t2", "p3", "p4"], keys(proxy));
+
+ // [[Has]] is not used in for-in.
+ handler.has = function() { return false };
+ assertEquals(["t1", "t2", "p3", "p4"], keys(proxy));
+
+ // Proxy intercepts enumerability check.
+ handler.getOwnPropertyDescriptor = function() {
+ return {enumerable: false, configurable: true}
+ }
+ assertEquals([], keys(proxy));
+
+ handler.getOwnPropertyDescriptor = function() {
+ return {enumerable: true, configurable: true}
+ }
+ assertEquals(["t1", "t2", "p3", "p4"], keys(proxy));
+
+ handler.getOwnPropertyDescriptor = function(target, key) {
+ return {
+ enumerable: key in target,
+ configurable: true
+ }
+ }
+ assertEquals(["t1", "t2"], keys(proxy));
+
+ handler.getPrototypeOf = function() { throw "error" };
+ assertThrowsEquals(() => {keys(proxy)}, "error");
+})();
+
+
+(function () {
+ var symbol = Symbol();
+ var p = new Proxy({}, {ownKeys() { return ["1", symbol, "2"] }});
+ assertEquals(["1","2"], Object.getOwnPropertyNames(p));
+ assertEquals([symbol], Object.getOwnPropertySymbols(p));
+})();
diff --git a/test/mjsunit/es6/proxies-function.js b/test/mjsunit/es6/proxies-function.js
new file mode 100644
index 0000000..cb3a26c
--- /dev/null
+++ b/test/mjsunit/es6/proxies-function.js
@@ -0,0 +1,630 @@
+// Copyright 2011 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: --allow-natives-syntax
+
+
+var handler = {
+ get : function(r, n) { return n == "length" ? 2 : undefined }
+}
+
+
+// Calling (call, Function.prototype.call, Function.prototype.apply,
+// Function.prototype.bind).
+
+var global_object = this
+var receiver
+
+function TestCall(isStrict, callTrap) {
+ assertEquals(42, callTrap(undefined, undefined, [5, 37]))
+
+ var handler = {
+ get: function(r, k) {
+ return k == "length" ? 2 : Function.prototype[k]
+ },
+ apply: callTrap
+ }
+ var f = new Proxy(()=>{}, handler)
+ var o = {f: f}
+ global_object.f = f
+
+ receiver = 333
+ assertEquals(42, f(11, 31))
+ receiver = 333
+ assertEquals(42, o.f(10, 32))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, o["f"](9, 33))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, (1, o).f(8, 34))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, (1, o)["f"](7, 35))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, f.call(o, 32, 10))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, f.call(undefined, 33, 9))
+ receiver = 333
+ assertEquals(42, f.call(null, 33, 9))
+ receiver = 333
+ assertEquals(44, f.call(2, 21, 23))
+ assertSame(2, receiver.valueOf())
+ receiver = 333
+ assertEquals(42, Function.prototype.call.call(f, o, 20, 22))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(43, Function.prototype.call.call(f, null, 20, 23))
+ assertEquals(44, Function.prototype.call.call(f, 2, 21, 23))
+ assertEquals(2, receiver.valueOf())
+ receiver = 333
+ assertEquals(32, f.apply(o, [16, 16]))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(32, Function.prototype.apply.call(f, o, [17, 15]))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, %Call(f, o, 11, 31));
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, %Call(f, null, 11, 31));
+ receiver = 333
+ assertEquals(42, %_Call(f, o, 11, 31))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, %_Call(f, null, 11, 31))
+
+ var ff = Function.prototype.bind.call(f, o, 12)
+ assertTrue(ff.length <= 1) // TODO(rossberg): Not spec'ed yet, be lax.
+ receiver = 333
+ assertEquals(42, ff(30))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(33, Function.prototype.call.call(ff, {}, 21))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(32, Function.prototype.apply.call(ff, {}, [20]))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(23, %Call(ff, {}, 11));
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(23, %Call(ff, {}, 11, 3));
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(34, %_Call(ff, {}, 22))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(34, %_Call(ff, {}, 22, 3))
+ assertSame(o, receiver)
+
+ var fff = Function.prototype.bind.call(ff, o, 30)
+ assertEquals(0, fff.length)
+ receiver = 333
+ assertEquals(42, fff())
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, Function.prototype.call.call(fff, {}))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, Function.prototype.apply.call(fff, {}))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, %Call(fff, {}));
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, %Call(fff, {}, 11, 3))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, %_Call(fff, {}))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, %_Call(fff, {}, 3, 4, 5))
+ assertSame(o, receiver)
+
+ var f = new Proxy(()=>{}, {apply: callTrap})
+ receiver = 333
+ assertEquals(42, f(11, 31))
+ var o = {f: f}
+ receiver = 333
+ assertEquals(42, o.f(10, 32))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, o["f"](9, 33))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, (1, o).f(8, 34))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, (1, o)["f"](7, 35))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, Function.prototype.call.call(f, o, 20, 22))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(32, Function.prototype.apply.call(f, o, [17, 15]))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(23, %Call(f, o, 11, 12))
+ assertSame(o, receiver)
+ receiver = 333
+ assertEquals(42, %_Call(f, o, 18, 24))
+ assertSame(o, receiver)
+}
+
+TestCall(false, function(_, that, [x, y]) {
+ receiver = that
+ return x + y
+})
+
+TestCall(true, function(_, that, args) {
+ "use strict"
+ receiver = that
+ return args[0] + args[1]
+})
+
+TestCall(false, function() {
+ receiver = arguments[1]
+ return arguments[2][0] + arguments[2][1]
+})
+
+TestCall(false, new Proxy(function(_, that, [x, y]) {
+ receiver = that
+ return x + y
+ }, handler))
+
+TestCall(true, new Proxy(function(_, that, args) {
+ "use strict"
+ receiver = that
+ return args[0] + args[1]
+ }, handler))
+
+TestCall(false, Object.freeze(new Proxy(function(_, that, [x, y]) {
+ receiver = that
+ return x + y
+ }, handler)))
+
+
+
+// Using intrinsics as call traps.
+
+function TestCallIntrinsic(type, callTrap) {
+ var f = new Proxy(()=>{}, {apply: (_, that, args) => callTrap(...args)})
+ var x = f()
+ assertTrue(typeof x == type)
+}
+
+TestCallIntrinsic("boolean", Boolean)
+TestCallIntrinsic("number", Number)
+TestCallIntrinsic("string", String)
+TestCallIntrinsic("object", Object)
+TestCallIntrinsic("function", Function)
+
+
+
+// Throwing from call trap.
+
+function TestCallThrow(callTrap) {
+ var f = new Proxy(()=>{}, {apply: callTrap})
+ assertThrowsEquals(() => f(11), "myexn")
+ assertThrowsEquals(() => ({x: f}).x(11), "myexn")
+ assertThrowsEquals(() => ({x: f})["x"](11), "myexn")
+ assertThrowsEquals(() => Function.prototype.call.call(f, {}, 2), "myexn")
+ assertThrowsEquals(() => Function.prototype.apply.call(f, {}, [1]), "myexn")
+ assertThrowsEquals(() => %Call(f, {}), "myexn")
+ assertThrowsEquals(() => %Call(f, {}, 1, 2), "myexn")
+ assertThrowsEquals(() => %_Call(f, {}), "myexn")
+ assertThrowsEquals(() => %_Call(f, {}, 1, 2), "myexn")
+
+ var f = Object.freeze(new Proxy(()=>{}, {apply: callTrap}))
+ assertThrowsEquals(() => f(11), "myexn")
+ assertThrowsEquals(() => ({x: f}).x(11), "myexn")
+ assertThrowsEquals(() => ({x: f})["x"](11), "myexn")
+ assertThrowsEquals(() => Function.prototype.call.call(f, {}, 2), "myexn")
+ assertThrowsEquals(() => Function.prototype.apply.call(f, {}, [1]), "myexn")
+ assertThrowsEquals(() => %Call(f, {}), "myexn")
+ assertThrowsEquals(() => %Call(f, {}, 1, 2), "myexn")
+ assertThrowsEquals(() => %_Call(f, {}), "myexn")
+ assertThrowsEquals(() => %_Call(f, {}, 1, 2), "myexn")
+}
+
+TestCallThrow(function() { throw "myexn" })
+TestCallThrow(new Proxy(() => {throw "myexn"}, {}))
+TestCallThrow(Object.freeze(new Proxy(() => {throw "myexn"}, {})))
+
+
+
+// Construction (new).
+
+var prototype = {myprop: 0}
+var receiver
+
+var handlerWithPrototype = {
+ get: function(r, n) {
+ if (n == "length") return 2;
+ assertEquals("prototype", n);
+ return prototype;
+ }
+}
+
+var handlerSansPrototype = {
+ get: function(r, n) {
+ if (n == "length") return 2;
+ assertEquals("prototype", n);
+ return undefined;
+ }
+}
+
+function ReturnUndef(_, args, newt) {
+ "use strict";
+ newt.sum = args[0] + args[1];
+}
+
+function ReturnThis(x, y) {
+ "use strict";
+ receiver = this;
+ this.sum = x + y;
+ return this;
+}
+
+function ReturnNew(_, args, newt) {
+ "use strict";
+ return {sum: args[0] + args[1]};
+}
+
+function ReturnNewWithProto(_, args, newt) {
+ "use strict";
+ var result = Object.create(prototype);
+ result.sum = args[0] + args[1];
+ return result;
+}
+
+function TestConstruct(proto, constructTrap) {
+ TestConstruct2(proto, constructTrap, handlerWithPrototype)
+ TestConstruct2(proto, constructTrap, handlerSansPrototype)
+}
+
+function TestConstruct2(proto, constructTrap, handler) {
+ var f = new Proxy(function(){}, {construct: constructTrap})
+ var o = new f(11, 31)
+ assertEquals(42, o.sum)
+ assertSame(proto, Object.getPrototypeOf(o))
+
+ var f = Object.freeze(new Proxy(function(){}, {construct: constructTrap}))
+ var o = new f(11, 32)
+ assertEquals(43, o.sum)
+ assertSame(proto, Object.getPrototypeOf(o))
+}
+
+TestConstruct(Object.prototype, ReturnNew)
+TestConstruct(prototype, ReturnNewWithProto)
+
+TestConstruct(Object.prototype, new Proxy(ReturnNew, {}))
+TestConstruct(prototype, new Proxy(ReturnNewWithProto, {}))
+
+TestConstruct(Object.prototype, Object.freeze(new Proxy(ReturnNew, {})))
+TestConstruct(prototype, Object.freeze(new Proxy(ReturnNewWithProto, {})))
+
+
+
+// Throwing from the construct trap.
+
+function TestConstructThrow(trap) {
+ var f = new Proxy(function(){}, {construct: trap});
+ assertThrowsEquals(() => new f(11), "myexn")
+ Object.freeze(f)
+ assertThrowsEquals(() => new f(11), "myexn")
+}
+
+TestConstructThrow(function() { throw "myexn" })
+TestConstructThrow(new Proxy(function() { throw "myexn" }, {}))
+TestConstructThrow(Object.freeze(new Proxy(function() { throw "myexn" }, {})))
+
+
+
+// Using function proxies as getters and setters.
+
+var value
+var receiver
+
+function TestAccessorCall(getterCallTrap, setterCallTrap) {
+ var pgetter = new Proxy(()=>{}, {apply: getterCallTrap})
+ var psetter = new Proxy(()=>{}, {apply: setterCallTrap})
+
+ var o = {}
+ var oo = Object.create(o)
+ Object.defineProperty(o, "a", {get: pgetter, set: psetter})
+ Object.defineProperty(o, "b", {get: pgetter})
+ Object.defineProperty(o, "c", {set: psetter})
+ Object.defineProperty(o, "3", {get: pgetter, set: psetter})
+ Object.defineProperty(oo, "a", {value: 43})
+
+ receiver = ""
+ assertEquals(42, o.a)
+ assertSame(o, receiver)
+ receiver = ""
+ assertEquals(42, o.b)
+ assertSame(o, receiver)
+ receiver = ""
+ assertEquals(undefined, o.c)
+ assertEquals("", receiver)
+ receiver = ""
+ assertEquals(42, o["a"])
+ assertSame(o, receiver)
+ receiver = ""
+ assertEquals(42, o[3])
+ assertSame(o, receiver)
+
+ receiver = ""
+ assertEquals(43, oo.a)
+ assertEquals("", receiver)
+ receiver = ""
+ assertEquals(42, oo.b)
+ assertSame(oo, receiver)
+ receiver = ""
+ assertEquals(undefined, oo.c)
+ assertEquals("", receiver)
+ receiver = ""
+ assertEquals(43, oo["a"])
+ assertEquals("", receiver)
+ receiver = ""
+ assertEquals(42, oo[3])
+ assertSame(oo, receiver)
+
+ receiver = ""
+ assertEquals(50, o.a = 50)
+ assertSame(o, receiver)
+ assertEquals(50, value)
+ receiver = ""
+ assertEquals(51, o.b = 51)
+ assertEquals("", receiver)
+ assertEquals(50, value) // no setter
+ assertThrows(function() { "use strict"; o.b = 51 }, TypeError)
+ receiver = ""
+ assertEquals(52, o.c = 52)
+ assertSame(o, receiver)
+ assertEquals(52, value)
+ receiver = ""
+ assertEquals(53, o["a"] = 53)
+ assertSame(o, receiver)
+ assertEquals(53, value)
+ receiver = ""
+ assertEquals(54, o[3] = 54)
+ assertSame(o, receiver)
+ assertEquals(54, value)
+
+ value = 0
+ receiver = ""
+ assertEquals(60, oo.a = 60)
+ assertEquals("", receiver)
+ assertEquals(0, value) // oo has own 'a'
+ assertEquals(61, oo.b = 61)
+ assertSame("", receiver)
+ assertEquals(0, value) // no setter
+ assertThrows(function() { "use strict"; oo.b = 61 }, TypeError)
+ receiver = ""
+ assertEquals(62, oo.c = 62)
+ assertSame(oo, receiver)
+ assertEquals(62, value)
+ receiver = ""
+ assertEquals(63, oo["c"] = 63)
+ assertSame(oo, receiver)
+ assertEquals(63, value)
+ receiver = ""
+ assertEquals(64, oo[3] = 64)
+ assertSame(oo, receiver)
+ assertEquals(64, value)
+}
+
+TestAccessorCall(
+ function(_, that) { receiver = that; return 42 },
+ function(_, that, [x]) { receiver = that; value = x }
+)
+
+TestAccessorCall(
+ function(_, that) { "use strict"; receiver = that; return 42 },
+ function(_, that, args) { "use strict"; receiver = that; value = args[0] }
+)
+
+TestAccessorCall(
+ new Proxy(function(_, that) { receiver = that; return 42 }, {}),
+ new Proxy(function(_, that, [x]) { receiver = that; value = x }, {})
+)
+
+TestAccessorCall(
+ Object.freeze(
+ new Proxy(function(_, that) { receiver = that; return 42 }, {})),
+ Object.freeze(
+ new Proxy(function(_, that, [x]) { receiver = that; value = x }, {}))
+)
+
+
+// Passing a proxy function to higher-order library functions.
+
+function TestHigherOrder(f) {
+ assertEquals(6, [6, 2].map(f)[0])
+ assertEquals(4, [5, 2].reduce(f, 4))
+ assertTrue([1, 2].some(f))
+ assertEquals("a.b.c", "a.b.c".replace(".", f))
+}
+
+TestHigherOrder(function(x) { return x })
+TestHigherOrder(function(x) { "use strict"; return x })
+TestHigherOrder(new Proxy(function(x) { return x }, {}))
+TestHigherOrder(Object.freeze(new Proxy(function(x) { return x }, {})))
+
+
+
+// TODO(rossberg): Ultimately, I want to have the following test function
+// run through, but it currently fails on so many cases (some not even
+// involving proxies), that I leave that for later...
+/*
+function TestCalls() {
+ var handler = {
+ get: function(r, k) {
+ return k == "length" ? 2 : Function.prototype[k]
+ }
+ }
+ var bind = Function.prototype.bind
+ var o = {}
+
+ var traps = [
+ function(x, y) {
+ return {receiver: this, result: x + y, strict: false}
+ },
+ function(x, y) { "use strict";
+ return {receiver: this, result: x + y, strict: true}
+ },
+ function() {
+ var x = arguments[0], y = arguments[1]
+ return {receiver: this, result: x + y, strict: false}
+ },
+ Proxy.createFunction(handler, function(x, y) {
+ return {receiver: this, result: x + y, strict: false}
+ }),
+ Proxy.createFunction(handler, function() {
+ var x = arguments[0], y = arguments[1]
+ return {receiver: this, result: x + y, strict: false}
+ }),
+ Proxy.createFunction(handler, function(x, y) { "use strict"
+ return {receiver: this, result: x + y, strict: true}
+ }),
+ CreateFrozen(handler, function(x, y) {
+ return {receiver: this, result: x + y, strict: false}
+ }),
+ CreateFrozen(handler, function(x, y) { "use strict"
+ return {receiver: this, result: x + y, strict: true}
+ }),
+ ]
+ var creates = [
+ function(trap) { return trap },
+ function(trap) { return CreateFrozen({}, callTrap) },
+ function(trap) { return Proxy.createFunction(handler, callTrap) },
+ function(trap) {
+ return Proxy.createFunction(handler, CreateFrozen({}, callTrap))
+ },
+ function(trap) {
+ return Proxy.createFunction(handler, Proxy.createFunction(handler, callTrap))
+ },
+ ]
+ var binds = [
+ function(f, o, x, y) { return f },
+ function(f, o, x, y) { return bind.call(f, o) },
+ function(f, o, x, y) { return bind.call(f, o, x) },
+ function(f, o, x, y) { return bind.call(f, o, x, y) },
+ function(f, o, x, y) { return bind.call(f, o, x, y, 5) },
+ function(f, o, x, y) { return bind.call(bind.call(f, o), {}, x, y) },
+ function(f, o, x, y) { return bind.call(bind.call(f, o, x), {}, y) },
+ function(f, o, x, y) { return bind.call(bind.call(f, o, x, y), {}, 5) },
+ ]
+ var calls = [
+ function(f, x, y) { return f(x, y) },
+ function(f, x, y) { var g = f; return g(x, y) },
+ function(f, x, y) { with ({}) return f(x, y) },
+ function(f, x, y) { var g = f; with ({}) return g(x, y) },
+ function(f, x, y, o) { with (o) return f(x, y) },
+ function(f, x, y, o) { return f.call(o, x, y) },
+ function(f, x, y, o) { return f.apply(o, [x, y]) },
+ function(f, x, y, o) { return Function.prototype.call.call(f, o, x, y) },
+ function(f, x, y, o) { return Function.prototype.apply.call(f, o, [x, y]) },
+ function(f, x, y, o) { return %_Call(f, o, x, y) },
+ function(f, x, y, o) { return %Call(f, o, x, y) },
+ function(f, x, y, o) { return %Apply(f, o, [null, x, y, null], 1, 2) },
+ function(f, x, y, o) { return %Apply(f, o, arguments, 2, 2) },
+ function(f, x, y, o) { if (typeof o == "object") return o.f(x, y) },
+ function(f, x, y, o) { if (typeof o == "object") return o["f"](x, y) },
+ function(f, x, y, o) { if (typeof o == "object") return (1, o).f(x, y) },
+ function(f, x, y, o) { if (typeof o == "object") return (1, o)["f"](x, y) },
+ ]
+ var receivers = [o, global_object, undefined, null, 2, "bla", true]
+ var expectedSloppies = [o, global_object, global_object, global_object]
+
+ for (var t = 0; t < traps.length; ++t) {
+ for (var i = 0; i < creates.length; ++i) {
+ for (var j = 0; j < binds.length; ++j) {
+ for (var k = 0; k < calls.length; ++k) {
+ for (var m = 0; m < receivers.length; ++m) {
+ for (var n = 0; n < receivers.length; ++n) {
+ var bound = receivers[m]
+ var receiver = receivers[n]
+ var func = binds[j](creates[i](traps[t]), bound, 31, 11)
+ var expected = j > 0 ? bound : receiver
+ var expectedSloppy = expectedSloppies[j > 0 ? m : n]
+ o.f = func
+ global_object.f = func
+ var x = calls[k](func, 11, 31, receiver)
+ if (x !== undefined) {
+ assertEquals(42, x.result)
+ if (calls[k].length < 4)
+ assertSame(x.strict ? undefined : global_object, x.receiver)
+ else if (x.strict)
+ assertSame(expected, x.receiver)
+ else if (expectedSloppy === undefined)
+ assertSame(expected, x.receiver.valueOf())
+ else
+ assertSame(expectedSloppy, x.receiver)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+TestCalls()
+*/
+
+var realms = [Realm.create(), Realm.create()];
+Realm.shared = {};
+
+Realm.eval(realms[0], "function f(_, that) { return that; };");
+Realm.eval(realms[0], "Realm.shared.f = f;");
+Realm.eval(realms[0], "Realm.shared.fg = this;");
+Realm.eval(realms[1], "function g(_, that) { return that; };");
+Realm.eval(realms[1], "Realm.shared.g = g;");
+Realm.eval(realms[1], "Realm.shared.gg = this;");
+
+var fp = new Proxy(()=>{}, {apply: Realm.shared.f});
+var gp = new Proxy(()=>{}, {apply: Realm.shared.g});
+
+for (var i = 0; i < 10; i++) {
+ assertEquals(undefined, fp());
+ assertEquals(undefined, gp());
+
+ with (this) {
+ assertEquals(this, fp());
+ assertEquals(this, gp());
+ }
+
+ with ({}) {
+ assertEquals(undefined, fp());
+ assertEquals(undefined, gp());
+ }
+}
diff --git a/test/mjsunit/es6/proxies-get-own-property-descriptor.js b/test/mjsunit/es6/proxies-get-own-property-descriptor.js
new file mode 100644
index 0000000..441ff16
--- /dev/null
+++ b/test/mjsunit/es6/proxies-get-own-property-descriptor.js
@@ -0,0 +1,127 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var target = {};
+var configurable_desc = {
+ value: 123,
+ configurable: true,
+ writable: true,
+ enumerable: false,
+};
+Object.defineProperty(target, "configurable", configurable_desc);
+var nonconfigurable_desc = {
+ value: 234,
+ configurable: false,
+ writable: false,
+ enumerable: true
+}
+Object.defineProperty(target, "nonconfigurable", nonconfigurable_desc);
+
+var proxied_desc = {
+ value: 345,
+ configurable: true
+};
+
+var handler = {
+ "getOwnPropertyDescriptor": function(target, name) {
+ if (name === "proxied") {
+ return proxied_desc;
+ }
+ if (name === "return_null") {
+ return null;
+ }
+ return Object.getOwnPropertyDescriptor(target, name);
+ }
+};
+
+var proxy = new Proxy(target, handler);
+var proxy_without_handler = new Proxy(target, {});
+
+// Checking basic functionality:
+
+assertEquals(configurable_desc,
+ Object.getOwnPropertyDescriptor(proxy, "configurable"));
+assertEquals(nonconfigurable_desc,
+ Object.getOwnPropertyDescriptor(proxy, "nonconfigurable"));
+assertEquals({ value: proxied_desc.value,
+ configurable: proxied_desc.configurable,
+ enumerable: false,
+ writable: false },
+ Object.getOwnPropertyDescriptor(proxy, "proxied"));
+assertEquals(configurable_desc,
+ Object.getOwnPropertyDescriptor(proxy_without_handler,
+ "configurable"));
+assertEquals(nonconfigurable_desc,
+ Object.getOwnPropertyDescriptor(proxy_without_handler,
+ "nonconfigurable"));
+
+assertThrows('Object.getOwnPropertyDescriptor(proxy, "return_null")');
+
+handler.getOwnPropertyDescriptor = undefined;
+assertEquals(configurable_desc,
+ Object.getOwnPropertyDescriptor(proxy, "configurable"));
+
+// Checking invariants mentioned explicitly by the ES spec:
+
+// (Inv-1) "A property cannot be reported as non-existent, if it exists as a
+// non-configurable own property of the target object."
+handler.getOwnPropertyDescriptor = function(target, name) { return undefined; };
+assertThrows('Object.getOwnPropertyDescriptor(proxy, "nonconfigurable")');
+assertEquals(undefined, Object.getOwnPropertyDescriptor(proxy, "configurable"));
+
+// (Inv-2) "A property cannot be reported as non-configurable, if it does not
+// exist as an own property of the target object or if it exists as a
+// configurable own property of the target object."
+handler.getOwnPropertyDescriptor = function(target, name) {
+ return {value: 234, configurable: false, enumerable: true};
+};
+assertThrows('Object.getOwnPropertyDescriptor(proxy, "nonexistent")');
+assertThrows('Object.getOwnPropertyDescriptor(proxy, "configurable")');
+assertEquals(
+ false,
+ Object.getOwnPropertyDescriptor(proxy, "nonconfigurable").configurable);
+
+// (Inv-3) "A property cannot be reported as non-existent, if it exists as an
+// own property of the target object and the target object is not extensible."
+Object.seal(target);
+handler.getOwnPropertyDescriptor = function(target, name) { return undefined; };
+assertThrows('Object.getOwnPropertyDescriptor(proxy, "configurable")');
+assertThrows('Object.getOwnPropertyDescriptor(proxy, "nonconfigurable")');
+assertEquals(undefined, Object.getOwnPropertyDescriptor(proxy, "nonexistent"));
+
+// (Inv-4) "A property cannot be reported as existent, if it does not exist as
+// an own property of the target object and the target object is not
+// extensible."
+var existent_desc = {value: "yes"};
+handler.getOwnPropertyDescriptor = function() { return existent_desc; };
+assertThrows('Object.getOwnPropertyDescriptor(proxy, "nonexistent")');
+assertEquals(
+ {value: "yes", writable: false, enumerable: false, configurable: false},
+ Object.getOwnPropertyDescriptor(proxy, "configurable"));
+
+// Checking individual bailout points in the implementation:
+
+// Step 6: Trap is not callable.
+handler.getOwnPropertyDescriptor = {};
+assertThrows('Object.getOwnPropertyDescriptor(proxy, "configurable")');
+
+// Step 8: Trap throws.
+handler.getOwnPropertyDescriptor = function() { throw "ball"; };
+assertThrows('Object.getOwnPropertyDescriptor(proxy, "configurable")');
+
+// Step 9: Trap result is neither undefined nor an object.
+handler.getOwnPropertyDescriptor = function() { return 1; }
+assertThrows('Object.getOwnPropertyDescriptor(proxy, "configurable")');
+
+// Step 11b: See (Inv-1) above.
+// Step 11e: See (Inv-3) above.
+
+// Step 16: Incompatible PropertyDescriptor; a non-configurable property
+// cannot be reported as configurable. (Inv-4) above checks more cases.
+handler.getOwnPropertyDescriptor = function(target, name) {
+ return {value: 456, configurable: true, writable: true}
+};
+assertThrows('Object.getOwnPropertyDescriptor(proxy, "nonconfigurable")');
+
+// Step 17: See (Inv-2) above.
diff --git a/test/mjsunit/es6/proxies-get-prototype-of.js b/test/mjsunit/es6/proxies-get-prototype-of.js
new file mode 100644
index 0000000..a628f3f
--- /dev/null
+++ b/test/mjsunit/es6/proxies-get-prototype-of.js
@@ -0,0 +1,91 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var target = { target: 1 };
+target.__proto__ = {};
+var handler = { handler: 1 };
+var proxy = new Proxy(target, handler);
+
+assertSame(Object.getPrototypeOf(proxy), target.__proto__ );
+
+target.__proto__ = [];
+assertSame(Object.getPrototypeOf(proxy), target.__proto__);
+
+handler.getPrototypeOf = function() {
+ return 1;
+}
+assertThrows(function() { Object.getPrototypeOf(proxy) }, TypeError);
+
+var target_prototype = {a:1, b:2};
+handler.getPrototypeOf = function() {
+ return target_prototype ;
+}
+assertSame(Object.getPrototypeOf(proxy), target_prototype);
+
+// Test with proxy target:
+var proxy2 = new Proxy(proxy, {'handler':1});
+assertSame(Object.getPrototypeOf(proxy2), target_prototype);
+
+// Test with Proxy handler:
+var proxy3_prototype = {'proto3':true};
+var handler_proxy = new Proxy({
+ getPrototypeOf: function() { return proxy3_prototype }
+}, {});
+var proxy3 = new Proxy(target, handler_proxy);
+assertSame(Object.getPrototypeOf(proxy3), proxy3_prototype);
+
+
+// Some tests with Object.prototype.isPrototypeOf
+
+(function () {
+ var object = {};
+ var handler = {};
+ var proto = new Proxy({}, handler);
+ object.__proto__ = proto;
+
+ assertTrue(proto.isPrototypeOf(object));
+ assertTrue(Object.prototype.isPrototypeOf.call(proto, object));
+
+ handler.getPrototypeOf = function () { return Object.prototype };
+ assertTrue(proto.isPrototypeOf(object));
+ assertTrue(Object.prototype.isPrototypeOf.call(proto, object));
+ assertTrue(Object.prototype.isPrototypeOf(object));
+ assertFalse(Object.prototype.isPrototypeOf.call(Array.prototype, object));
+ assertFalse(Array.prototype.isPrototypeOf(object));
+
+ handler.getPrototypeOf = function () { return object };
+ assertTrue(Object.prototype.isPrototypeOf.call(proto, object));
+ assertTrue(proto.isPrototypeOf(object));
+ assertTrue(Object.prototype.isPrototypeOf.call(object, object));
+ assertTrue(object.isPrototypeOf(object));
+
+ handler.getPrototypeOf = function () { throw "foo" };
+ assertTrue(proto.isPrototypeOf(object));
+ assertTrue(Object.prototype.isPrototypeOf.call(proto, object));
+ assertThrows(()=> Object.prototype.isPrototypeOf(object));
+ assertThrows(()=> Object.prototype.isPrototypeOf.call(Array.prototype, object));
+ assertThrows(()=> Array.prototype.isPrototypeOf(object));
+})();
+
+(function () {
+ var handler = {};
+ var object = new Proxy({}, handler);
+ var proto = {};
+
+ assertFalse(Object.prototype.isPrototypeOf.call(object, object));
+ assertFalse(Object.prototype.isPrototypeOf.call(proto, object));
+ assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, object));
+
+ handler.getPrototypeOf = function () { return proto };
+ assertTrue(Object.prototype.isPrototypeOf.call(proto, object));
+ assertFalse(Object.prototype.isPrototypeOf.call({}, object));
+ assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, object));
+
+ handler.getPrototypeOf = function () { return object };
+ assertTrue(Object.prototype.isPrototypeOf.call(object, object));
+
+ handler.getPrototypeOf = function () { throw "foo" };
+ assertThrows(()=> Object.prototype.isPrototypeOf.call(object, object));
+ assertThrows(()=> Object.prototype.isPrototypeOf(object));
+})();
diff --git a/test/mjsunit/es6/proxies-get.js b/test/mjsunit/es6/proxies-get.js
new file mode 100644
index 0000000..b1b92db
--- /dev/null
+++ b/test/mjsunit/es6/proxies-get.js
@@ -0,0 +1,127 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+(function testBasicFunctionality() {
+ var target = {
+ target_one: 1,
+ property: "value"
+ };
+
+ var handler = {handler:1};
+
+ var proxy = new Proxy(target, handler);
+ assertEquals("value", proxy.property);
+ assertEquals(undefined, proxy.nothing);
+ assertEquals(undefined, proxy.handler);
+
+ handler.get = function() { return "value 2" };
+ assertEquals("value 2", proxy.property);
+ assertEquals("value 2", proxy.nothing);
+ assertEquals("value 2", proxy.handler);
+
+ var handler2 = new Proxy({get: function() { return "value 3" }},{});
+ var proxy2 = new Proxy(target, handler2);
+ assertEquals("value 3", proxy2.property);
+ assertEquals("value 3", proxy2.nothing);
+ assertEquals("value 3", proxy2.handler);
+})();
+
+(function testThrowOnGettingTrap() {
+ var handler = new Proxy({}, {get: function(){ throw Error() }});
+ var proxy = new Proxy({}, handler);
+ assertThrows("proxy.property", Error);
+})();
+
+(function testFallback() {
+ var target = {property:"value"};
+ var proxy = new Proxy(target, {});
+ assertEquals("value", proxy.property);
+ assertEquals(undefined, proxy.property2);
+})();
+
+(function testFallbackUndefinedTrap() {
+ var handler = new Proxy({}, {get: function(){ return undefined }});
+ var target = {property:"value"};
+ var proxy = new Proxy(target, handler);
+ assertEquals("value", proxy.property);
+ assertEquals(undefined, proxy.property2);
+})();
+
+(function testFailingInvariant() {
+ var target = {};
+ var handler = { get: function(r, p){ if (p != "key4") return "value" }}
+ var proxy = new Proxy(target, handler);
+ assertEquals("value", proxy.property);
+ assertEquals("value", proxy.key);
+ assertEquals("value", proxy.key2);
+ assertEquals("value", proxy.key3);
+
+ // Define a non-configurable, non-writeable property on the target for
+ // which the handler will return a different value.
+ Object.defineProperty(target, "key", {
+ configurable: false,
+ writable: false,
+ value: "different value"
+ });
+ assertEquals("value", proxy.property);
+ assertThrows(function(){ proxy.key }, TypeError);
+ assertEquals("value", proxy.key2);
+ assertEquals("value", proxy.key3);
+
+ // Define a non-configurable getter on the target for which the handler
+ // will return a value, according to the spec we do not throw.
+ Object.defineProperty(target, "key2", {
+ configurable: false,
+ get: function() { return "different value" }
+ });
+ assertEquals("value", proxy.property);
+ assertThrows(function(){ proxy.key }, TypeError);
+ assertEquals("value", proxy.key2);
+ assertEquals("value", proxy.key3);
+
+ // Define a non-configurable setter without a corresponding getter on the
+ // target for which the handler will return a value.
+ Object.defineProperty(target, "key3", {
+ configurable: false,
+ set: function() { }
+ });
+ assertEquals("value", proxy.property);
+ assertThrows(function(){ proxy.key }, TypeError);
+ assertEquals("value", proxy.key2);
+ assertThrows(function(){ proxy.key3 }, TypeError);
+
+ // Define a non-configurable setter without a corresponding getter on the
+ // target for which the handler will return undefined.
+ Object.defineProperty(target, "key4", {
+ configurable: false,
+ set: function() { }
+ });
+ assertSame(undefined, proxy.key4);
+})();
+
+(function testGetInternalIterators() {
+ var log = [];
+ var array = [1,2,3,4,5]
+ var origIt = array[Symbol.iterator]();
+ var it = new Proxy(origIt, {
+ get(t, name) {
+ log.push(`[[Get]](iterator, ${String(name)})`);
+ return Reflect.get(t, name);
+ },
+ set(t, name, val) {
+ log.push(`[[Set]](iterator, ${String(name)}, ${String(val)})`);
+ return Reflect.set(t, name, val);
+ }
+ });
+
+ assertThrows(function() {
+ for (var v of it) log.push(v);
+ }, TypeError);
+ assertEquals([
+ "[[Get]](iterator, Symbol(Symbol.iterator))",
+ "[[Get]](iterator, next)"
+ ], log);
+})();
diff --git a/test/mjsunit/es6/proxies-global-reference.js b/test/mjsunit/es6/proxies-global-reference.js
new file mode 100644
index 0000000..975d7f7
--- /dev/null
+++ b/test/mjsunit/es6/proxies-global-reference.js
@@ -0,0 +1,12 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var failing_proxy = new Proxy({}, new Proxy({}, {
+ get() { throw "No trap should fire" }}));
+
+Object.setPrototypeOf(Object.prototype, failing_proxy);
+assertThrows(()=>a, TypeError);
+
+Object.setPrototypeOf(this, failing_proxy);
+assertThrows(()=>a, TypeError);
diff --git a/test/mjsunit/es6/proxies-has-own-property.js b/test/mjsunit/es6/proxies-has-own-property.js
new file mode 100644
index 0000000..5b9ddbc
--- /dev/null
+++ b/test/mjsunit/es6/proxies-has-own-property.js
@@ -0,0 +1,37 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var handler = {};
+var target = {a:1};
+var proxy = new Proxy(target, handler);
+
+assertTrue(target.hasOwnProperty('a'));
+assertTrue(proxy.hasOwnProperty('a'));
+assertFalse(target.hasOwnProperty('b'));
+assertFalse(proxy.hasOwnProperty('b'));
+
+
+handler.has = function() { assertUnreachable() }
+handler.getOwnPropertyDescriptor = function () {}
+
+assertTrue(target.hasOwnProperty('a'));
+assertFalse(proxy.hasOwnProperty('a'));
+assertFalse(target.hasOwnProperty('b'));
+assertFalse(proxy.hasOwnProperty('b'));
+
+
+handler.getOwnPropertyDescriptor = function() { return {configurable: true} }
+
+assertTrue(target.hasOwnProperty('a'));
+assertTrue(proxy.hasOwnProperty('a'));
+assertFalse(target.hasOwnProperty('b'));
+assertTrue(proxy.hasOwnProperty('b'));
+
+
+handler.getOwnPropertyDescriptor = function() { throw Error(); }
+
+assertTrue(target.hasOwnProperty('a'));
+assertThrows(function(){ proxy.hasOwnProperty('a') }, Error);
+assertFalse(target.hasOwnProperty('b'));
+assertThrows(function(){ proxy.hasOwnProperty('b') }, Error);
diff --git a/test/mjsunit/es6/proxies-has.js b/test/mjsunit/es6/proxies-has.js
new file mode 100644
index 0000000..7294196
--- /dev/null
+++ b/test/mjsunit/es6/proxies-has.js
@@ -0,0 +1,61 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var target = {
+ "target_one": 1
+};
+target.__proto__ = {
+ "target_two": 2
+};
+var handler = {
+ has: function(target, name) {
+ return name == "present";
+ }
+}
+
+var proxy = new Proxy(target, handler);
+
+// Test simple cases.
+assertTrue("present" in proxy);
+assertFalse("nonpresent" in proxy);
+
+// Test interesting algorithm steps:
+
+// Step 7: Fall through to target if trap is undefined.
+handler.has = undefined;
+assertTrue("target_one" in proxy);
+assertTrue("target_two" in proxy);
+assertFalse("in_your_dreams" in proxy);
+
+// Step 8: Result is converted to boolean.
+var result = 1;
+handler.has = function(t, n) { return result; }
+assertTrue("foo" in proxy);
+result = {};
+assertTrue("foo" in proxy);
+result = undefined;
+assertFalse("foo" in proxy);
+result = "string";
+assertTrue("foo" in proxy);
+
+// Step 9b i. Trap result must confirm presence of non-configurable properties
+// of the target.
+Object.defineProperty(target, "nonconf", {value: 1, configurable: false});
+result = false;
+assertThrows("'nonconf' in proxy", TypeError);
+
+// Step 9b iii. Trap result must confirm presence of all own properties of
+// non-extensible targets.
+Object.preventExtensions(target);
+assertThrows("'nonconf' in proxy", TypeError);
+assertThrows("'target_one' in proxy", TypeError);
+assertFalse("target_two" in proxy);
+assertFalse("in_your_dreams" in proxy);
+
+// Regression test for crbug.com/570120 (stray JSObject::cast).
+(function TestHasPropertyFastPath() {
+ var proxy = new Proxy({}, {});
+ var object = Object.create(proxy);
+ object.hasOwnProperty(0);
+})();
diff --git a/test/mjsunit/es6/proxies-hash.js b/test/mjsunit/es6/proxies-hash.js
new file mode 100644
index 0000000..05433f0
--- /dev/null
+++ b/test/mjsunit/es6/proxies-hash.js
@@ -0,0 +1,121 @@
+// Copyright 2011 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.
+
+
+// Helper.
+
+function TestWithProxies(test, construct, handler) {
+ test(construct, handler, function(h) { return new Proxy({}, h) })
+ // TODO(cbruni): Adapt and enable once we have [[Call]] working.
+ // test(construct, handler, function(h) {
+ // return Proxy.createFunction(h, function() {})
+ // })
+}
+
+
+// Sets.
+
+function TestSet(construct, fix) {
+ TestWithProxies(TestSet2, construct, fix)
+}
+
+function TestSet2(construct, fix, create) {
+ var handler = {fix: function() { return {} }}
+ var p1 = create(handler)
+ var p2 = create(handler)
+ var p3 = create(handler)
+ fix(p3)
+
+ var s = new construct();
+ s.add(p1);
+ s.add(p2);
+ assertTrue(s.has(p1));
+ assertTrue(s.has(p2));
+ assertFalse(s.has(p3));
+
+ fix(p1)
+ fix(p2)
+ assertTrue(s.has(p1));
+ assertTrue(s.has(p2));
+ assertFalse(s.has(p3));
+
+ s.delete(p2);
+ assertTrue(s.has(p1));
+ assertFalse(s.has(p2));
+ assertFalse(s.has(p3));
+}
+
+TestSet(Set, Object.seal)
+TestSet(Set, Object.freeze)
+TestSet(Set, Object.preventExtensions)
+
+
+// Maps and weak maps.
+
+function TestMap(construct, fix) {
+ TestWithProxies(TestMap2, construct, fix)
+}
+
+function TestMap2(construct, fix, create) {
+ var handler = {fix: function() { return {} }}
+ var p1 = create(handler)
+ var p2 = create(handler)
+ var p3 = create(handler)
+ fix(p3)
+
+ var m = new construct();
+ m.set(p1, 123);
+ m.set(p2, 321);
+ assertTrue(m.has(p1));
+ assertTrue(m.has(p2));
+ assertFalse(m.has(p3));
+ assertSame(123, m.get(p1));
+ assertSame(321, m.get(p2));
+
+ fix(p1)
+ fix(p2)
+ assertTrue(m.has(p1));
+ assertTrue(m.has(p2));
+ assertFalse(m.has(p3));
+ assertSame(123, m.get(p1));
+ assertSame(321, m.get(p2));
+
+ m.delete(p2);
+ assertTrue(m.has(p1));
+ assertFalse(m.has(p2));
+ assertFalse(m.has(p3));
+ assertSame(123, m.get(p1));
+ assertSame(undefined, m.get(p2));
+}
+
+TestMap(Map, Object.seal)
+TestMap(Map, Object.freeze)
+TestMap(Map, Object.preventExtensions)
+
+TestMap(WeakMap, Object.seal)
+TestMap(WeakMap, Object.freeze)
+TestMap(WeakMap, Object.preventExtensions)
diff --git a/test/mjsunit/es6/proxies-integrity.js b/test/mjsunit/es6/proxies-integrity.js
new file mode 100644
index 0000000..4cdf770
--- /dev/null
+++ b/test/mjsunit/es6/proxies-integrity.js
@@ -0,0 +1,211 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+
+function toKey(x) {
+ if (typeof x === "symbol") return x;
+ return String(x);
+}
+
+
+const noconf = {configurable: false};
+const noconf_nowrite = {configurable: false, writable: false};
+
+
+var symbol = Symbol();
+
+
+var log = [];
+var logger = {};
+var handler = new Proxy({}, logger);
+
+logger.get = function(t, trap, r) {
+ return function() {
+ log.push([trap, ...arguments]);
+ return Reflect[trap](...arguments);
+ }
+};
+
+
+(function Seal() {
+ var target = [];
+ var proxy = new Proxy(target, handler);
+ log.length = 0;
+
+ target.wurst = 42;
+ target[0] = true;
+ Object.defineProperty(target, symbol, {get: undefined});
+
+ Object.seal(proxy);
+ assertEquals(6, log.length)
+ for (var i in log) assertSame(target, log[i][1]);
+
+ assertArrayEquals(
+ ["preventExtensions", target], log[0]);
+ assertArrayEquals(
+ ["ownKeys", target], log[1]);
+ assertArrayEquals(
+ ["defineProperty", target, toKey(0), noconf], log[2]);
+ assertArrayEquals(
+ ["defineProperty", target, toKey("length"), noconf], log[3]);
+ assertArrayEquals(
+ ["defineProperty", target, toKey("wurst"), noconf], log[4]);
+ assertArrayEquals(
+ ["defineProperty", target, toKey(symbol), noconf], log[5]);
+})();
+
+
+(function Freeze() {
+ var target = [];
+ var proxy = new Proxy(target, handler);
+ log.length = 0;
+
+ target.wurst = 42;
+ target[0] = true;
+ Object.defineProperty(target, symbol, {get: undefined});
+
+ Object.freeze(proxy);
+ assertEquals(10, log.length)
+ for (var i in log) assertSame(target, log[i][1]);
+
+ assertArrayEquals(
+ ["preventExtensions", target], log[0]);
+ assertArrayEquals(
+ ["ownKeys", target], log[1]);
+ assertArrayEquals(
+ ["getOwnPropertyDescriptor", target, toKey(0)], log[2]);
+ assertArrayEquals(
+ ["defineProperty", target, toKey(0), noconf_nowrite], log[3]);
+ assertArrayEquals(
+ ["getOwnPropertyDescriptor", target, toKey("length")], log[4]);
+ assertArrayEquals(
+ ["defineProperty", target, toKey("length"), noconf_nowrite], log[5]);
+ assertArrayEquals(
+ ["getOwnPropertyDescriptor", target, toKey("wurst")], log[6]);
+ assertArrayEquals(
+ ["defineProperty", target, toKey("wurst"), noconf_nowrite], log[7]);
+ assertArrayEquals(
+ ["getOwnPropertyDescriptor", target, toKey(symbol)], log[8]);
+ assertArrayEquals(
+ ["defineProperty", target, toKey(symbol), noconf], log[9]);
+})();
+
+
+(function IsSealed() {
+ var target = [];
+ var proxy = new Proxy(target, handler);
+
+ target.wurst = 42;
+ target[0] = true;
+ Object.defineProperty(target, symbol, {get: undefined});
+
+ // Extensible.
+
+ log.length = 0;
+
+ Object.isSealed(proxy);
+ assertEquals(1, log.length)
+ for (var i in log) assertSame(target, log[i][1]);
+
+ assertArrayEquals(
+ ["isExtensible", target], log[0]);
+
+ // Not extensible but not sealed.
+
+ log.length = 0;
+ Object.preventExtensions(target);
+
+ Object.isSealed(proxy);
+ assertEquals(3, log.length)
+ for (var i in log) assertSame(target, log[i][1]);
+
+ assertArrayEquals(
+ ["isExtensible", target], log[0]);
+ assertArrayEquals(
+ ["ownKeys", target], log[1]);
+ assertArrayEquals(
+ ["getOwnPropertyDescriptor", target, toKey(0)], log[2]);
+
+ // Sealed.
+
+ log.length = 0;
+ Object.seal(target);
+
+ Object.isSealed(proxy);
+ assertEquals(6, log.length)
+ for (var i in log) assertSame(target, log[i][1]);
+
+ assertArrayEquals(
+ ["isExtensible", target], log[0]);
+ assertArrayEquals(
+ ["ownKeys", target], log[1]);
+ assertArrayEquals(
+ ["getOwnPropertyDescriptor", target, toKey(0)], log[2]);
+ assertArrayEquals(
+ ["getOwnPropertyDescriptor", target, toKey("length")], log[3]);
+ assertArrayEquals(
+ ["getOwnPropertyDescriptor", target, toKey("wurst")], log[4]);
+ assertArrayEquals(
+ ["getOwnPropertyDescriptor", target, toKey(symbol)], log[5]);
+})();
+
+
+(function IsFrozen() {
+ var target = [];
+ var proxy = new Proxy(target, handler);
+
+ target.wurst = 42;
+ target[0] = true;
+ Object.defineProperty(target, symbol, {get: undefined});
+
+ // Extensible.
+
+ log.length = 0;
+
+ Object.isFrozen(proxy);
+ assertEquals(1, log.length)
+ for (var i in log) assertSame(target, log[i][1]);
+
+ assertArrayEquals(
+ ["isExtensible", target], log[0]);
+
+ // Not extensible but not frozen.
+
+ log.length = 0;
+ Object.preventExtensions(target);
+
+ Object.isFrozen(proxy);
+ assertEquals(3, log.length)
+ for (var i in log) assertSame(target, log[i][1]);
+
+ assertArrayEquals(
+ ["isExtensible", target], log[0]);
+ assertArrayEquals(
+ ["ownKeys", target], log[1]);
+ assertArrayEquals(
+ ["getOwnPropertyDescriptor", target, toKey(0)], log[2]);
+
+ // Frozen.
+
+ log.length = 0;
+ Object.freeze(target);
+
+ Object.isFrozen(proxy);
+ assertEquals(6, log.length)
+ for (var i in log) assertSame(target, log[i][1]);
+
+ assertArrayEquals(
+ ["isExtensible", target], log[0]);
+ assertArrayEquals(
+ ["ownKeys", target], log[1]);
+ assertArrayEquals(
+ ["getOwnPropertyDescriptor", target, toKey(0)], log[2]);
+ assertArrayEquals(
+ ["getOwnPropertyDescriptor", target, toKey("length")], log[3]);
+ assertArrayEquals(
+ ["getOwnPropertyDescriptor", target, toKey("wurst")], log[4]);
+ assertArrayEquals(
+ ["getOwnPropertyDescriptor", target, toKey(symbol)], log[5]);
+})();
diff --git a/test/mjsunit/es6/proxies-is-extensible.js b/test/mjsunit/es6/proxies-is-extensible.js
new file mode 100644
index 0000000..9ab2c05
--- /dev/null
+++ b/test/mjsunit/es6/proxies-is-extensible.js
@@ -0,0 +1,72 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+(function () {
+ // No trap.
+
+ var target = {};
+ var handler = {};
+ var proxy = new Proxy(target, handler);
+
+ assertTrue(Reflect.isExtensible(target));
+ assertTrue(Reflect.isExtensible(proxy));
+ assertTrue(Reflect.preventExtensions(proxy));
+ assertFalse(Reflect.isExtensible(target));
+ assertFalse(Reflect.isExtensible(proxy));
+})();
+
+
+(function () {
+ // "Undefined" trap.
+
+ var target = {};
+ var handler = { isExtensible: null };
+ var proxy = new Proxy(target, handler);
+
+ assertTrue(Reflect.isExtensible(target));
+ assertTrue(Reflect.isExtensible(proxy));
+ assertTrue(Reflect.preventExtensions(proxy));
+ assertFalse(Reflect.isExtensible(target));
+ assertFalse(Reflect.isExtensible(proxy));
+})();
+
+
+(function () {
+ // Invalid trap.
+
+ var target = {};
+ var handler = { isExtensible: true };
+ var proxy = new Proxy(target, handler);
+
+ assertThrows(() => {Reflect.isExtensible(proxy)}, TypeError);
+})();
+
+
+(function () {
+ var target = {};
+ var handler = { isExtensible() {return "bla"} };
+ var proxy = new Proxy(target, handler);
+
+ // Trap returns trueish and target is extensible.
+ assertTrue(Reflect.isExtensible(proxy));
+
+ // Trap returns trueish but target is not extensible.
+ Reflect.preventExtensions(target);
+ assertThrows(() => {Reflect.isExtensible(proxy)}, TypeError);
+})();
+
+
+(function () {
+ var target = {};
+ var handler = { isExtensible() {return 0} };
+ var proxy = new Proxy(target, handler);
+
+ // Trap returns falsish but target is extensible.
+ assertThrows(() => {Reflect.isExtensible(proxy)}, TypeError);
+
+ // Trap returns falsish and target is not extensible.
+ Reflect.preventExtensions(target);
+ assertFalse(Reflect.isExtensible(proxy));
+})();
diff --git a/test/mjsunit/es6/proxies-json.js b/test/mjsunit/es6/proxies-json.js
new file mode 100644
index 0000000..d48d539
--- /dev/null
+++ b/test/mjsunit/es6/proxies-json.js
@@ -0,0 +1,505 @@
+// 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.
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// JSON.stringify
+
+
+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, a function proxy, and objects that contain them.
+
+var handler1 = {
+ get: function(target, name) {
+ return name.toUpperCase();
+ },
+ ownKeys: function() {
+ return ['a', 'b', 'c'];
+ },
+ getOwnPropertyDescriptor: function() {
+ return { enumerable: true, configurable: true };
+ }
+}
+
+var proxy1 = new Proxy({}, handler1);
+testStringify('{"a":"A","b":"B","c":"C"}', proxy1);
+
+var proxy_fun = new Proxy(() => {}, handler1);
+assertTrue(typeof(proxy_fun) === 'function');
+testStringify(undefined, proxy_fun);
+testStringify('[1,null]', [1, proxy_fun]);
+
+handler1.apply = function() { return 666; };
+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();
+ },
+ ownKeys: function() {
+ return ['a', 'b', 'c'];
+ },
+ getOwnPropertyDescriptor: function() {
+ return { enumerable: true, configurable: true };
+ }
+}
+
+var proxy2 = new Proxy({}, 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 receiver argument.
+
+var handler3 = {
+ get: function(target, name, receiver) {
+ if (name == 'valueOf' || name === Symbol.toPrimitive) {
+ return function() { return "proxy" };
+ };
+ if (typeof name !== 'symbol') return name + "(" + receiver + ")";
+ },
+ ownKeys: function() {
+ return ['a', 'b', 'c'];
+ },
+ getOwnPropertyDescriptor: function() {
+ return { enumerable: true, configurable: true };
+ }
+}
+
+var proxy3 = new Proxy({}, 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;
+ },
+ has: function() {
+ return true;
+ },
+ getOwnPropertyDescriptor: function(target, name) {
+ return { enumerable: false };
+ }
+}
+
+var proxy4 = new Proxy({}, 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; };
+ },
+ ownKeys: function(target) {
+ return ['toJSON', 'z'];
+ },
+ has: function() {
+ return true;
+ },
+ getOwnPropertyDescriptor: function(target, name) {
+ return { enumerable: true };
+ }
+}
+
+var proxy5 = new Proxy({}, 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; };
+ },
+ ownKeys: function(target) {
+ return ['toJSON'];
+ },
+ has: function() {
+ return true;
+ },
+ getOwnPropertyDescriptor: function(target, name) {
+ return { enumerable: true };
+ }
+}
+
+var proxy6 = new Proxy({}, 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();
+ },
+ ownKeys: function() {
+ return ['a', 'b', 'c'];
+ },
+ getOwnPropertyDescriptor: function() {
+ return { enumerable: true, configurable: true };
+ }
+}
+
+var proxy7 = new Proxy({}, 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));
+
+
+// (Proxy handler to log trap calls)
+
+var log = [];
+var logger = {};
+var handler = new Proxy({}, logger);
+
+logger.get = function(t, trap, r) {
+ return function() {
+ log.push([trap, ...arguments]);
+ return Reflect[trap](...arguments);
+ }
+};
+
+
+// Object is a callable proxy
+
+log.length = 0;
+var target = () => 42;
+var proxy = new Proxy(target, handler);
+assertTrue(typeof proxy === 'function');
+
+assertEquals(undefined, JSON.stringify(proxy));
+assertEquals(1, log.length)
+for (var i in log) assertSame(target, log[i][1]);
+
+assertEquals(["get", target, "toJSON", proxy], log[0]);
+
+
+// Object is a non-callable non-arraylike proxy
+
+log.length = 0;
+var target = {foo: 42}
+var proxy = new Proxy(target, handler);
+assertFalse(Array.isArray(proxy));
+
+assertEquals('{"foo":42}', JSON.stringify(proxy));
+assertEquals(4, log.length)
+for (var i in log) assertSame(target, log[i][1]);
+
+assertEquals(
+ ["get", target, "toJSON", proxy], log[0]);
+assertEquals(
+ ["ownKeys", target], log[1]); // EnumerableOwnNames
+assertEquals(
+ ["getOwnPropertyDescriptor", target, "foo"], log[2]); // EnumerableOwnNames
+assertEquals(
+ ["get", target, "foo", proxy], log[3]);
+
+
+// Object is an arraylike proxy
+
+log.length = 0;
+var target = [42];
+var proxy = new Proxy(target, handler);
+assertTrue(Array.isArray(proxy));
+
+assertEquals('[42]', JSON.stringify(proxy));
+assertEquals(3, log.length)
+for (var i in log) assertSame(target, log[i][1]);
+
+assertEquals(["get", target, "toJSON", proxy], log[0]);
+assertEquals(["get", target, "length", proxy], log[1]);
+assertEquals(["get", target, "0", proxy], log[2]);
+
+
+// Replacer is a callable proxy
+
+log.length = 0;
+var object = {0: "foo", 1: 666};
+var target = (key, val) => key == "1" ? val + 42 : val;
+var proxy = new Proxy(target, handler);
+assertTrue(typeof proxy === 'function');
+
+assertEquals('{"0":"foo","1":708}', JSON.stringify(object, proxy));
+assertEquals(3, log.length)
+for (var i in log) assertSame(target, log[i][1]);
+
+assertEquals(4, log[0].length)
+assertEquals("apply", log[0][0]);
+assertEquals("", log[0][3][0]);
+assertEquals({0: "foo", 1: 666}, log[0][3][1]);
+assertEquals(4, log[1].length)
+assertEquals("apply", log[1][0]);
+assertEquals(["0", "foo"], log[1][3]);
+assertEquals(4, log[2].length)
+assertEquals("apply", log[2][0]);
+assertEquals(["1", 666], log[2][3]);
+
+
+// Replacer is an arraylike proxy
+
+log.length = 0;
+var object = {0: "foo", 1: 666};
+var target = [0];
+var proxy = new Proxy(target, handler);
+assertTrue(Array.isArray(proxy));
+
+assertEquals('{"0":"foo"}', JSON.stringify(object, proxy));
+assertEquals(2, log.length)
+for (var i in log) assertSame(target, log[i][1]);
+
+assertEquals(["get", target, "length", proxy], log[0]);
+assertEquals(["get", target, "0", proxy], log[1]);
+
+
+// Replacer is an arraylike proxy and object is an array
+
+log.length = 0;
+var object = ["foo", 42];
+var target = [0];
+var proxy = new Proxy(target, handler);
+assertTrue(Array.isArray(proxy));
+
+assertEquals('["foo",42]', JSON.stringify(object, proxy));
+assertEquals(2, log.length);
+for (var i in log) assertSame(target, log[i][1]);
+
+assertEquals(["get", target, "length", proxy], log[0]);
+assertEquals(["get", target, "0", proxy], log[1]);
+
+
+// Replacer is an arraylike proxy with a non-trivial length
+
+var getTrap = function(t, key) {
+ if (key === "length") return {[Symbol.toPrimitive]() {return 42}};
+ if (key === "41") return "foo";
+ if (key === "42") return "bar";
+};
+var target = [];
+var proxy = new Proxy(target, {get: getTrap});
+assertTrue(Array.isArray(proxy));
+var object = {foo: true, bar: 666};
+assertEquals('{"foo":true}', JSON.stringify(object, proxy));
+
+
+// Replacer is an arraylike proxy with a bogus length
+
+var getTrap = function(t, key) {
+ if (key === "length") return Symbol();
+ if (key === "41") return "foo";
+ if (key === "42") return "bar";
+};
+var target = [];
+var proxy = new Proxy(target, {get: getTrap});
+assertTrue(Array.isArray(proxy));
+var object = {foo: true, bar: 666};
+assertThrows(() => JSON.stringify(object, proxy), TypeError);
+
+
+// Replacer returns a non-callable non-arraylike proxy
+
+log.length = 0;
+var object = ["foo", 42];
+var target = {baz: 5};
+var proxy = new Proxy(target, handler);
+var replacer = (key, val) => key === "1" ? proxy : val;
+
+assertEquals('["foo",{"baz":5}]', JSON.stringify(object, replacer));
+assertEquals(3, log.length);
+for (var i in log) assertSame(target, log[i][1]);
+
+assertEquals(["ownKeys", target], log[0]);
+assertEquals(["getOwnPropertyDescriptor", target, "baz"], log[1]);
+
+
+// Replacer returns an arraylike proxy
+
+log.length = 0;
+var object = ["foo", 42];
+var target = ["bar"];
+var proxy = new Proxy(target, handler);
+var replacer = (key, val) => key === "1" ? proxy : val;
+
+assertEquals('["foo",["bar"]]', JSON.stringify(object, replacer));
+assertEquals(2, log.length);
+for (var i in log) assertSame(target, log[i][1]);
+
+assertEquals(["get", target, "length", proxy], log[0]);
+assertEquals(["get", target, "0", proxy], log[1]);
+
+
+// Replacer returns an arraylike proxy with a non-trivial length
+
+var getTrap = function(t, key) {
+ if (key === "length") return {[Symbol.toPrimitive]() {return 3}};
+ if (key === "2") return "baz";
+ if (key === "3") return "bar";
+};
+var target = [];
+var proxy = new Proxy(target, {get: getTrap});
+var replacer = (key, val) => key === "goo" ? proxy : val;
+var object = {foo: true, goo: false};
+assertEquals('{"foo":true,"goo":[null,null,"baz"]}',
+ JSON.stringify(object, replacer));
+
+
+// Replacer returns an arraylike proxy with a bogus length
+
+var getTrap = function(t, key) {
+ if (key === "length") return Symbol();
+ if (key === "2") return "baz";
+ if (key === "3") return "bar";
+};
+var target = [];
+var proxy = new Proxy(target, {get: getTrap});
+var replacer = (key, val) => key === "goo" ? proxy : val;
+var object = {foo: true, goo: false};
+assertThrows(() => JSON.stringify(object, replacer), TypeError);
+
+
+// Replacer returns a callable proxy
+
+log.length = 0;
+var target = () => 666;
+var proxy = new Proxy(target, handler);
+var replacer = (key, val) => key === "1" ? proxy : val;
+
+assertEquals('["foo",null]', JSON.stringify(["foo", 42], replacer));
+assertEquals(0, log.length);
+
+assertEquals('{"0":"foo"}', JSON.stringify({0: "foo", 1: 42}, replacer));
+assertEquals(0, log.length);
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// JSON.parse
+
+
+// Reviver is a callable proxy
+
+log.length = 0;
+var target = () => 42;
+var proxy = new Proxy(target, handler);
+assertTrue(typeof proxy === "function");
+
+assertEquals(42, JSON.parse("[true, false]", proxy));
+assertEquals(3, log.length);
+for (var i in log) assertSame(target, log[i][1]);
+
+assertEquals(4, log[0].length);
+assertEquals("apply", log[0][0]);
+assertEquals(["0", true], log[0][3]);
+assertEquals(4, log[1].length);
+assertEquals("apply", log[1][0]);
+assertEquals(["1", false], log[1][3]);
+assertEquals(4, log[2].length);
+assertEquals("apply", log[2][0]);
+assertEquals(["", [42, 42]], log[2][3]);
+
+
+// Reviver plants a non-arraylike proxy into a yet-to-be-visited property
+
+log.length = 0;
+var target = {baz: 42};
+var proxy = new Proxy(target, handler);
+var reviver = function(p, v) {
+ if (p === "baz") return 5;
+ if (p === "foo") this.bar = proxy;
+ return v;
+}
+
+assertEquals({foo: 0, bar: proxy}, JSON.parse('{"foo":0,"bar":1}', reviver));
+assertEquals(4, log.length);
+for (var i in log) assertSame(target, log[i][1]);
+
+assertEquals(["ownKeys", target], log[0]);
+assertEquals(["getOwnPropertyDescriptor", target, "baz"], log[1]);
+assertEquals(["get", target, "baz", proxy], log[2]);
+assertEquals(["defineProperty", target, "baz",
+ {value: 5, configurable: true, writable: true, enumerable: true}], log[3]);
+
+
+// Reviver plants an arraylike proxy into a yet-to-be-visited property
+
+log.length = 0;
+var target = [42];
+var proxy = new Proxy(target, handler);
+assertTrue(Array.isArray(proxy));
+var reviver = function(p, v) {
+ if (p === "0") return undefined;
+ if (p === "foo") this.bar = proxy;
+ return v;
+}
+
+var result = JSON.parse('{"foo":0,"bar":1}', reviver);
+assertEquals({foo: 0, bar: proxy}, result);
+assertSame(result.bar, proxy);
+assertEquals(3, log.length);
+for (var i in log) assertSame(target, log[i][1]);
+
+assertEquals(["get", target, "length", proxy], log[0]);
+assertEquals(["get", target, "0", proxy], log[1]);
+assertEquals(["deleteProperty", target, "0"], log[2]);
diff --git a/test/mjsunit/es6/proxies-keys.js b/test/mjsunit/es6/proxies-keys.js
new file mode 100644
index 0000000..7344032
--- /dev/null
+++ b/test/mjsunit/es6/proxies-keys.js
@@ -0,0 +1,39 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var target = {
+ target: 1
+};
+target.__proto__ = {
+ target_proto: 2
+};
+
+var handler = {
+ ownKeys: function(target) {
+ return ["foo", "bar", Symbol("baz"), "non-enum", "not-found"];
+ },
+ getOwnPropertyDescriptor: function(target, name) {
+ if (name == "non-enum") return {configurable: true};
+ if (name == "not-found") return undefined;
+ return {enumerable: true, configurable: true};
+ }
+}
+
+var proxy = new Proxy(target, handler);
+
+// Object.keys() ignores symbols and non-enumerable keys.
+assertEquals(["foo", "bar"], Object.keys(proxy));
+
+// Edge case: no properties left after filtering.
+handler.getOwnPropertyDescriptor = undefined;
+assertEquals([], Object.keys(proxy));
+
+// Throwing shouldn't crash.
+handler.getOwnPropertyDescriptor = function() { throw new Number(1); };
+assertThrows("Object.keys(proxy)", Number);
+
+// Fall through to target if there is no trap.
+handler.ownKeys = undefined;
+assertEquals(["target"], Object.keys(proxy));
+assertEquals(["target"], Object.keys(target));
diff --git a/test/mjsunit/es6/proxies-object-assign.js b/test/mjsunit/es6/proxies-object-assign.js
new file mode 100644
index 0000000..c350f4e
--- /dev/null
+++ b/test/mjsunit/es6/proxies-object-assign.js
@@ -0,0 +1,28 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var handler = {
+ ownKeys: function(t) { return ["a", "b"]; },
+ getOwnPropertyDescriptor: function(t, p) {
+ return {enumerable: true, configurable: true}
+ },
+ get: function(t, p) {
+ return 1;
+ }
+};
+
+var proxy = new Proxy({}, handler);
+
+var o = {};
+
+Object.assign(o, proxy);
+
+assertEquals({"a": 1, "b": 1}, o);
+
+(function TestStringSources() {
+ var source = "abc";
+ var target = {};
+ Object.assign(target, source);
+ assertEquals({0: "a", 1: "b", 2: "c"}, target);
+})();
diff --git a/test/mjsunit/es6/proxies-ownkeys.js b/test/mjsunit/es6/proxies-ownkeys.js
new file mode 100644
index 0000000..7cc0a87
--- /dev/null
+++ b/test/mjsunit/es6/proxies-ownkeys.js
@@ -0,0 +1,94 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var target = {
+ "target_one": 1
+};
+target.__proto__ = {
+ "target_proto_two": 2
+};
+var handler = {
+ ownKeys: function(target) {
+ return ["foo", "bar"];
+ }
+}
+
+var proxy = new Proxy(target, handler);
+
+// Simple case.
+assertEquals(["foo", "bar"], Reflect.ownKeys(proxy));
+
+// Test interesting steps of the algorithm:
+
+// Step 6: Fall through to target.[[OwnPropertyKeys]] if the trap is undefined.
+handler.ownKeys = undefined;
+assertEquals(["target_one"], Reflect.ownKeys(proxy));
+
+// Step 7: Throwing traps don't crash.
+handler.ownKeys = function(target) { throw 1; };
+assertThrows("Reflect.ownKeys(proxy)");
+
+// Step 8: CreateListFromArrayLike error cases:
+// Returning a non-Object throws.
+var keys = 1;
+handler.ownKeys = function(target) { return keys; };
+assertThrows("Reflect.ownKeys(proxy)", TypeError);
+keys = "string";
+assertThrows("Reflect.ownKeys(proxy)", TypeError);
+keys = Symbol("foo");
+assertThrows("Reflect.ownKeys(proxy)", TypeError);
+keys = null;
+assertThrows("Reflect.ownKeys(proxy)", TypeError);
+
+// "length" property is honored.
+keys = { 0: "a", 1: "b", 2: "c" };
+keys.length = 0;
+assertEquals([], Reflect.ownKeys(proxy));
+keys.length = 1;
+assertEquals(["a"], Reflect.ownKeys(proxy));
+keys.length = 3;
+assertEquals(["a", "b", "c"], Reflect.ownKeys(proxy));
+// The spec wants to allow lengths up to 2^53, but we can't allocate arrays
+// of that size, so we throw even for smaller values.
+keys.length = Math.pow(2, 33);
+assertThrows("Reflect.ownKeys(proxy)", RangeError);
+
+// Check that we allow duplicated keys.
+keys = ['a', 'a', 'a']
+assertEquals(keys, Reflect.ownKeys(proxy));
+
+// Non-Name results throw.
+keys = [1];
+assertThrows("Reflect.ownKeys(proxy)", TypeError);
+keys = [{}];
+assertThrows("Reflect.ownKeys(proxy)", TypeError);
+keys = [{toString: function() { return "foo"; }}];
+assertThrows("Reflect.ownKeys(proxy)", TypeError);
+keys = [null];
+assertThrows("Reflect.ownKeys(proxy)", TypeError);
+
+// Step 17a: The trap result must include all non-configurable keys.
+Object.defineProperty(target, "nonconf", {value: 1, configurable: false});
+keys = ["foo"];
+assertThrows("Reflect.ownKeys(proxy)", TypeError);
+keys = ["nonconf"];
+assertEquals(keys, Reflect.ownKeys(proxy));
+
+// Check that we allow duplicated keys.
+keys = ['nonconf', 'nonconf', 'nonconf']
+assertEquals(keys, Reflect.ownKeys(proxy));
+
+// Step 19a: The trap result must all keys of a non-extensible target.
+Object.preventExtensions(target);
+assertThrows("Reflect.ownKeys(proxy)", TypeError);
+keys = ["nonconf", "target_one"];
+assertEquals(keys, Reflect.ownKeys(proxy));
+
+// Step 20: The trap result must not add keys to a non-extensible target.
+keys = ["nonconf", "target_one", "fantasy"];
+assertThrows("Reflect.ownKeys(proxy)", TypeError);
+
+// Check that we allow duplicated keys.
+keys = ['nonconf', 'target_one', 'nonconf', 'nonconf', 'target_one',]
+assertEquals(keys, Reflect.ownKeys(proxy));
diff --git a/test/mjsunit/es6/proxies-prevent-extensions.js b/test/mjsunit/es6/proxies-prevent-extensions.js
new file mode 100644
index 0000000..dc3c42e
--- /dev/null
+++ b/test/mjsunit/es6/proxies-prevent-extensions.js
@@ -0,0 +1,85 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+(function () {
+ // No trap.
+
+ var target = {};
+ var handler = {};
+ var proxy = new Proxy(target, handler);
+
+ assertTrue(Reflect.isExtensible(target));
+ assertTrue(Reflect.isExtensible(proxy));
+ assertTrue(Reflect.preventExtensions(proxy));
+ assertFalse(Reflect.isExtensible(target));
+ assertFalse(Reflect.isExtensible(proxy));
+})();
+
+
+(function () {
+ // "Undefined" trap.
+
+ var target = {};
+ var handler = { preventExtensions: null };
+ var proxy = new Proxy(target, handler);
+
+ assertTrue(Reflect.isExtensible(target));
+ assertTrue(Reflect.isExtensible(proxy));
+ assertTrue(Reflect.preventExtensions(proxy));
+ assertFalse(Reflect.isExtensible(target));
+ assertFalse(Reflect.isExtensible(proxy));
+})();
+
+
+(function () {
+ // Invalid trap.
+
+ var target = {};
+ var handler = { preventExtensions: 42 };
+ var proxy = new Proxy(target, handler);
+
+ assertThrows(() => {Reflect.preventExtensions(proxy)}, TypeError);
+})();
+
+
+(function () {
+ var target = {};
+ var handler = { isExtensible() {return "bla"} };
+ var proxy = new Proxy(target, handler);
+
+ // Trap returns trueish and target is extensible.
+ assertTrue(Reflect.isExtensible(proxy));
+
+ // Trap returns trueish but target is not extensible.
+ Reflect.preventExtensions(target);
+ assertThrows(() => {Reflect.isExtensible(proxy)}, TypeError);
+})();
+
+
+(function () {
+ // Trap returns falsish.
+
+ var target = {};
+ var handler = { preventExtensions() {return 0} };
+ var proxy = new Proxy(target, handler);
+
+ assertFalse(Reflect.preventExtensions(proxy));
+ Reflect.preventExtensions(target);
+ assertFalse(Reflect.preventExtensions(proxy));
+})();
+
+
+(function () {
+ var target = {};
+ var handler = { preventExtensions() {return Symbol()} };
+ var proxy = new Proxy(target, handler);
+
+ // Trap returns trueish but target is extensible.
+ assertThrows(() => {Reflect.preventExtensions(proxy)}, TypeError);
+
+ // Trap returns trueish and target is not extensible.
+ Reflect.preventExtensions(target);
+ assertTrue(Reflect.preventExtensions(proxy));
+})();
diff --git a/test/mjsunit/es6/proxies-property-is-enumerable.js b/test/mjsunit/es6/proxies-property-is-enumerable.js
new file mode 100644
index 0000000..0d4a92f
--- /dev/null
+++ b/test/mjsunit/es6/proxies-property-is-enumerable.js
@@ -0,0 +1,28 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var handler = {};
+var target = { a: 1 };
+var proxy = new Proxy(target, handler);
+
+assertTrue(target.propertyIsEnumerable('a'));
+assertTrue(proxy.propertyIsEnumerable('a'));
+assertFalse(target.propertyIsEnumerable('b'));
+assertFalse(proxy.propertyIsEnumerable('b'));
+
+handler.getOwnPropertyDescriptor = function(target, prop) {
+ return { configurable: true, enumerable: true, value: 10 };
+}
+assertTrue(target.propertyIsEnumerable('a'));
+assertTrue(proxy.propertyIsEnumerable('a'));
+assertFalse(target.propertyIsEnumerable('b'));
+assertTrue(proxy.propertyIsEnumerable('b'));
+
+handler.getOwnPropertyDescriptor = function(target, prop) {
+ return { configurable: true, enumerable: false, value: 10 };
+}
+assertTrue(target.propertyIsEnumerable('a'));
+assertFalse(proxy.propertyIsEnumerable('a'));
+assertFalse(target.propertyIsEnumerable('b'));
+assertFalse(proxy.propertyIsEnumerable('b'));
diff --git a/test/mjsunit/es6/proxies-prototype-handler-stackoverflow.js b/test/mjsunit/es6/proxies-prototype-handler-stackoverflow.js
new file mode 100644
index 0000000..3da36c4
--- /dev/null
+++ b/test/mjsunit/es6/proxies-prototype-handler-stackoverflow.js
@@ -0,0 +1,118 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --stack-size=100
+
+// Test that traps that involve walking the target object's prototype chain
+// don't overflow the stack when the original proxy is on that chain.
+
+(function TestGetPrototype() {
+ var handler = {};
+ var p = new Proxy({}, handler);
+ handler.__proto__ = p;
+ try { return p.__proto__; } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+(function TestSetPrototype() {
+ var handler = {};
+ var p = new Proxy({}, handler);
+ handler.__proto__ = p;
+ try { p.__proto__ = p; } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+(function TestHasProperty() {
+ var handler = {};
+ var p = new Proxy({}, handler);
+ handler.__proto__ = p;
+ try {
+ return Reflect.has(p, "foo");
+ } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+(function TestSet() {
+ var handler = {};
+ var p = new Proxy({}, handler);
+ handler.__proto__ = p;
+ try { p.foo = 1; } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+(function TestGet() {
+ var handler = {};
+ var p = new Proxy({}, handler);
+ handler.__proto__ = p;
+ try { return p.foo; } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+(function TestEnumerate() {
+ var handler = {};
+ var p = new Proxy({}, handler);
+ handler.__proto__ = p;
+ try { for (var x in p) {} } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+(function TestIsExtensible() {
+ var handler = {};
+ var p = new Proxy({}, handler);
+ handler.__proto__ = p;
+ try {
+ return Reflect.isExtensible(p);
+ } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+(function TestPreventExtensions() {
+ var handler = {};
+ var p = new Proxy({}, handler);
+ handler.__proto__ = p;
+ try {
+ Reflect.preventExtensions(p);
+ } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+(function TestGetOwnPropertyDescriptor() {
+ var handler = {};
+ var p = new Proxy({}, handler);
+ handler.__proto__ = p;
+ try {
+ return Object.getOwnPropertyDescriptor(p, "foo");
+ } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+(function TestDeleteProperty() {
+ var handler = {};
+ var p = new Proxy({}, handler);
+ handler.__proto__ = p;
+ try { delete p.foo; } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+(function TestDefineProperty() {
+ var handler = {};
+ var p = new Proxy({}, handler);
+ handler.__proto__ = p;
+ try {
+ Object.defineProperty(p, "foo", {value: "bar"});
+ } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+(function TestOwnKeys() {
+ var handler = {};
+ var p = new Proxy({}, handler);
+ handler.__proto__ = p;
+ try {
+ return Reflect.ownKeys(p);
+ } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+(function TestCall() {
+ var handler = {};
+ var p = new Proxy(function() {}, handler);
+ handler.__proto__ = p;
+ try { return p(); } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+(function TestConstruct() {
+ var handler = {};
+ var p = new Proxy(function() { this.foo = 1; }, handler);
+ handler.__proto__ = p;
+ try { return new p(); } catch(e) { assertInstanceof(e, RangeError); }
+})();
diff --git a/test/mjsunit/es6/proxies-prototype-target-stackoverflow.js b/test/mjsunit/es6/proxies-prototype-target-stackoverflow.js
new file mode 100644
index 0000000..741a8b0
--- /dev/null
+++ b/test/mjsunit/es6/proxies-prototype-target-stackoverflow.js
@@ -0,0 +1,95 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Test that traps that involve walking the target object's prototype chain
+// don't overflow the stack when the original proxy is on that chain.
+
+(function TestGetPrototype() {
+ var p = new Proxy({}, {});
+ p.__proto__ = p;
+ try { return p.__proto__; } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+(function TestSetPrototype() {
+ var p = new Proxy({}, {});
+ p.__proto__ = p;
+ try { p.__proto__ = p; } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+(function TestHasProperty() {
+ var p = new Proxy({}, {});
+ p.__proto__ = p;
+ try {
+ return Reflect.has(p, "foo");
+ } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+(function TestSet() {
+ var p = new Proxy({}, {});
+ p.__proto__ = p;
+ try { p.foo = 1; } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+(function TestGet() {
+ var p = new Proxy({}, {});
+ p.__proto__ = p;
+ try { return p.foo; } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+(function TestEnumerate() {
+ var p = new Proxy({}, {});
+ p.__proto__ = p;
+ try { for (var x in p) {} } catch(e) { assertInstanceof(e, RangeError); }
+})();
+
+// The following traps don't involve the target object's prototype chain;
+// we test them anyway for completeness.
+
+(function TestIsExtensible() {
+ var p = new Proxy({}, {});
+ p.__proto__ = p;
+ return Reflect.isExtensible(p);
+})();
+
+(function TestPreventExtensions() {
+ var p = new Proxy({}, {});
+ p.__proto__ = p;
+ Reflect.preventExtensions(p);
+})();
+
+(function TestGetOwnPropertyDescriptor() {
+ var p = new Proxy({}, {});
+ p.__proto__ = p;
+ return Object.getOwnPropertyDescriptor(p, "foo");
+})();
+
+(function TestDeleteProperty() {
+ var p = new Proxy({}, {});
+ p.__proto__ = p;
+ delete p.foo;
+})();
+
+(function TestDefineProperty() {
+ var p = new Proxy({}, {});
+ p.__proto__ = p;
+ Object.defineProperty(p, "foo", {value: "bar"});
+})();
+
+(function TestOwnKeys() {
+ var p = new Proxy({}, {});
+ p.__proto__ = p;
+ return Reflect.ownKeys(p);
+})();
+
+(function TestCall() {
+ var p = new Proxy(function() {}, {});
+ p.__proto__ = p;
+ return p();
+})();
+
+(function TestConstruct() {
+ var p = new Proxy(function() { this.foo = 1; }, {});
+ p.__proto__ = p;
+ return new p();
+})();
diff --git a/test/mjsunit/es6/proxies-revocable.js b/test/mjsunit/es6/proxies-revocable.js
new file mode 100644
index 0000000..1f61174
--- /dev/null
+++ b/test/mjsunit/es6/proxies-revocable.js
@@ -0,0 +1,23 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+traps = [
+ "getPrototypeOf", "setPrototypeOf", "isExtensible", "preventExtensions",
+ "getOwnPropertyDescriptor", "has", "get", "set", "deleteProperty",
+ "defineProperty", "ownKeys", "apply", "construct"
+];
+
+var {proxy, revoke} = Proxy.revocable({}, {});
+assertEquals(0, revoke.length);
+
+assertEquals(undefined, revoke());
+for (var trap of traps) {
+ assertThrows(() => Reflect[trap](proxy), TypeError);
+}
+
+assertEquals(undefined, revoke());
+for (var trap of traps) {
+ assertThrows(() => Reflect[trap](proxy), TypeError);
+}
diff --git a/test/mjsunit/es6/proxies-set-prototype-of.js b/test/mjsunit/es6/proxies-set-prototype-of.js
new file mode 100644
index 0000000..9d9e73f
--- /dev/null
+++ b/test/mjsunit/es6/proxies-set-prototype-of.js
@@ -0,0 +1,128 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var target = { target: 1 };
+target.__proto__ = {};
+var handler = { handler: 1 };
+var proxy = new Proxy(target, handler);
+
+assertSame(Object.getPrototypeOf(proxy), target.__proto__ );
+
+
+assertThrows(function() { Object.setPrototypeOf(proxy, undefined) }, TypeError);
+assertThrows(function() { Object.setPrototypeOf(proxy, 1) }, TypeError);
+
+var prototype = [1];
+assertSame(proxy, Object.setPrototypeOf(proxy, prototype));
+assertSame(prototype, Object.getPrototypeOf(proxy));
+assertSame(prototype, Object.getPrototypeOf(target));
+
+var pair = Proxy.revocable(target, handler);
+assertSame(pair.proxy, Object.setPrototypeOf(pair.proxy, prototype));
+assertSame(prototype, Object.getPrototypeOf(pair.proxy));
+pair.revoke();
+assertThrows('Object.setPrototypeOf(pair.proxy, prototype)', TypeError);
+
+handler.setPrototypeOf = function(target, proto) {
+ return false;
+};
+assertThrows(function() { Object.setPrototypeOf(proxy, {a:1}) }, TypeError);
+
+handler.setPrototypeOf = function(target, proto) {
+ return undefined;
+};
+assertThrows(function() { Object.setPrototypeOf(proxy, {a:2}) }, TypeError);
+
+handler.setPrototypeOf = function(proto) {};
+assertThrows(function() { Object.setPrototypeOf(proxy, {a:3}) }, TypeError);
+
+handler.setPrototypeOf = function(target, proto) {
+ throw Error();
+};
+assertThrows(function() { Object.setPrototypeOf(proxy, {a:4}) }, Error);
+
+var seen_prototype;
+var seen_target;
+handler.setPrototypeOf = function(target, proto) {
+ seen_target = target;
+ seen_prototype = proto;
+ return true;
+}
+assertSame(Object.setPrototypeOf(proxy, {a:5}), proxy);
+assertSame(target, seen_target);
+assertEquals({a:5}, seen_prototype);
+
+(function setPrototypeProxyTarget() {
+ var target = { target: 1 };
+ target.__proto__ = {};
+ var handler = {};
+ var handler2 = {};
+ var target2 = new Proxy(target, handler2);
+ var proxy2 = new Proxy(target2, handler);
+ assertSame(Object.getPrototypeOf(proxy2), target.__proto__ );
+
+ var prototype = [2,3];
+ assertSame(proxy2, Object.setPrototypeOf(proxy2, prototype));
+ assertSame(prototype, Object.getPrototypeOf(proxy2));
+ assertSame(prototype, Object.getPrototypeOf(target));
+})();
+
+(function testProxyTrapInconsistent() {
+ var target = { target: 1 };
+ target.__proto__ = {};
+ var handler = {};
+ var handler2 = {
+ };
+
+ var target2 = new Proxy(target, handler);
+ var proxy2 = new Proxy(target2, handler2);
+
+ // If the final target is extensible we can set any prototype.
+ var prototype = [1];
+ Reflect.setPrototypeOf(proxy2, prototype);
+ assertSame(prototype, Reflect.getPrototypeOf(target));
+
+ handler2.setPrototypeOf = function(target, value) {
+ Reflect.setPrototypeOf(target, value);
+ return true;
+ };
+ prototype = [2];
+ Reflect.setPrototypeOf(proxy2, prototype);
+ assertSame(prototype, Reflect.getPrototypeOf(target));
+
+ // Prevent getting the target's prototype used to check the invariant.
+ var gotPrototype = false;
+ handler.getPrototypeOf = function() {
+ gotPrototype = true;
+ throw TypeError()
+ };
+ // If the target is extensible we do not check the invariant.
+ prototype = [3];
+ Reflect.setPrototypeOf(proxy2, prototype);
+ assertFalse(gotPrototype);
+ assertSame(prototype, Reflect.getPrototypeOf(target));
+
+ // Changing the prototype of a non-extensible target will trigger the
+ // invariant-check and throw in the above handler.
+ Reflect.preventExtensions(target);
+ assertThrows(() => {Reflect.setPrototypeOf(proxy2, [4])}, TypeError);
+ assertTrue(gotPrototype);
+ assertEquals([3], Reflect.getPrototypeOf(target));
+
+ // Setting the prototype of a non-extensible target is fine if the prototype
+ // doesn't change.
+ delete handler.getPrototypeOf;
+ Reflect.setPrototypeOf(proxy2, prototype);
+ // Changing the prototype will throw.
+ prototype = [5];
+ assertThrows(() => {Reflect.setPrototypeOf(proxy2, prototype)}, TypeError);
+})();
+
+(function testProxyTrapReturnsFalse() {
+ var handler = {};
+ handler.setPrototypeOf = () => false;
+ var target = new Proxy({}, {isExtensible: () => assertUnreachable()});
+ var object = new Proxy(target, handler);
+ assertFalse(Reflect.setPrototypeOf(object, {}));
+})();
diff --git a/test/mjsunit/es6/proxies-set.js b/test/mjsunit/es6/proxies-set.js
new file mode 100644
index 0000000..19f39f9
--- /dev/null
+++ b/test/mjsunit/es6/proxies-set.js
@@ -0,0 +1,310 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+function sloppyDefaultSet(o, p, v) { return o[p] = v }
+function sloppyReflectSet(o, p, v) { return Reflect.set(o, p, v) }
+function strictDefaultSet(o, p, v) { "use strict"; return o[p] = v }
+function strictReflectSet(o, p, v) { "use strict"; return Reflect.set(o, p, v) }
+
+sloppyDefaultSet.shouldThrow = false;
+sloppyReflectSet.shouldThrow = false;
+strictDefaultSet.shouldThrow = true;
+strictReflectSet.shouldThrow = false;
+
+sloppyDefaultSet.returnsBool = false;
+sloppyReflectSet.returnsBool = true;
+strictDefaultSet.returnsBool = false;
+strictReflectSet.returnsBool = true;
+
+
+function assertTrueIf(flag, x) { if (flag) assertTrue(x) }
+function assertFalseIf(flag, x) { if (flag) assertFalse(x) }
+function assertSetFails(mySet, o, p, v) {
+ if (mySet.shouldThrow) {
+ assertThrows(() => mySet(o, p, v), TypeError);
+ } else {
+ assertFalseIf(mySet.returnsBool, mySet(o, p, v));
+ }
+}
+
+
+function dataDescriptor(x) {
+ return {value: x, writable: true, enumerable: true, configurable: true};
+}
+
+
+function toKey(x) {
+ if (typeof x === "symbol") return x;
+ return String(x);
+}
+
+
+var properties =
+ ["bla", "0", 1, Symbol(), {[Symbol.toPrimitive]() {return "a"}}];
+
+
+function TestForwarding(handler, mySet) {
+ assertTrue(undefined == handler.set);
+ assertTrue(undefined == handler.getOwnPropertyDescriptor);
+ assertTrue(undefined == handler.defineProperty);
+
+ var target = {};
+ var proxy = new Proxy(target, handler);
+
+ // Property does not exist on target.
+ for (var p of properties) {
+ assertTrueIf(mySet.returnsBool, mySet(proxy, p, 42));
+ assertSame(42, target[p]);
+ }
+
+ // Property exists as writable data on target.
+ for (var p of properties) {
+ assertTrueIf(mySet.returnsBool, mySet(proxy, p, 0));
+ assertSame(0, target[p]);
+ }
+
+ // Property exists as non-writable data on target.
+ for (var p of properties) {
+ Object.defineProperty(target, p,
+ {value: 42, configurable: true, writable: false});
+ assertSetFails(mySet, proxy, p, 42);
+ assertSetFails(mySet, proxy, p, 0);
+ assertEquals(42, target[p]);
+ }
+};
+
+(function () {
+ // No trap.
+ var handler = {};
+ TestForwarding(handler, sloppyDefaultSet);
+ TestForwarding(handler, sloppyReflectSet);
+ TestForwarding(handler, strictDefaultSet);
+ TestForwarding(handler, strictReflectSet);
+})();
+
+(function () {
+ // "Undefined" trap.
+ var handler = { set: null };
+ TestForwarding(handler, sloppyDefaultSet);
+ TestForwarding(handler, sloppyReflectSet);
+ TestForwarding(handler, strictDefaultSet);
+ TestForwarding(handler, strictReflectSet);
+})();
+
+
+function TestForwarding2(mySet) {
+ // Check that setting on a proxy without "set" trap correctly triggers its
+ // "getOwnProperty" trap and its "defineProperty" trap.
+
+ var target = {};
+ var handler = {};
+ var observations = [];
+ var proxy = new Proxy(target, handler);
+
+ handler.getOwnPropertyDescriptor = function() {
+ observations.push(arguments);
+ return Reflect.getOwnPropertyDescriptor(...arguments);
+ }
+
+ handler.defineProperty = function() {
+ observations.push(arguments);
+ return Reflect.defineProperty(...arguments);
+ }
+
+ for (var p of properties) {
+ mySet(proxy, p, 42);
+ assertEquals(2, observations.length)
+ assertArrayEquals([target, toKey(p)], observations[0]);
+ assertSame(target, observations[0][0]);
+ assertArrayEquals([target, toKey(p), dataDescriptor(42)], observations[1]);
+ assertSame(target, observations[1][0]);
+ observations = [];
+
+ mySet(proxy, p, 42);
+ assertEquals(2, observations.length)
+ assertArrayEquals([target, toKey(p)], observations[0]);
+ assertSame(target, observations[0][0]);
+ assertArrayEquals([target, toKey(p), {value: 42}], observations[1]);
+ assertSame(target, observations[1][0]);
+ observations = [];
+ }
+}
+
+TestForwarding2(sloppyDefaultSet);
+TestForwarding2(sloppyReflectSet);
+TestForwarding2(strictDefaultSet);
+TestForwarding2(strictReflectSet);
+
+
+function TestInvalidTrap(proxy, mySet) {
+ for (var p of properties) {
+ assertThrows(() => mySet(proxy, p, 42), TypeError);
+ }
+}
+
+(function () {
+ var target = {};
+ var handler = { set: true };
+ var proxy = new Proxy(target, handler);
+
+ TestInvalidTrap(proxy, sloppyDefaultSet);
+ TestInvalidTrap(proxy, sloppyReflectSet);
+ TestInvalidTrap(proxy, strictDefaultSet);
+ TestInvalidTrap(proxy, strictReflectSet);
+})();
+
+
+function TestTrappingFalsish(mySet) {
+ var target = {};
+ var handler = { set() {return ""} };
+ var proxy = new Proxy(target, handler);
+
+ for (var p of properties) {
+ assertSetFails(mySet, proxy, p, 42);
+ }
+}
+
+TestTrappingFalsish(sloppyDefaultSet);
+TestTrappingFalsish(sloppyReflectSet);
+TestTrappingFalsish(strictDefaultSet);
+TestTrappingFalsish(strictReflectSet);
+
+
+function TestTrappingTrueish(mySet) {
+ var target = {};
+ var handler = { set() {return 42} };
+ var proxy = new Proxy(target, handler);
+
+ // Trap returns trueish and property does not exist in target.
+ for (var p of properties) {
+ assertTrueIf(mySet.returnsBool, mySet(proxy, p, 0));
+ }
+
+ // Trap returns trueish and target property is configurable or writable data.
+ for (var p of properties) {
+ Object.defineProperty(target, p, {configurable: true, writable: true});
+ assertTrueIf(mySet.returnsBool, mySet(proxy, p, 0));
+ Object.defineProperty(target, p, {configurable: true, writable: false});
+ assertTrueIf(mySet.returnsBool, mySet(proxy, p, 0));
+ Object.defineProperty(target, p, {configurable: false, writable: true});
+ assertTrueIf(mySet.returnsBool, mySet(proxy, p, 0));
+ }
+}
+
+TestTrappingTrueish(sloppyDefaultSet);
+TestTrappingTrueish(sloppyReflectSet);
+TestTrappingTrueish(strictDefaultSet);
+TestTrappingTrueish(strictReflectSet);
+
+
+function TestTrappingTrueish2(mySet) {
+ var target = {};
+ var handler = { set() {return 42} };
+ var proxy = new Proxy(target, handler);
+
+ // Trap returns trueish but target property is frozen data.
+ for (var p of properties) {
+ Object.defineProperty(target, p, {
+ configurable: false, writable: false, value: 0
+ });
+ assertThrows(() => mySet(proxy, p, 666), TypeError); // New value.
+ assertTrueIf(mySet.returnsBool, mySet(proxy, p, 0)); // Old value.
+ }
+};
+
+TestTrappingTrueish2(sloppyDefaultSet);
+TestTrappingTrueish2(sloppyReflectSet);
+TestTrappingTrueish2(strictDefaultSet);
+TestTrappingTrueish2(strictReflectSet);
+
+
+function TestTrappingTrueish3(mySet) {
+ var target = {};
+ var handler = { set() {return 42} };
+ var proxy = new Proxy(target, handler);
+
+ // Trap returns trueish and target property is configurable accessor.
+ for (var p of properties) {
+ Object.defineProperty(target, p, { configurable: true, set: undefined });
+ assertTrueIf(mySet.returnsBool, mySet(proxy, p, 0));
+ }
+
+ // Trap returns trueish and target property is non-configurable accessor.
+ for (var p of properties) {
+ Object.defineProperty(target, p, { configurable: false, set: undefined });
+ assertThrows(() => mySet(proxy, p, 0));
+ }
+};
+
+TestTrappingTrueish3(sloppyDefaultSet);
+TestTrappingTrueish3(sloppyReflectSet);
+TestTrappingTrueish3(strictDefaultSet);
+TestTrappingTrueish3(strictReflectSet);
+
+
+function TestTrapReceiverArgument(mySet) {
+ var target = {};
+ var handler = {};
+ var observations = [];
+ var proxy = new Proxy(target, handler);
+ var object = Object.create(proxy);
+
+ handler.set = function() {
+ observations.push(arguments);
+ return Reflect.set(...arguments);
+ }
+
+ for (var p of properties) {
+ mySet(object, p, 42);
+ assertEquals(1, observations.length)
+ assertArrayEquals([target, toKey(p), 42, object], observations[0]);
+ assertSame(target, observations[0][0]);
+ assertSame(object, observations[0][3]);
+ observations = [];
+ }
+};
+
+TestTrapReceiverArgument(sloppyDefaultSet);
+TestTrapReceiverArgument(sloppyReflectSet);
+TestTrapReceiverArgument(strictDefaultSet);
+TestTrapReceiverArgument(strictReflectSet);
+
+
+(function TestTrapReceiverArgument2() {
+ // Check that non-object receiver is passed through as well.
+
+ var target = {};
+ var handler = {};
+ var observations = [];
+ var proxy = new Proxy(target, handler);
+
+ handler.set = function() {
+ observations.push(arguments);
+ return Reflect.set(...arguments);
+ }
+
+ for (var p of properties) {
+ for (var receiver of [null, undefined, 1]) {
+ Reflect.set(proxy, p, 42, receiver);
+ assertEquals(1, observations.length)
+ assertArrayEquals([target, toKey(p), 42, receiver], observations[0]);
+ assertSame(target, observations[0][0]);
+ assertSame(receiver, observations[0][3]);
+ observations = [];
+ }
+ }
+
+ var object = Object.create(proxy);
+ for (var p of properties) {
+ for (var receiver of [null, undefined, 1]) {
+ Reflect.set(object, p, 42, receiver);
+ assertEquals(1, observations.length);
+ assertArrayEquals([target, toKey(p), 42, receiver], observations[0]);
+ assertSame(target, observations[0][0]);
+ assertSame(receiver, observations[0][3]);
+ observations = [];
+ }
+ }
+})();
diff --git a/test/mjsunit/es6/proxies-with-unscopables.js b/test/mjsunit/es6/proxies-with-unscopables.js
new file mode 100644
index 0000000..b9a7ad8
--- /dev/null
+++ b/test/mjsunit/es6/proxies-with-unscopables.js
@@ -0,0 +1,146 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+function TestBasics() {
+ var log = [];
+
+ var proxy = new Proxy({}, {
+ get: function(target, key) {
+ log.push("get " + String(key));
+ if (key === 'x') return 1;
+ },
+ has: function(target, key) {
+ log.push("has " + String(key));
+ if (key === 'x') return true;
+ return false;
+ }
+ });
+
+ var x = 'local';
+
+ with (proxy) {
+ assertEquals(1, x);
+ }
+
+ assertEquals(['has assertEquals', 'has x', 'get Symbol(Symbol.unscopables)',
+ 'get x'], log);
+}
+TestBasics();
+
+
+function TestInconsistent() {
+ var log = [];
+
+ var proxy = new Proxy({}, {
+ get: function(target, key) {
+ log.push("get " + String(key));
+ return undefined;
+ },
+ has: function(target, key) {
+ log.push("has " + String(key));
+ if (key === 'x') return true;
+ return false;
+ }
+ });
+
+ var x = 'local';
+
+ with (proxy) {
+ assertEquals(void 0, x);
+ }
+
+ assertEquals(['has assertEquals', 'has x', 'get Symbol(Symbol.unscopables)',
+ 'get x'], log);
+}
+TestInconsistent();
+
+
+function TestUseProxyAsUnscopables() {
+ var x = 1;
+ var object = {
+ x: 2
+ };
+ var calls = 0;
+ var proxy = new Proxy({}, {
+ has: function() {
+ assertUnreachable();
+ },
+ get: function(target, key) {
+ assertEquals('x', key);
+ calls++;
+ return calls === 2 ? true : undefined;
+ }
+ });
+
+ object[Symbol.unscopables] = proxy;
+
+ with (object) {
+ assertEquals(2, x);
+ assertEquals(1, x);
+ }
+
+ // HasBinding, HasBinding
+ assertEquals(2, calls);
+}
+TestUseProxyAsUnscopables();
+
+
+function TestThrowInHasUnscopables() {
+ var x = 1;
+ var object = {
+ x: 2
+ };
+
+ function CustomError() {}
+
+ var calls = 0;
+ var proxy = new Proxy({}, {
+ has: function() {
+ assertUnreachable();
+ },
+ get: function(target, key) {
+ if (calls++ === 0) {
+ throw new CustomError();
+ }
+ assertUnreachable();
+ }
+ });
+
+ object[Symbol.unscopables] = proxy;
+
+ assertThrows(function() {
+ with (object) {
+ x;
+ }
+ }, CustomError);
+}
+TestThrowInHasUnscopables();
+
+
+var global = this;
+function TestGlobalShouldIgnoreUnscopables() {
+ global.x = 1;
+ var proxy = new Proxy({}, {
+ get: function() {
+ assertUnreachable();
+ },
+ has: function() {
+ assertUnreachable();
+ }
+ });
+ global[Symbol.unscopables] = proxy;
+
+ assertEquals(1, global.x);
+ assertEquals(1, x);
+
+ global.x = 2;
+ assertEquals(2, global.x);
+ assertEquals(2, x);
+
+ x = 3;
+ assertEquals(3, global.x);
+ assertEquals(3, x);
+}
+TestGlobalShouldIgnoreUnscopables();
diff --git a/test/mjsunit/es6/proxies-with.js b/test/mjsunit/es6/proxies-with.js
new file mode 100644
index 0000000..710e8b5
--- /dev/null
+++ b/test/mjsunit/es6/proxies-with.js
@@ -0,0 +1,351 @@
+// Copyright 2011 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.
+
+
+// Helper.
+
+function TestWithProxies(test, x, y, z) {
+ test(function(h) { return new Proxy({}, h) }, x, y, z)
+ test(function(h) {
+ return new Proxy(function() {}, h)
+ }, x, y, z)
+}
+
+
+
+// Getting.
+
+function TestWithGet(handler) {
+ TestWithProxies(TestWithGet2, handler)
+}
+
+var c = "global"
+var key = ""
+
+function TestWithGet2(create, handler) {
+ var b = "local"
+
+ var p = create(handler);
+ assertEquals("onproxy", p.a);
+ assertEquals(undefined, p.b);
+ assertEquals(undefined, p.c);
+
+ with (p) {
+ assertEquals("onproxy", a);
+ assertEquals("local", b);
+ assertEquals("global", c);
+ }
+
+ var o = Object.create(p, {d: {value: "own"}})
+ with (o) {
+ assertEquals("onproxy", a)
+ assertEquals("local", b);
+ assertEquals("global", c)
+ assertEquals("own", d)
+ }
+}
+
+TestWithGet({
+ get(target, k) {
+ key = k;
+ return k === "a" ? "onproxy" : undefined
+ },
+ has(target, k) { return k === 'a' }
+})
+
+TestWithGet({
+ get: function(r, k) { return this.get2(r, k) },
+ get2: function(r, k) { key = k; return k === "a" ? "onproxy" : undefined },
+ has(target, k) { return k === 'a' }
+})
+
+
+
+
+// Invoking.
+
+function TestWithGetCall(handler) {
+ TestWithProxies(TestWithGetCall2, handler)
+}
+
+var receiver = null
+var c = function() { return "global" }
+
+function TestWithGetCall2(create, handler) {
+ var b = function() { return "local" }
+
+ var p = create(handler)
+ with (p) {
+ receiver = null
+ assertEquals("onproxy", a())
+ assertSame(p, receiver)
+ assertEquals("local", b())
+ assertEquals("global", c())
+ }
+
+ var o = Object.create(p, {d: {value: function() { return "own" }}})
+ with (o) {
+ receiver = null
+ assertEquals("onproxy", a())
+ assertSame(o, receiver)
+ assertEquals("local", b())
+ assertEquals("global", c())
+ assertEquals("own", d())
+ }
+}
+
+function onproxy() { receiver = this; return "onproxy" }
+
+TestWithGetCall({
+ get: function(r, k) { key = k; return k === "a" ? onproxy : undefined },
+ has: function(t, k) {
+ key = k;
+ return k === "a";
+ }
+})
+
+TestWithGetCall({
+ get: function(r, k) { return this.get2(r, k) },
+ get2: function(r, k) { key = k; return k === "a" ? onproxy : undefined },
+ has: function(t, k) {
+ key = k;
+ return k === "a";
+ }
+})
+
+TestWithGetCall({
+ get: function(r, k) { key = k; return k === "a" ? onproxy : undefined },
+ has: function(t, k) {
+ return this.has2(k)
+ },
+ has2: function(k) {
+ key = k;
+ return k === "a";
+ }
+})
+
+TestWithGetCall({
+ get: function(r, k) { key = k; return k === "a" ? onproxy : undefined },
+ has: function(t, k) {
+ key = k;
+ return k === "a";
+ }
+})
+
+
+function TestWithGetCallThrow(handler) {
+ TestWithProxies(TestWithGetCallThrow2, handler)
+}
+
+function TestWithGetCallThrow2(create, handler) {
+ var b = function() { return "local" }
+
+ var p = create(handler)
+ with (p) {
+ assertThrowsEquals(function(){ a() }, "myexn")
+ assertEquals("local", b())
+ assertEquals("global", c())
+ }
+
+ var o = Object.create(p, {d: {value: function() { return "own" }}})
+ with (o) {
+ assertThrowsEquals(function(){ a() }, "myexn")
+ assertEquals("local", b())
+ assertEquals("global", c())
+ assertEquals("own", d())
+ }
+}
+
+function onproxythrow() { throw "myexn" }
+
+TestWithGetCallThrow({
+ has: function(r, k) { return k === "a"; },
+ get: function(r, k) { key = k; return k === "a" ? onproxythrow : undefined },
+})
+
+TestWithGetCallThrow({
+ has: function(r, k) { return k === "a"; },
+ get: function(r, k) { return this.get2(r, k) },
+ get2: function(r, k) { key = k; return k === "a" ? onproxythrow : undefined },
+})
+
+
+
+// Setting.
+
+var key
+var val
+
+function TestWithSet(handler, hasSetter) {
+ TestWithProxies(TestWithSet2, handler, hasSetter)
+}
+
+var c = "global"
+
+function TestWithSet2(create, handler, hasSetter) {
+ var b = "local"
+
+ var p = create(handler)
+ key = val = undefined
+ with (p) {
+ a = "set"
+ assertEquals("a", key)
+ assertEquals("set", val)
+ assertEquals("local", b)
+ assertEquals("global", c)
+ b = "local"
+ c = "global"
+ assertEquals("a", key)
+ assertEquals("set", val)
+ }
+
+ if (!hasSetter) return
+
+ var o = Object.create(p, {d: {value: "own"}})
+ key = val = undefined
+ with (o) {
+ a = "set"
+ assertEquals("a", key)
+ assertEquals("set", val)
+ assertEquals("local", b)
+ assertEquals("global", c)
+ assertEquals("own", d)
+ b = "local"
+ c = "global"
+ d = "own"
+ assertEquals("a", key)
+ assertEquals("set", val)
+ }
+}
+
+TestWithSet({
+ set: function(r, k, v) { key = k; val = v; return true },
+ has: function(t, k) {
+ return k === "a"
+ }
+})
+
+TestWithSet({
+ set: function(r, k, v) { return this.set2(r, k, v) },
+ set2: function(r, k, v) { key = k; val = v; return true },
+ has: function(t, k) {
+ return k === "a"
+ }
+})
+
+TestWithSet({
+ has: function(t, k) {
+ return k === "a"
+ },
+ defineProperty: function(t, k, desc) { key = k; val = desc.value }
+})
+
+TestWithSet({
+ has: function(t, k) {
+ return this.has2(k)
+ },
+ has2: function(k) {
+ return k === "a"
+ },
+ defineProperty: function(t, k, desc) { this.defineProperty2(k, desc) },
+ defineProperty2: function(k, desc) { key = k; val = desc.value }
+})
+
+TestWithSet({
+ has: function(t, k) {
+ return k === "a"
+ },
+ defineProperty: function(t, k, desc) { key = k; val = desc.value }
+})
+
+TestWithSet({
+ has: function(t, k) {
+ return this.has2(k) },
+ has2: function(k) {
+ return k === "a"
+ },
+ set: function(t, k, v) { key = k; val = v; return true }
+}, true)
+
+TestWithSet({
+ has: function(t, k) {
+ return k === "a"
+ },
+ defineProperty: function(t, k, desc) { key = k; val = desc.value }
+})
+
+
+function TestWithSetThrow(handler, hasSetter) {
+ TestWithProxies(TestWithSetThrow2, handler, hasSetter)
+}
+
+function TestWithSetThrow2(create, handler, hasSetter) {
+ var p = create(handler)
+ assertThrowsEquals(function(){
+ with (p) {
+ a = 1
+ }
+ }, "myexn")
+
+ if (!hasSetter) return
+
+ var o = Object.create(p, {})
+ assertThrowsEquals(function(){
+ with (o) {
+ a = 1
+ }
+ }, "myexn")
+}
+
+TestWithSetThrow({
+ set: function() { throw "myexn" },
+ has: function(t, k) {
+ return k === "a"
+ }
+})
+
+TestWithSetThrow({
+ has: function() { throw "myexn" },
+})
+
+TestWithSetThrow({
+ has: function() { throw "myexn" },
+})
+
+TestWithSetThrow({
+ has: function(t, k) {
+ return k === "a"
+ },
+ defineProperty: function() { throw "myexn" }
+})
+
+TestWithSetThrow({
+ has: function(t, k) {
+ return k === "a"
+ },
+ set: function() { throw "myexn" }
+}, true)
diff --git a/test/mjsunit/es6/proxies.js b/test/mjsunit/es6/proxies.js
new file mode 100644
index 0000000..3b9a4c5
--- /dev/null
+++ b/test/mjsunit/es6/proxies.js
@@ -0,0 +1,1506 @@
+// Copyright 2011 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.
+
+// We change the stack size for the ARM64 simulator because at one point this
+// test enters an infinite recursion which goes through the runtime and we
+// overflow the system stack before the simulator stack.
+
+// Flags: --sim-stack-size=500 --allow-natives-syntax
+
+
+// Helper.
+
+function TestWithProxies(test, x, y, z) {
+ // Separate function for nicer stack traces.
+ TestWithObjectProxy(test, x, y, z);
+ TestWithFunctionProxy(test, x, y, z);
+}
+
+function TestWithObjectProxy(test, x, y, z) {
+ test((handler) => { return new Proxy({}, handler) }, x, y, z)
+
+}
+
+function TestWithFunctionProxy(test, x, y, z) {
+ test((handler) => { return new Proxy(() => {}, handler) }, x, y, z)
+}
+
+// ---------------------------------------------------------------------------
+// Getting property descriptors (Object.getOwnPropertyDescriptor).
+
+var key
+
+function TestGetOwnProperty(handler) {
+ TestWithProxies(TestGetOwnProperty2, handler)
+}
+
+function TestGetOwnProperty2(create, handler) {
+ var p = create(handler)
+ assertEquals(42, Object.getOwnPropertyDescriptor(p, "a").value)
+ assertEquals("a", key)
+ assertEquals(42, Object.getOwnPropertyDescriptor(p, 99).value)
+ assertEquals("99", key)
+}
+
+TestGetOwnProperty({
+ getOwnPropertyDescriptor(target, k) {
+ key = k
+ return {value: 42, configurable: true}
+ }
+})
+
+TestGetOwnProperty({
+ getOwnPropertyDescriptor(target, k) {
+ return this.getOwnPropertyDescriptor2(k)
+ },
+ getOwnPropertyDescriptor2(k) {
+ key = k
+ return {value: 42, configurable: true}
+ }
+})
+
+TestGetOwnProperty({
+ getOwnPropertyDescriptor(target, k) {
+ key = k
+ return {get value() { return 42 }, get configurable() { return true }}
+ }
+})
+
+TestGetOwnProperty(new Proxy({}, {
+ get(target, pk, receiver) {
+ return function(t, k) { key = k; return {value: 42, configurable: true} }
+ }
+}))
+
+
+// ---------------------------------------------------------------------------
+function TestGetOwnPropertyThrow(handler) {
+ TestWithProxies(TestGetOwnPropertyThrow2, handler)
+}
+
+function TestGetOwnPropertyThrow2(create, handler) {
+ var p = create(handler)
+ assertThrowsEquals(() => Object.getOwnPropertyDescriptor(p, "a"), "myexn")
+ assertThrowsEquals(() => Object.getOwnPropertyDescriptor(p, 77), "myexn")
+}
+
+TestGetOwnPropertyThrow({
+ getOwnPropertyDescriptor: function(k) { throw "myexn" }
+})
+
+TestGetOwnPropertyThrow({
+ getOwnPropertyDescriptor: function(k) {
+ return this.getOwnPropertyDescriptor2(k)
+ },
+ getOwnPropertyDescriptor2: function(k) { throw "myexn" }
+})
+
+TestGetOwnPropertyThrow({
+ getOwnPropertyDescriptor: function(k) {
+ return {get value() { throw "myexn" }}
+ }
+})
+
+TestGetOwnPropertyThrow(new Proxy({}, {
+ get: function(pr, pk) {
+ return function(k) { throw "myexn" }
+ }
+}))
+
+
+// ---------------------------------------------------------------------------
+// Getters (dot, brackets).
+
+var key
+
+function TestGet(handler) {
+ TestWithProxies(TestGet2, handler)
+}
+
+function TestGet2(create, handler) {
+ var p = create(handler)
+ assertEquals(42, p.a)
+ assertEquals("a", key)
+ assertEquals(42, p["b"])
+ assertEquals("b", key)
+ assertEquals(42, p[99])
+ assertEquals("99", key)
+ assertEquals(42, (function(n) { return p[n] })("c"))
+ assertEquals("c", key)
+ assertEquals(42, (function(n) { return p[n] })(101))
+ assertEquals("101", key)
+
+ var o = Object.create(p, {x: {value: 88}})
+ assertEquals(42, o.a)
+ assertEquals("a", key)
+ assertEquals(42, o["b"])
+ assertEquals("b", key)
+ assertEquals(42, o[99])
+ assertEquals("99", key)
+ assertEquals(88, o.x)
+ assertEquals(88, o["x"])
+ assertEquals(42, (function(n) { return o[n] })("c"))
+ assertEquals("c", key)
+ assertEquals(42, (function(n) { return o[n] })(101))
+ assertEquals("101", key)
+ assertEquals(88, (function(n) { return o[n] })("x"))
+}
+
+TestGet({
+ get(t, k, r) { key = k; return 42 }
+})
+
+TestGet({
+ get(t, k, r) { return this.get2(r, k) },
+ get2(r, k) { key = k; return 42 }
+})
+
+TestGet(new Proxy({}, {
+ get(pt, pk, pr) {
+ return function(t, k, r) { key = k; return 42 }
+ }
+}))
+
+
+// ---------------------------------------------------------------------------
+function TestGetCall(handler) {
+ TestWithProxies(TestGetCall2, handler)
+}
+
+function TestGetCall2(create, handler) {
+ var p = create(handler)
+ assertEquals(55, p.f())
+ assertEquals(55, p["f"]())
+ assertEquals(55, p.f("unused", "arguments"))
+ assertEquals(55, p.f.call(p))
+ assertEquals(55, p["f"].call(p))
+ assertEquals(55, p[101].call(p))
+ assertEquals(55, p.withargs(45, 5))
+ assertEquals(55, p.withargs.call(p, 11, 22))
+ assertEquals(55, (function(n) { return p[n]() })("f"))
+ assertEquals(55, (function(n) { return p[n].call(p) })("f"))
+ assertEquals(55, (function(n) { return p[n](15, 20) })("withargs"))
+ assertEquals(55, (function(n) { return p[n].call(p, 13, 21) })("withargs"))
+ assertEquals("6655", "66" + p) // calls p.toString
+
+ var o = Object.create(p, {g: {value: function(x) { return x + 88 }}})
+ assertEquals(55, o.f())
+ assertEquals(55, o["f"]())
+ assertEquals(55, o.f("unused", "arguments"))
+ assertEquals(55, o.f.call(o))
+ assertEquals(55, o.f.call(p))
+ assertEquals(55, o["f"].call(p))
+ assertEquals(55, o[101].call(p))
+ assertEquals(55, o.withargs(45, 5))
+ assertEquals(55, o.withargs.call(p, 11, 22))
+ assertEquals(90, o.g(2))
+ assertEquals(91, o.g.call(o, 3))
+ assertEquals(92, o.g.call(p, 4))
+ assertEquals(55, (function(n) { return o[n]() })("f"))
+ assertEquals(55, (function(n) { return o[n].call(o) })("f"))
+ assertEquals(55, (function(n) { return o[n](15, 20) })("withargs"))
+ assertEquals(55, (function(n) { return o[n].call(o, 13, 21) })("withargs"))
+ assertEquals(93, (function(n) { return o[n](5) })("g"))
+ assertEquals(94, (function(n) { return o[n].call(o, 6) })("g"))
+ assertEquals(95, (function(n) { return o[n].call(p, 7) })("g"))
+ assertEquals("6655", "66" + o) // calls o.toString
+}
+
+TestGetCall({
+ get(t, k, r) { return () => { return 55 } }
+})
+
+TestGetCall({
+ get(t, k, r) { return this.get2(t, k, r) },
+ get2(t, k, r) { return () => { return 55 } }
+})
+
+TestGetCall({
+ get(t, k, r) {
+ if (k == "gg") {
+ return () => { return 55 }
+ } else if (k == "withargs") {
+ return (n, m) => { return n + m * 2 }
+ } else {
+ return () => { return r.gg() }
+ }
+ }
+})
+
+TestGetCall(new Proxy({}, {
+ get(pt, pk, pr) {
+ return (t, k, r) => { return () => { return 55 } }
+ }
+}))
+
+
+// ---------------------------------------------------------------------------
+function TestGetThrow(handler) {
+ TestWithProxies(TestGetThrow2, handler)
+}
+
+function TestGetThrow2(create, handler) {
+ var p = create(handler)
+ assertThrowsEquals(function(){ p.a }, "myexn")
+ assertThrowsEquals(function(){ p["b"] }, "myexn")
+ assertThrowsEquals(function(){ p[3] }, "myexn")
+ assertThrowsEquals(function(){ (function(n) { p[n] })("c") }, "myexn")
+ assertThrowsEquals(function(){ (function(n) { p[n] })(99) }, "myexn")
+
+ var o = Object.create(p, {x: {value: 88}, '4': {value: 89}})
+ assertThrowsEquals(function(){ o.a }, "myexn")
+ assertThrowsEquals(function(){ o["b"] }, "myexn")
+ assertThrowsEquals(function(){ o[3] }, "myexn")
+ assertThrowsEquals(function(){ (function(n) { o[n] })("c") }, "myexn")
+ assertThrowsEquals(function(){ (function(n) { o[n] })(99) }, "myexn")
+}
+
+TestGetThrow({
+ get(r, k) { throw "myexn" }
+})
+
+TestGetThrow({
+ get(r, k) { return this.get2(r, k) },
+ get2(r, k) { throw "myexn" }
+})
+
+TestGetThrow(new Proxy({}, {
+ get(pr, pk) { throw "myexn" }
+}))
+
+TestGetThrow(new Proxy({}, {
+ get(pr, pk) {
+ return function(r, k) { throw "myexn" }
+ }
+}))
+
+
+// ---------------------------------------------------------------------------
+// Setters.
+
+var key
+var val
+
+function TestSet(handler) {
+ TestWithProxies(TestSet2, handler)
+}
+
+function TestSet2(create, handler) {
+ var p = create(handler)
+ assertEquals(42, p.a = 42)
+ assertEquals("a", key)
+ assertEquals(42, val)
+ assertEquals(43, p["b"] = 43)
+ assertEquals("b", key)
+ assertEquals(43, val)
+ assertEquals(44, p[77] = 44)
+ assertEquals("77", key)
+ assertEquals(44, val)
+
+ assertEquals(45, (function(n) { return p[n] = 45 })("c"))
+ assertEquals("c", key)
+ assertEquals(45, val)
+ assertEquals(46, (function(n) { return p[n] = 46 })(99))
+ assertEquals("99", key)
+ assertEquals(46, val)
+
+ assertEquals(47, p["0"] = 47)
+ assertEquals("0", key)
+ assertEquals(47, val)
+}
+
+TestSet({
+ set: function(r, k, v) { key = k; val = v; return true }
+})
+
+TestSet({
+ set: function(r, k, v) { return this.set2(r, k, v) },
+ set2: function(r, k, v) { key = k; val = v; return true }
+})
+
+TestSet(new Proxy({}, {
+ get(pk, pr) {
+ return (r, k, v) => { key = k; val = v; return true }
+ }
+}))
+
+
+// ---------------------------------------------------------------------------
+function TestSetThrow(handler) {
+ TestWithProxies(TestSetThrow2, handler)
+}
+
+function TestSetThrow2(create, handler) {
+ var p = create(handler)
+ assertThrowsEquals(function(){ p.a = 42 }, "myexn")
+ assertThrowsEquals(function(){ p["b"] = 42 }, "myexn")
+ assertThrowsEquals(function(){ p[22] = 42 }, "myexn")
+ assertThrowsEquals(function(){ (function(n) { p[n] = 45 })("c") }, "myexn")
+ assertThrowsEquals(function(){ (function(n) { p[n] = 46 })(99) }, "myexn")
+}
+
+TestSetThrow({
+ set: function(r, k, v) { throw "myexn" }
+})
+
+TestSetThrow({
+ set: function(r, k, v) { return this.set2(r, k, v) },
+ set2: function(r, k, v) { throw "myexn" }
+})
+
+TestSetThrow({
+ getOwnPropertyDescriptor: function(k) { throw "myexn" },
+ defineProperty: function(k, desc) { key = k; val = desc.value }
+})
+
+TestSetThrow({
+ getOwnPropertyDescriptor: function(k) {
+ return {configurable: true, writable: true}
+ },
+ defineProperty: function(k, desc) { throw "myexn" }
+})
+
+TestSetThrow({
+ getOwnPropertyDescriptor: function(k) {
+ return this.getOwnPropertyDescriptor2(k)
+ },
+ getOwnPropertyDescriptor2: function(k) { throw "myexn" },
+ defineProperty: function(k, desc) { this.defineProperty2(k, desc) },
+ defineProperty2: function(k, desc) { key = k; val = desc.value }
+})
+
+TestSetThrow({
+ getOwnPropertyDescriptor: function(k) {
+ return this.getOwnPropertyDescriptor2(k)
+ },
+ getOwnPropertyDescriptor2: function(k) {
+ return {configurable: true, writable: true}
+ },
+ defineProperty: function(k, desc) { this.defineProperty2(k, desc) },
+ defineProperty2: function(k, desc) { throw "myexn" }
+})
+
+TestSetThrow({
+ getOwnPropertyDescriptor: function(k) { throw "myexn" },
+ defineProperty: function(k, desc) { key = k; val = desc.value }
+})
+
+TestSetThrow({
+ getOwnPropertyDescriptor: function(k) {
+ return {
+ get configurable() { return true },
+ get writable() { return true }
+ }
+ },
+ defineProperty: function(k, desc) { throw "myexn" }
+})
+
+TestSetThrow({
+ getOwnPropertyDescriptor: function(k) { throw "myexn" }
+})
+
+TestSetThrow({
+ getOwnPropertyDescriptor: function(k) { throw "myexn" },
+ defineProperty: function(k, desc) { key = k; val = desc.value }
+})
+
+TestSetThrow(new Proxy({}, {
+ get: function(pr, pk) { throw "myexn" }
+}))
+
+TestSetThrow(new Proxy({}, {
+ get: function(pr, pk) {
+ return function(r, k, v) { throw "myexn" }
+ }
+}))
+
+// ---------------------------------------------------------------------------
+
+// Evil proxy-induced side-effects shouldn't crash.
+TestWithProxies(function(create) {
+ var calls = 0
+ var handler = {
+ getPropertyDescriptor: function() {
+ ++calls
+ return (calls % 2 == 1)
+ ? {get: function() { return 5 }, configurable: true}
+ : {set: function() { return false }, configurable: true}
+ }
+ }
+ var p = create(handler)
+ var o = Object.create(p)
+ // Make proxy prototype property read-only after CanPut check.
+ try { o.x = 4 } catch (e) { assertInstanceof(e, Error) }
+})
+
+TestWithProxies(function(create) {
+ var handler = {
+ getPropertyDescriptor: function() {
+ Object.defineProperty(o, "x", {get: function() { return 5 }});
+ return {set: function() {}}
+ }
+ }
+ var p = create(handler)
+ var o = Object.create(p)
+ // Make object property read-only after CanPut check.
+ try { o.x = 4 } catch (e) { assertInstanceof(e, Error) }
+})
+
+
+// ---------------------------------------------------------------------------
+// Property definition (Object.defineProperty and Object.defineProperties).
+
+var key
+var desc
+
+function TestDefine(handler) {
+ TestWithProxies(TestDefine2, handler)
+}
+
+function TestDefine2(create, handler) {
+ var p = create(handler)
+ assertEquals(p, Object.defineProperty(p, "a", {value: 44}))
+ assertEquals("a", key)
+ assertEquals(1, Object.getOwnPropertyNames(desc).length)
+ assertEquals(44, desc.value)
+
+ assertEquals(p, Object.defineProperty(p, "b", {value: 45, writable: false}))
+ assertEquals("b", key)
+ assertEquals(2, Object.getOwnPropertyNames(desc).length)
+ assertEquals(45, desc.value)
+ assertEquals(false, desc.writable)
+
+ assertEquals(p, Object.defineProperty(p, "c", {value: 46, enumerable: false}))
+ assertEquals("c", key)
+ assertEquals(2, Object.getOwnPropertyNames(desc).length)
+ assertEquals(46, desc.value)
+ assertEquals(false, desc.enumerable)
+
+ assertEquals(p, Object.defineProperty(p, 101, {value: 47, enumerable: false}))
+ assertEquals("101", key)
+ assertEquals(2, Object.getOwnPropertyNames(desc).length)
+ assertEquals(47, desc.value)
+ assertEquals(false, desc.enumerable)
+
+ var attributes = {configurable: true, mine: 66, minetoo: 23}
+ assertEquals(p, Object.defineProperty(p, "d", attributes))
+ assertEquals("d", key);
+ // Modifying the attributes object after the fact should have no effect.
+ attributes.configurable = false
+ attributes.mine = 77
+ delete attributes.minetoo;
+ assertEquals(1, Object.getOwnPropertyNames(desc).length)
+ assertEquals(true, desc.configurable)
+ assertEquals(undefined, desc.mine)
+ assertEquals(undefined, desc.minetoo)
+
+ assertEquals(p, Object.defineProperty(p, "e", {get: function(){ return 5 }}))
+ assertEquals("e", key)
+ assertEquals(1, Object.getOwnPropertyNames(desc).length)
+ assertEquals(5, desc.get())
+
+ assertEquals(p, Object.defineProperty(p, "zzz", {}))
+ assertEquals("zzz", key)
+ assertEquals(0, Object.getOwnPropertyNames(desc).length)
+
+ var props = {
+ '11': {},
+ blub: {get: function() { return true }},
+ '': {get value() { return 20 }},
+ last: {value: 21, configurable: true, mine: "eyes"}
+ }
+ Object.defineProperty(props, "hidden", {value: "hidden", enumerable: false})
+ assertEquals(p, Object.defineProperties(p, props))
+ assertEquals("last", key)
+ assertEquals(2, Object.getOwnPropertyNames(desc).length)
+ assertEquals(21, desc.value)
+ assertEquals(true, desc.configurable)
+ assertEquals(undefined, desc.mine) // Arguably a bug in the spec...
+
+ var props = {bla: {get value() { throw "myexn" }}}
+ assertThrowsEquals(function(){ Object.defineProperties(p, props) }, "myexn")
+}
+
+TestDefine({
+ defineProperty(t, k, d) { key = k; desc = d; return true }
+})
+
+TestDefine({
+ defineProperty(t, k, d) { return this.defineProperty2(k, d) },
+ defineProperty2(k, d) { key = k; desc = d; return true }
+})
+
+
+// ---------------------------------------------------------------------------
+function TestDefineThrow(handler) {
+ TestWithProxies(TestDefineThrow2, handler)
+}
+
+function TestDefineThrow2(create, handler) {
+ var p = create(handler)
+ assertThrowsEquals(() => Object.defineProperty(p, "a", {value: 44}), "myexn")
+ assertThrowsEquals(() => Object.defineProperty(p, 0, {value: 44}), "myexn")
+
+ var d1 = create({
+ get: function(r, k) { throw "myexn" },
+ getOwnPropertyNames: function() { return ["value"] }
+ })
+ assertThrowsEquals(function(){ Object.defineProperty(p, "p", d1) }, "myexn")
+ var d2 = create({
+ get: function(r, k) { return 77 },
+ getOwnPropertyNames: function() { throw "myexn" }
+ })
+ assertThrowsEquals(function(){ Object.defineProperty(p, "p", d2) }, "myexn")
+
+ var props = {bla: {get value() { throw "otherexn" }}}
+ assertThrowsEquals(() => Object.defineProperties(p, props), "otherexn")
+}
+
+TestDefineThrow({
+ defineProperty: function(k, d) { throw "myexn" }
+})
+
+TestDefineThrow({
+ defineProperty: function(k, d) { return this.defineProperty2(k, d) },
+ defineProperty2: function(k, d) { throw "myexn" }
+})
+
+TestDefineThrow(new Proxy({}, {
+ get: function(pr, pk) { throw "myexn" }
+}))
+
+TestDefineThrow(new Proxy({}, {
+ get: function(pr, pk) {
+ return function(k, d) { throw "myexn" }
+ }
+}))
+
+
+
+// ---------------------------------------------------------------------------
+// Property deletion (delete).
+
+var key
+
+function TestDelete(handler) {
+ TestWithProxies(TestDelete2, handler)
+}
+
+function TestDelete2(create, handler) {
+ var p = create(handler)
+ assertEquals(true, delete p.a)
+ assertEquals("a", key)
+ assertEquals(true, delete p["b"])
+ assertEquals("b", key)
+ assertEquals(true, delete p[1])
+ assertEquals("1", key)
+
+ assertEquals(false, delete p.z1)
+ assertEquals("z1", key)
+ assertEquals(false, delete p["z2"])
+ assertEquals("z2", key);
+
+ (function() {
+ "use strict"
+ assertEquals(true, delete p.c)
+ assertEquals("c", key)
+ assertEquals(true, delete p["d"])
+ assertEquals("d", key)
+ assertEquals(true, delete p[2])
+ assertEquals("2", key)
+
+ assertThrows(function(){ delete p.z3 }, TypeError)
+ assertEquals("z3", key)
+ assertThrows(function(){ delete p["z4"] }, TypeError)
+ assertEquals("z4", key)
+ })()
+}
+
+TestDelete({
+ deleteProperty(target, k) { key = k; return k < "z" }
+})
+
+TestDelete({
+ deleteProperty(target, k) { return this.delete2(k) },
+ delete2: function(k) { key = k; return k < "z" }
+})
+
+TestDelete(new Proxy({}, {
+ get(pt, pk, pr) {
+ return (target, k) => { key = k; return k < "z" }
+ }
+}))
+
+
+// ---------------------------------------------------------------------------
+function TestDeleteThrow(handler) {
+ TestWithProxies(TestDeleteThrow2, handler)
+}
+
+function TestDeleteThrow2(create, handler) {
+ var p = create(handler)
+ assertThrowsEquals(function(){ delete p.a }, "myexn")
+ assertThrowsEquals(function(){ delete p["b"] }, "myexn");
+ assertThrowsEquals(function(){ delete p[3] }, "myexn");
+
+ (function() {
+ "use strict"
+ assertThrowsEquals(function(){ delete p.c }, "myexn")
+ assertThrowsEquals(function(){ delete p["d"] }, "myexn")
+ assertThrowsEquals(function(){ delete p[4] }, "myexn");
+ })()
+}
+
+TestDeleteThrow({
+ deleteProperty(t, k) { throw "myexn" }
+})
+
+TestDeleteThrow({
+ deleteProperty(t, k) { return this.delete2(k) },
+ delete2(k) { throw "myexn" }
+})
+
+TestDeleteThrow(new Proxy({}, {
+ get(pt, pk, pr) { throw "myexn" }
+}))
+
+TestDeleteThrow(new Proxy({}, {
+ get(pt, pk, pr) {
+ return (k) => { throw "myexn" }
+ }
+}))
+
+
+// ---------------------------------------------------------------------------
+// Property descriptors (Object.getOwnPropertyDescriptor).
+
+function TestDescriptor(handler) {
+ TestWithProxies(TestDescriptor2, handler)
+}
+
+function TestDescriptor2(create, handler) {
+ var p = create(handler)
+ var descs = [
+ {configurable: true},
+ {value: 34, enumerable: true, configurable: true},
+ {value: 3, writable: false, mine: "eyes", configurable: true},
+ {get value() { return 20 }, get configurable() { return true }},
+ {get: function() { "get" }, set: function() { "set" }, configurable: true}
+ ]
+ for (var i = 0; i < descs.length; ++i) {
+ assertEquals(p, Object.defineProperty(p, i, descs[i]))
+ var desc = Object.getOwnPropertyDescriptor(p, i)
+ for (prop in descs[i]) {
+ // TODO(rossberg): Ignore user attributes as long as the spec isn't
+ // fixed suitably.
+ if (prop != "mine") assertEquals(descs[i][prop], desc[prop])
+ }
+ assertEquals(undefined, Object.getOwnPropertyDescriptor(p, "absent"))
+ }
+}
+
+TestDescriptor({
+ defineProperty(t, k, d) { this["__" + k] = d; return true },
+ getOwnPropertyDescriptor(t, k) { return this["__" + k] }
+})
+
+TestDescriptor({
+ defineProperty(t, k, d) { this["__" + k] = d; return true },
+ getOwnPropertyDescriptor(t, k) {
+ return this.getOwnPropertyDescriptor2(k)
+ },
+ getOwnPropertyDescriptor2: function(k) { return this["__" + k] }
+})
+
+
+// ---------------------------------------------------------------------------
+function TestDescriptorThrow(handler) {
+ TestWithProxies(TestDescriptorThrow2, handler)
+}
+
+function TestDescriptorThrow2(create, handler) {
+ var p = create(handler)
+ assertThrowsEquals(() => Object.getOwnPropertyDescriptor(p, "a"), "myexn")
+}
+
+TestDescriptorThrow({
+ getOwnPropertyDescriptor: function(k) { throw "myexn" }
+})
+
+TestDescriptorThrow({
+ getOwnPropertyDescriptor: function(k) {
+ return this.getOwnPropertyDescriptor2(k)
+ },
+ getOwnPropertyDescriptor2: function(k) { throw "myexn" }
+})
+
+
+
+// ---------------------------------------------------------------------------
+// Comparison.
+
+function TestComparison(eq) {
+ TestWithProxies(TestComparison2, eq)
+}
+
+function TestComparison2(create, eq) {
+ var p1 = create({})
+ var p2 = create({})
+
+ assertTrue(eq(p1, p1))
+ assertTrue(eq(p2, p2))
+ assertTrue(!eq(p1, p2))
+ assertTrue(!eq(p1, {}))
+ assertTrue(!eq({}, p2))
+ assertTrue(!eq({}, {}))
+}
+
+TestComparison(function(o1, o2) { return o1 == o2 })
+TestComparison(function(o1, o2) { return o1 === o2 })
+TestComparison(function(o1, o2) { return !(o1 != o2) })
+TestComparison(function(o1, o2) { return !(o1 !== o2) })
+
+
+
+// Type (typeof).
+
+function TestTypeof() {
+ assertEquals("object", typeof new Proxy({},{}))
+ assertTrue(typeof new Proxy({}, {}) == "object")
+ assertTrue("object" == typeof new Proxy({},{}))
+
+ assertEquals("function", typeof new Proxy(function() {}, {}))
+ assertTrue(typeof new Proxy(function() {}, {}) == "function")
+ assertTrue("function" == typeof new Proxy(function() {},{}))
+}
+
+TestTypeof()
+
+
+
+// ---------------------------------------------------------------------------
+// Membership test (in).
+
+var key
+
+function TestIn(handler) {
+ TestWithProxies(TestIn2, handler)
+}
+
+function TestIn2(create, handler) {
+ var p = create(handler)
+ assertTrue("a" in p)
+ assertEquals("a", key)
+ assertTrue(99 in p)
+ assertEquals("99", key)
+ assertFalse("z" in p)
+ assertEquals("z", key)
+
+ assertEquals(2, ("a" in p) ? 2 : 0)
+ assertEquals(0, !("a" in p) ? 2 : 0)
+ assertEquals(0, ("zzz" in p) ? 2 : 0)
+ assertEquals(2, !("zzz" in p) ? 2 : 0)
+
+ // Test compilation in conditionals.
+ if ("b" in p) {
+ } else {
+ assertTrue(false)
+ }
+ assertEquals("b", key)
+
+ if ("zz" in p) {
+ assertTrue(false)
+ }
+ assertEquals("zz", key)
+
+ if (!("c" in p)) {
+ assertTrue(false)
+ }
+ assertEquals("c", key)
+
+ if (!("zzz" in p)) {
+ } else {
+ assertTrue(false)
+ }
+ assertEquals("zzz", key)
+}
+
+TestIn({
+ has(t, k) { key = k; return k < "z" }
+})
+
+TestIn({
+ has(t, k) { return this.has2(k) },
+ has2(k) { key = k; return k < "z" }
+})
+
+TestIn(new Proxy({},{
+ get(pt, pk, pr) {
+ return (t, k) => { key = k; return k < "z" }
+ }
+}))
+
+
+// ---------------------------------------------------------------------------
+function TestInThrow(handler) {
+ TestWithProxies(TestInThrow2, handler)
+}
+
+function TestInThrow2(create, handler) {
+ var p = create(handler)
+ assertThrowsEquals(function(){ return "a" in p }, "myexn")
+ assertThrowsEquals(function(){ return 99 in p }, "myexn")
+ assertThrowsEquals(function(){ return !("a" in p) }, "myexn")
+ assertThrowsEquals(function(){ return ("a" in p) ? 2 : 3 }, "myexn")
+ assertThrowsEquals(function(){ if ("b" in p) {} }, "myexn")
+ assertThrowsEquals(function(){ if (!("b" in p)) {} }, "myexn")
+ assertThrowsEquals(function(){ if ("zzz" in p) {} }, "myexn")
+}
+
+TestInThrow({
+ has: function(k) { throw "myexn" }
+})
+
+TestInThrow({
+ has: function(k) { return this.has2(k) },
+ has2: function(k) { throw "myexn" }
+})
+
+TestInThrow(new Proxy({},{
+ get: function(pr, pk) { throw "myexn" }
+}))
+
+TestInThrow(new Proxy({},{
+ get: function(pr, pk) {
+ return function(k) { throw "myexn" }
+ }
+}))
+
+
+
+// ---------------------------------------------------------------------------
+// Own Properties (Object.prototype.hasOwnProperty).
+
+var key
+
+function TestHasOwn(handler) {
+ TestWithProxies(TestHasOwn2, handler)
+}
+
+function TestHasOwn2(create, handler) {
+ var p = create(handler)
+ assertTrue(Object.prototype.hasOwnProperty.call(p, "a"))
+ assertEquals("a", key)
+ assertTrue(Object.prototype.hasOwnProperty.call(p, 99))
+ assertEquals("99", key)
+ assertFalse(Object.prototype.hasOwnProperty.call(p, "z"))
+ assertEquals("z", key)
+}
+
+TestHasOwn({
+ getOwnPropertyDescriptor(t, k) {
+ key = k; if (k < "z") return {configurable: true}
+ },
+ has() { assertUnreachable() }
+})
+
+TestHasOwn({
+ getOwnPropertyDescriptor(t, k) { return this.getOwnPropertyDescriptor2(k) },
+ getOwnPropertyDescriptor2(k) {
+ key = k; if (k < "z") return {configurable: true}
+ }
+})
+
+
+
+// ---------------------------------------------------------------------------
+function TestHasOwnThrow(handler) {
+ TestWithProxies(TestHasOwnThrow2, handler)
+}
+
+function TestHasOwnThrow2(create, handler) {
+ var p = create(handler)
+ assertThrowsEquals(function(){ Object.prototype.hasOwnProperty.call(p, "a")},
+ "myexn")
+ assertThrowsEquals(function(){ Object.prototype.hasOwnProperty.call(p, 99)},
+ "myexn")
+}
+
+TestHasOwnThrow({
+ getOwnPropertyDescriptor(t, k) { throw "myexn" }
+})
+
+TestHasOwnThrow({
+ getOwnPropertyDescriptor(t, k) { return this.getOwnPropertyDescriptor2(k) },
+ getOwnPropertyDescriptor2(k) { throw "myexn" }
+});
+
+
+// ---------------------------------------------------------------------------
+// Instanceof (instanceof)
+
+(function TestProxyInstanceof() {
+ var o1 = {}
+ var p1 = new Proxy({}, {})
+ var p2 = new Proxy(o1, {})
+ var p3 = new Proxy(p2, {})
+ var o2 = Object.create(p2)
+
+ var f0 = function() {}
+ f0.prototype = o1
+ var f1 = function() {}
+ f1.prototype = p1
+ var f2 = function() {}
+ f2.prototype = p2
+ var f3 = function() {}
+ f3.prototype = o2
+
+ assertTrue(o1 instanceof Object)
+ assertFalse(o1 instanceof f0)
+ assertFalse(o1 instanceof f1)
+ assertFalse(o1 instanceof f2)
+ assertFalse(o1 instanceof f3)
+ assertTrue(p1 instanceof Object)
+ assertFalse(p1 instanceof f0)
+ assertFalse(p1 instanceof f1)
+ assertFalse(p1 instanceof f2)
+ assertFalse(p1 instanceof f3)
+ assertTrue(p2 instanceof Object)
+ assertFalse(p2 instanceof f0)
+ assertFalse(p2 instanceof f1)
+ assertFalse(p2 instanceof f2)
+ assertFalse(p2 instanceof f3)
+ assertTrue(p3 instanceof Object)
+ assertFalse(p3 instanceof f0)
+ assertFalse(p3 instanceof f1)
+ assertFalse(p3 instanceof f2)
+ assertFalse(p3 instanceof f3)
+ assertTrue(o2 instanceof Object)
+ assertFalse(o2 instanceof f0)
+ assertFalse(o2 instanceof f1)
+ assertTrue(o2 instanceof f2)
+ assertFalse(o2 instanceof f3)
+
+ var f = new Proxy(function() {}, {})
+ assertTrue(f instanceof Function)
+})();
+
+
+(function TestInstanceofProxy() {
+ var o0 = Object.create(null)
+ var o1 = {}
+ var o2 = Object.create(o0)
+ var o3 = Object.create(o1)
+ var o4 = Object.create(o2)
+ var o5 = Object.create(o3)
+
+ function handler(o) {
+ return {
+ get: function(r, p) {
+ // We want to test prototype lookup, so ensure the proxy
+ // offers OrdinaryHasInstance behavior.
+ if (p === Symbol.hasInstance) {
+ return undefined;
+ }
+ return o;
+ }
+ }
+ }
+
+ var f0 = new Proxy(function() {}, handler(o0))
+ var f1 = new Proxy(function() {}, handler(o1))
+ var f2 = new Proxy(function() {}, handler(o2))
+ var f3 = new Proxy(function() {}, handler(o3))
+ var f4 = new Proxy(function() {}, handler(o4))
+ var f5 = new Proxy(function() {}, handler(o4))
+
+ assertFalse(null instanceof f0)
+ assertFalse(o0 instanceof f0)
+ assertFalse(o0 instanceof f1)
+ assertFalse(o0 instanceof f2)
+ assertFalse(o0 instanceof f3)
+ assertFalse(o0 instanceof f4)
+ assertFalse(o0 instanceof f5)
+ assertFalse(o1 instanceof f0)
+ assertFalse(o1 instanceof f1)
+ assertFalse(o1 instanceof f2)
+ assertFalse(o1 instanceof f3)
+ assertFalse(o1 instanceof f4)
+ assertFalse(o1 instanceof f5)
+ assertTrue(o2 instanceof f0)
+ assertFalse(o2 instanceof f1)
+ assertFalse(o2 instanceof f2)
+ assertFalse(o2 instanceof f3)
+ assertFalse(o2 instanceof f4)
+ assertFalse(o2 instanceof f5)
+ assertFalse(o3 instanceof f0)
+ assertTrue(o3 instanceof f1)
+ assertFalse(o3 instanceof f2)
+ assertFalse(o3 instanceof f3)
+ assertFalse(o3 instanceof f4)
+ assertFalse(o3 instanceof f5)
+ assertTrue(o4 instanceof f0)
+ assertFalse(o4 instanceof f1)
+ assertTrue(o4 instanceof f2)
+ assertFalse(o4 instanceof f3)
+ assertFalse(o4 instanceof f4)
+ assertFalse(o4 instanceof f5)
+ assertFalse(o5 instanceof f0)
+ assertTrue(o5 instanceof f1)
+ assertFalse(o5 instanceof f2)
+ assertTrue(o5 instanceof f3)
+ assertFalse(o5 instanceof f4)
+ assertFalse(o5 instanceof f5)
+
+ var f = new Proxy(function() {}, {})
+ var ff = new Proxy(function() {}, handler(Function))
+ assertTrue(f instanceof Function)
+ assertFalse(f instanceof ff)
+})();
+
+
+// ---------------------------------------------------------------------------
+// Prototype (Object.getPrototypeOf, Object.prototype.isPrototypeOf).
+
+(function TestPrototype() {
+ var o1 = {}
+ var p1 = new Proxy({}, {})
+ var p2 = new Proxy(o1, {})
+ var p3 = new Proxy(p2, {})
+ var o2 = Object.create(p3)
+
+ assertSame(Object.getPrototypeOf(o1), Object.prototype)
+ assertSame(Object.getPrototypeOf(p1), Object.prototype)
+ assertSame(Object.getPrototypeOf(p2), Object.prototype)
+ assertSame(Object.getPrototypeOf(p3), Object.prototype)
+ assertSame(Object.getPrototypeOf(o2), p3)
+
+ assertTrue(Object.prototype.isPrototypeOf(o1))
+ assertTrue(Object.prototype.isPrototypeOf(p1))
+ assertTrue(Object.prototype.isPrototypeOf(p2))
+ assertTrue(Object.prototype.isPrototypeOf(p3))
+ assertTrue(Object.prototype.isPrototypeOf(o2))
+ assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o1))
+ assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p1))
+ assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p2))
+ assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p3))
+ assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o2))
+ assertFalse(Object.prototype.isPrototypeOf.call(o1, o1))
+ assertFalse(Object.prototype.isPrototypeOf.call(o1, p1))
+ assertFalse(Object.prototype.isPrototypeOf.call(o1, p2))
+ assertFalse(Object.prototype.isPrototypeOf.call(o1, p3))
+ assertFalse(Object.prototype.isPrototypeOf.call(o1, o2))
+ assertFalse(Object.prototype.isPrototypeOf.call(p1, p1))
+ assertFalse(Object.prototype.isPrototypeOf.call(p1, o1))
+ assertFalse(Object.prototype.isPrototypeOf.call(p1, p2))
+ assertFalse(Object.prototype.isPrototypeOf.call(p1, p3))
+ assertFalse(Object.prototype.isPrototypeOf.call(p1, o2))
+ assertFalse(Object.prototype.isPrototypeOf.call(p2, p1))
+ assertFalse(Object.prototype.isPrototypeOf.call(p2, p2))
+ assertFalse(Object.prototype.isPrototypeOf.call(p2, p3))
+ assertFalse(Object.prototype.isPrototypeOf.call(p2, o2))
+ assertFalse(Object.prototype.isPrototypeOf.call(p3, p2))
+ assertTrue(Object.prototype.isPrototypeOf.call(p3, o2))
+ assertFalse(Object.prototype.isPrototypeOf.call(o2, o1))
+ assertFalse(Object.prototype.isPrototypeOf.call(o2, p1))
+ assertFalse(Object.prototype.isPrototypeOf.call(o2, p2))
+ assertFalse(Object.prototype.isPrototypeOf.call(o2, p3))
+ assertFalse(Object.prototype.isPrototypeOf.call(o2, o2))
+
+ var f = new Proxy(function() {}, {})
+ assertSame(Object.getPrototypeOf(f), Function.prototype)
+ assertTrue(Object.prototype.isPrototypeOf(f))
+ assertTrue(Object.prototype.isPrototypeOf.call(Function.prototype, f))
+})();
+
+
+// ---------------------------------------------------------------------------
+function TestPropertyNamesThrow(handler) {
+ TestWithProxies(TestPropertyNamesThrow2, handler)
+}
+
+function TestPropertyNamesThrow2(create, handler) {
+ var p = create(handler)
+ assertThrowsEquals(function(){ Object.getOwnPropertyNames(p) }, "myexn")
+}
+
+TestPropertyNamesThrow({
+ ownKeys() { throw "myexn" }
+})
+
+TestPropertyNamesThrow({
+ ownKeys() { return this.getOwnPropertyNames2() },
+ getOwnPropertyNames2() { throw "myexn" }
+})
+
+// ---------------------------------------------------------------------------
+
+function TestKeys(names, handler) {
+ var p = new Proxy({}, handler);
+ assertArrayEquals(names, Object.keys(p))
+}
+
+TestKeys([], {
+ ownKeys() { return [] }
+})
+
+TestKeys([], {
+ ownKeys() { return ["a", "zz", " ", "0", "toString"] }
+})
+
+TestKeys(["a", "zz", " ", "0", "toString"], {
+ ownKeys() { return ["a", "zz", " ", "0", "toString"] },
+ getOwnPropertyDescriptor(t, p) {
+ return {configurable: true, enumerable: true}
+ }
+})
+
+TestKeys([], {
+ ownKeys() { return this.keys2() },
+ keys2() { return ["throw", "function "] }
+})
+
+TestKeys(["throw", "function "], {
+ ownKeys() { return this.keys2() },
+ keys2() { return ["throw", "function "] },
+ getOwnPropertyDescriptor(t, p) {
+ return {configurable: true, enumerable: true}
+ }
+})
+
+TestKeys(["a", "0"], {
+ ownKeys() { return ["a", "23", "zz", "", "0"] },
+ getOwnPropertyDescriptor(t, k) {
+ return k == "" ?
+ undefined :
+ { configurable: true, enumerable: k.length == 1}
+ }
+})
+
+TestKeys(["23", "zz", ""], {
+ ownKeys() { return this.getOwnPropertyNames2() },
+ getOwnPropertyNames2() { return ["a", "23", "zz", "", "0"] },
+ getOwnPropertyDescriptor(t, k) {
+ return this.getOwnPropertyDescriptor2(k)
+ },
+ getOwnPropertyDescriptor2(k) {
+ return {configurable: true, enumerable: k.length != 1 }
+ }
+})
+
+TestKeys([], {
+ get ownKeys() {
+ return function() { return ["a", "b", "c"] }
+ },
+ getOwnPropertyDescriptor: function(k) { return {configurable: true} }
+})
+
+
+// ---------------------------------------------------------------------------
+function TestKeysThrow(handler) {
+ TestWithProxies(TestKeysThrow2, handler)
+}
+
+function TestKeysThrow2(create, handler) {
+ var p = create(handler);
+ assertThrowsEquals(function(){ Object.keys(p) }, "myexn");
+}
+
+TestKeysThrow({
+ ownKeys() { throw "myexn" }
+})
+
+TestKeysThrow({
+ ownKeys() { return this.keys2() },
+ keys2() { throw "myexn" }
+})
+
+TestKeysThrow({
+ ownKeys() { return ['1'] },
+ getOwnPropertyDescriptor: function() { throw "myexn" },
+})
+
+TestKeysThrow({
+ ownKeys() { return this.getOwnPropertyNames2() },
+ getOwnPropertyNames2() { return ['1', '2'] },
+ getOwnPropertyDescriptor(k) {
+ return this.getOwnPropertyDescriptor2(k)
+ },
+ getOwnPropertyDescriptor2(k) { throw "myexn" }
+})
+
+TestKeysThrow({
+ get ownKeys() { throw "myexn" }
+})
+
+TestKeysThrow({
+ get ownKeys() {
+ return function() { throw "myexn" }
+ },
+})
+
+TestKeysThrow({
+ get ownKeys() {
+ return function() { return ['1', '2'] }
+ },
+ getOwnPropertyDescriptor(k) { throw "myexn" }
+})
+
+
+
+// ---------------------------------------------------------------------------
+// String conversion (Object.prototype.toString,
+// Object.prototype.toLocaleString,
+// Function.prototype.toString)
+
+var key
+
+function TestToString(handler) {
+ var p = new Proxy({}, handler)
+ key = ""
+ assertEquals("[object Object]", Object.prototype.toString.call(p))
+ assertEquals(Symbol.toStringTag, key)
+ assertEquals("my_proxy", Object.prototype.toLocaleString.call(p))
+ assertEquals("toString", key)
+
+ var f = new Proxy(function() {}, handler)
+ key = ""
+ assertEquals("[object Function]", Object.prototype.toString.call(f))
+ assertEquals(Symbol.toStringTag, key)
+ assertEquals("my_proxy", Object.prototype.toLocaleString.call(f))
+ assertEquals("toString", key)
+ assertThrows(function(){ Function.prototype.toString.call(f) })
+
+ var o = Object.create(p)
+ key = ""
+ assertEquals("[object Object]", Object.prototype.toString.call(o))
+ assertEquals(Symbol.toStringTag, key)
+ assertEquals("my_proxy", Object.prototype.toLocaleString.call(o))
+ assertEquals("toString", key)
+}
+
+TestToString({
+ get: function(r, k) { key = k; return function() { return "my_proxy" } }
+})
+
+TestToString({
+ get: function(r, k) { return this.get2(r, k) },
+ get2: function(r, k) { key = k; return function() { return "my_proxy" } }
+})
+
+TestToString(new Proxy({}, {
+ get: function(pr, pk) {
+ return function(r, k) { key = k; return function() { return "my_proxy" } }
+ }
+}))
+
+
+function TestToStringThrow(handler) {
+ var p = new Proxy({}, handler)
+ assertThrowsEquals(() => Object.prototype.toString.call(p), "myexn")
+ assertThrowsEquals(() => Object.prototype.toLocaleString.call(p), "myexn")
+
+ var f = new Proxy(function(){}, handler)
+ assertThrowsEquals(() => Object.prototype.toString.call(f), "myexn")
+ assertThrowsEquals(() => Object.prototype.toLocaleString.call(f), "myexn")
+
+ var o = Object.create(p)
+ assertThrowsEquals(() => Object.prototype.toString.call(o), "myexn")
+ assertThrowsEquals(() => Object.prototype.toLocaleString.call(o), "myexn")
+}
+
+TestToStringThrow({
+ get: function(r, k) { throw "myexn" }
+})
+
+TestToStringThrow({
+ get: function(r, k) { return this.get2(r, k) },
+ get2: function(r, k) { throw "myexn" }
+})
+
+TestToStringThrow(new Proxy({}, {
+ get: function(pr, pk) { throw "myexn" }
+}))
+
+TestToStringThrow(new Proxy({}, {
+ get: function(pr, pk) {
+ return function(r, k) { throw "myexn" }
+ }
+}))
+
+
+// ---------------------------------------------------------------------------
+// Value conversion (Object.prototype.toValue)
+
+function TestValueOf(handler) {
+ TestWithProxies(TestValueOf2, handler)
+}
+
+function TestValueOf2(create, handler) {
+ var p = create(handler)
+ assertSame(p, Object.prototype.valueOf.call(p))
+}
+
+TestValueOf({})
+
+
+
+// ---------------------------------------------------------------------------
+// Enumerability (Object.prototype.propertyIsEnumerable)
+
+var key
+
+function TestIsEnumerable(handler) {
+ TestWithProxies(TestIsEnumerable2, handler)
+}
+
+function TestIsEnumerable2(create, handler) {
+ var p = create(handler)
+ assertTrue(Object.prototype.propertyIsEnumerable.call(p, "a"))
+ assertEquals("a", key)
+ assertTrue(Object.prototype.propertyIsEnumerable.call(p, 2))
+ assertEquals("2", key)
+ assertFalse(Object.prototype.propertyIsEnumerable.call(p, "z"))
+ assertEquals("z", key)
+
+ var o = Object.create(p)
+ key = ""
+ assertFalse(Object.prototype.propertyIsEnumerable.call(o, "a"))
+ assertEquals("", key) // trap not invoked
+}
+
+TestIsEnumerable({
+ getOwnPropertyDescriptor(t, k) {
+ key = k;
+ return {enumerable: k < "z", configurable: true}
+ },
+})
+
+TestIsEnumerable({
+ getOwnPropertyDescriptor: function(t, k) {
+ return this.getOwnPropertyDescriptor2(k)
+ },
+ getOwnPropertyDescriptor2: function(k) {
+ key = k;
+ return {enumerable: k < "z", configurable: true}
+ },
+})
+
+TestIsEnumerable({
+ getOwnPropertyDescriptor: function(t, k) {
+ key = k;
+ return {get enumerable() { return k < "z" }, configurable: true}
+ },
+})
+
+TestIsEnumerable(new Proxy({}, {
+ get: function(pt, pk, pr) {
+ return function(t, k) {
+ key = k;
+ return {enumerable: k < "z", configurable: true}
+ }
+ }
+}))
+
+
+// ---------------------------------------------------------------------------
+function TestIsEnumerableThrow(handler) {
+ TestWithProxies(TestIsEnumerableThrow2, handler)
+}
+
+function TestIsEnumerableThrow2(create, handler) {
+ var p = create(handler)
+ assertThrowsEquals(() => Object.prototype.propertyIsEnumerable.call(p, "a"),
+ "myexn")
+ assertThrowsEquals(() => Object.prototype.propertyIsEnumerable.call(p, 11),
+ "myexn")
+}
+
+TestIsEnumerableThrow({
+ getOwnPropertyDescriptor: function(k) { throw "myexn" }
+})
+
+TestIsEnumerableThrow({
+ getOwnPropertyDescriptor: function(k) {
+ return this.getOwnPropertyDescriptor2(k)
+ },
+ getOwnPropertyDescriptor2: function(k) { throw "myexn" }
+})
+
+TestIsEnumerableThrow({
+ getOwnPropertyDescriptor: function(k) {
+ return {get enumerable() { throw "myexn" }, configurable: true}
+ },
+})
+
+TestIsEnumerableThrow(new Proxy({}, {
+ get: function(pr, pk) { throw "myexn" }
+}))
+
+TestIsEnumerableThrow(new Proxy({}, {
+ get: function(pr, pk) {
+ return function(k) { throw "myexn" }
+ }
+}));
+
+
+
+// ---------------------------------------------------------------------------
+// Constructor functions with proxy prototypes.
+
+(function TestConstructorWithProxyPrototype() {
+ TestWithProxies(TestConstructorWithProxyPrototype2, {})
+})();
+
+function TestConstructorWithProxyPrototype2(create, handler) {
+ function C() {};
+ C.prototype = create(handler);
+
+ var o = new C;
+ assertSame(C.prototype, Object.getPrototypeOf(o));
+};
+
+
+(function TestOptWithProxyPrototype() {
+ var handler = {
+ get(t, k) {
+ return 10;
+ }
+ };
+
+ function C() {};
+ C.prototype = new Proxy({}, handler);
+ var o = new C();
+
+ function f() {
+ return o.x;
+ }
+ assertEquals(10, f());
+ assertEquals(10, f());
+ %OptimizeFunctionOnNextCall(f);
+ assertEquals(10, f());
+})();
diff --git a/test/mjsunit/es6/reflect-apply.js b/test/mjsunit/es6/reflect-apply.js
new file mode 100644
index 0000000..fa38013
--- /dev/null
+++ b/test/mjsunit/es6/reflect-apply.js
@@ -0,0 +1,210 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+(function testReflectApplyArity() {
+ assertEquals(3, Reflect.apply.length);
+})();
+
+
+(function testReflectApplyNonConstructor() {
+ assertThrows(function() {
+ new Reflect.apply(function(){}, null, []);
+ }, TypeError);
+})();
+
+
+(function testAppliedReceiverSloppy() {
+ function returnThis() { return this; }
+ var receiver = {};
+
+ assertSame(this, Reflect.apply(returnThis, void 0, []));
+ assertSame(this, Reflect.apply(returnThis, null, []));
+ assertSame(this, Reflect.apply(returnThis, this, []));
+ assertSame(receiver, Reflect.apply(returnThis, receiver, []));
+
+ // Wrap JS values
+ assertSame(String.prototype,
+ Object.getPrototypeOf(Reflect.apply(returnThis, "str", [])));
+ assertSame(Number.prototype,
+ Object.getPrototypeOf(Reflect.apply(returnThis, 123, [])));
+ assertSame(Boolean.prototype,
+ Object.getPrototypeOf(Reflect.apply(returnThis, true, [])));
+ assertSame(Symbol.prototype,
+ Object.getPrototypeOf(
+ Reflect.apply(returnThis, Symbol("test"), [])));
+})();
+
+
+(function testAppliedReceiverStrict() {
+ function returnThis() { 'use strict'; return this; }
+ var receiver = {};
+
+ assertSame(void 0, Reflect.apply(returnThis, void 0, []));
+ assertSame(this, Reflect.apply(returnThis, this, []));
+ assertSame(receiver, Reflect.apply(returnThis, receiver, []));
+
+ // Don't wrap value types
+ var regexp = /123/;
+ var symbol = Symbol("test");
+ assertSame("str", Reflect.apply(returnThis, "str", []));
+ assertSame(123, Reflect.apply(returnThis, 123, []));
+ assertSame(true, Reflect.apply(returnThis, true, []));
+ assertSame(regexp, Reflect.apply(returnThis, regexp, []));
+ assertSame(symbol, Reflect.apply(returnThis, symbol, []));
+})();
+
+
+(function testAppliedArgumentsLength() {
+ function returnLengthStrict() { 'use strict'; return arguments.length; }
+ function returnLengthSloppy() { return arguments.length; }
+
+ assertEquals(0, Reflect.apply(returnLengthStrict, this, []));
+ assertEquals(0, Reflect.apply(returnLengthSloppy, this, []));
+ assertEquals(0, Reflect.apply(returnLengthStrict, this, {}));
+ assertEquals(0, Reflect.apply(returnLengthSloppy, this, {}));
+
+ for (var i = 0; i < 256; ++i) {
+ assertEquals(i, Reflect.apply(returnLengthStrict, this, new Array(i)));
+ assertEquals(i, Reflect.apply(returnLengthSloppy, this, new Array(i)));
+ assertEquals(i, Reflect.apply(returnLengthStrict, this, { length: i }));
+ assertEquals(i, Reflect.apply(returnLengthSloppy, this, { length: i }));
+ }
+})();
+
+
+(function testAppliedArgumentsLengthThrows() {
+ function noopStrict() { 'use strict'; }
+ function noopSloppy() { }
+ function MyError() {}
+
+ var argsList = {};
+ Object.defineProperty(argsList, "length", {
+ get: function() { throw new MyError(); }
+ });
+
+ assertThrows(function() {
+ Reflect.apply(noopStrict, this, argsList);
+ }, MyError);
+
+ assertThrows(function() {
+ Reflect.apply(noopSloppy, this, argsList);
+ }, MyError);
+})();
+
+
+(function testAppliedArgumentsElementThrows() {
+ function noopStrict() { 'use strict'; }
+ function noopSloppy() { }
+ function MyError() {}
+
+ var argsList = { length: 1 };
+ Object.defineProperty(argsList, "0", {
+ get: function() { throw new MyError(); }
+ });
+
+ assertThrows(function() {
+ Reflect.apply(noopStrict, this, argsList);
+ }, MyError);
+
+ assertThrows(function() {
+ Reflect.apply(noopSloppy, this, argsList);
+ }, MyError);
+})();
+
+
+(function testAppliedNonFunctionStrict() {
+ 'use strict';
+ assertThrows(function() { Reflect.apply(void 0); }, TypeError);
+ assertThrows(function() { Reflect.apply(null); }, TypeError);
+ assertThrows(function() { Reflect.apply(123); }, TypeError);
+ assertThrows(function() { Reflect.apply("str"); }, TypeError);
+ assertThrows(function() { Reflect.apply(Symbol("x")); }, TypeError);
+ assertThrows(function() { Reflect.apply(/123/); }, TypeError);
+ assertThrows(function() { Reflect.apply(NaN); }, TypeError);
+ assertThrows(function() { Reflect.apply({}); }, TypeError);
+ assertThrows(function() { Reflect.apply([]); }, TypeError);
+})();
+
+
+(function testAppliedNonFunctionSloppy() {
+ assertThrows(function() { Reflect.apply(void 0); }, TypeError);
+ assertThrows(function() { Reflect.apply(null); }, TypeError);
+ assertThrows(function() { Reflect.apply(123); }, TypeError);
+ assertThrows(function() { Reflect.apply("str"); }, TypeError);
+ assertThrows(function() { Reflect.apply(Symbol("x")); }, TypeError);
+ assertThrows(function() { Reflect.apply(/123/); }, TypeError);
+ assertThrows(function() { Reflect.apply(NaN); }, TypeError);
+ assertThrows(function() { Reflect.apply({}); }, TypeError);
+ assertThrows(function() { Reflect.apply([]); }, TypeError);
+})();
+
+
+(function testAppliedArgumentsNonList() {
+ function noopStrict() { 'use strict'; }
+ function noopSloppy() {}
+ var R = void 0;
+ assertThrows(function() { Reflect.apply(noopStrict, R, null); }, TypeError);
+ assertThrows(function() { Reflect.apply(noopSloppy, R, null); }, TypeError);
+ assertThrows(function() { Reflect.apply(noopStrict, R, 1); }, TypeError);
+ assertThrows(function() { Reflect.apply(noopSloppy, R, 1); }, TypeError);
+ assertThrows(function() { Reflect.apply(noopStrict, R, "BAD"); }, TypeError);
+ assertThrows(function() { Reflect.apply(noopSloppy, R, "BAD"); }, TypeError);
+ assertThrows(function() { Reflect.apply(noopStrict, R, true); }, TypeError);
+ assertThrows(function() { Reflect.apply(noopSloppy, R, true); }, TypeError);
+ var sym = Symbol("x");
+ assertThrows(function() { Reflect.apply(noopStrict, R, sym); }, TypeError);
+ assertThrows(function() { Reflect.apply(noopSloppy, R, sym); }, TypeError);
+})();
+
+
+(function testAppliedArgumentValue() {
+ function returnFirstStrict(a) { 'use strict'; return a; }
+ function returnFirstSloppy(a) { return a; }
+ function returnLastStrict(a) {
+ 'use strict'; return arguments[arguments.length - 1]; }
+ function returnLastSloppy(a) { return arguments[arguments.length - 1]; }
+ function returnSumStrict() {
+ 'use strict';
+ var sum = arguments[0];
+ for (var i = 1; i < arguments.length; ++i) {
+ sum += arguments[i];
+ }
+ return sum;
+ }
+ function returnSumSloppy() {
+ var sum = arguments[0];
+ for (var i = 1; i < arguments.length; ++i) {
+ sum += arguments[i];
+ }
+ return sum;
+ }
+
+ assertEquals("OK!", Reflect.apply(returnFirstStrict, this, ["OK!"]));
+ assertEquals("OK!", Reflect.apply(returnFirstSloppy, this, ["OK!"]));
+ assertEquals("OK!", Reflect.apply(returnFirstStrict, this,
+ { 0: "OK!", length: 1 }));
+ assertEquals("OK!", Reflect.apply(returnFirstSloppy, this,
+ { 0: "OK!", length: 1 }));
+ assertEquals("OK!", Reflect.apply(returnLastStrict, this,
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, "OK!"]));
+ assertEquals("OK!", Reflect.apply(returnLastSloppy, this,
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, "OK!"]));
+ assertEquals("OK!", Reflect.apply(returnLastStrict, this,
+ { 9: "OK!", length: 10 }));
+ assertEquals("OK!", Reflect.apply(returnLastSloppy, this,
+ { 9: "OK!", length: 10 }));
+ assertEquals("TEST", Reflect.apply(returnSumStrict, this,
+ ["T", "E", "S", "T"]));
+ assertEquals("TEST!!", Reflect.apply(returnSumStrict, this,
+ ["T", "E", "S", "T", "!", "!"]));
+ assertEquals(10, Reflect.apply(returnSumStrict, this,
+ { 0: 1, 1: 2, 2: 3, 3: 4, length: 4 }));
+ assertEquals("TEST", Reflect.apply(returnSumSloppy, this,
+ ["T", "E", "S", "T"]));
+ assertEquals("TEST!!", Reflect.apply(returnSumSloppy, this,
+ ["T", "E", "S", "T", "!", "!"]));
+ assertEquals(10, Reflect.apply(returnSumSloppy, this,
+ { 0: 1, 1: 2, 2: 3, 3: 4, length: 4 }));
+})();
diff --git a/test/mjsunit/es6/reflect-construct.js b/test/mjsunit/es6/reflect-construct.js
new file mode 100644
index 0000000..b37f876
--- /dev/null
+++ b/test/mjsunit/es6/reflect-construct.js
@@ -0,0 +1,376 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+(function testReflectConstructArity() {
+ assertEquals(2, Reflect.construct.length);
+})();
+
+
+(function testReflectConstructNonConstructor() {
+ assertThrows(function() {
+ new Reflect.construct(function(){}, []);
+ }, TypeError);
+})();
+
+
+(function testReflectConstructBasic() {
+ function Constructor() { "use strict"; }
+ assertInstanceof(Reflect.construct(Constructor, []), Constructor);
+})();
+
+
+(function testReflectConstructBasicSloppy() {
+ function Constructor() {}
+ assertInstanceof(Reflect.construct(Constructor, []), Constructor);
+})();
+
+
+(function testReflectConstructReturnSomethingElseStrict() {
+ var R = {};
+ function Constructor() { "use strict"; return R; }
+ assertSame(R, Reflect.construct(Constructor, []));
+})();
+
+
+(function testReflectConstructReturnSomethingElseSloppy() {
+ var R = {};
+ function Constructor() { return R; }
+ assertSame(R, Reflect.construct(Constructor, []));
+})();
+
+
+(function testReflectConstructNewTargetStrict() {
+ "use strict";
+ function Constructor() { this[9] = 1; }
+ var O = Reflect.construct(Constructor, [], Array);
+ assertEquals(1, O[9]);
+ // Ordinary object with Array.prototype --- no exotic Array magic
+ assertFalse(Array.isArray(O));
+ assertEquals(0, O.length);
+ assertSame(Array.prototype, Object.getPrototypeOf(O));
+})();
+
+
+(function testReflectConstructNewTargetSloppy() {
+ function Constructor() { this[9] = 1; }
+ var O = Reflect.construct(Constructor, [], Array);
+ assertEquals(1, O[9]);
+ // Ordinary object with Array.prototype --- no exotic Array magic
+ assertFalse(Array.isArray(O));
+ assertEquals(0, O.length);
+ assertSame(Array.prototype, Object.getPrototypeOf(O));
+})();
+
+
+(function testReflectConstructNewTargetStrict2() {
+ "use strict";
+ function Constructor() { this[9] = 1; }
+ Constructor.prototype.add = function(x) {
+ this[this.length] = x; return this;
+ }
+ var O = Reflect.construct(Array, [1, 2, 3], Constructor);
+ // Exotic Array object with Constructor.prototype
+ assertTrue(Array.isArray(O));
+ assertSame(Constructor.prototype, Object.getPrototypeOf(O));
+ assertFalse(O instanceof Array);
+ assertEquals(3, O.length);
+ assertEquals(undefined, O[9]);
+ assertSame(O, O.add(4));
+ assertEquals(4, O.length);
+ assertEquals(4, O[3]);
+})();
+
+
+(function testReflectConstructNewTargetSloppy2() {
+ function Constructor() { this[9] = 1; }
+ Constructor.prototype.add = function(x) {
+ this[this.length] = x; return this;
+ }
+ var O = Reflect.construct(Array, [1, 2, 3], Constructor);
+ // Exotic Array object with Constructor.prototype
+ assertTrue(Array.isArray(O));
+ assertSame(Constructor.prototype, Object.getPrototypeOf(O));
+ assertFalse(O instanceof Array);
+ assertEquals(3, O.length);
+ assertEquals(undefined, O[9]);
+ assertSame(O, O.add(4));
+ assertEquals(4, O.length);
+ assertEquals(4, O[3]);
+})();
+
+
+(function testReflectConstructNewTargetStrict3() {
+ "use strict";
+ function A() {}
+ function B() {}
+ var O = Reflect.construct(A, [], B);
+ // TODO(caitp): bug: newTarget prototype is not used if it is not
+ // explicitly set.
+ //assertSame(B.prototype, Object.getPrototypeOf(O));
+})();
+
+
+(function testReflectConstructNewTargetSloppy3() {
+ function A() {}
+ function B() {}
+ var O = Reflect.construct(A, [], B);
+ // TODO(caitp): bug: newTarget prototype is not used if it is not
+ // explicitly set.
+ //assertSame(B.prototype, Object.getPrototypeOf(O));
+})();
+
+
+(function testAppliedArgumentsLength() {
+ function lengthStrict() { 'use strict'; this.a = arguments.length; }
+ function lengthSloppy() { this.a = arguments.length; }
+
+ assertEquals(0, Reflect.construct(lengthStrict, []).a);
+ assertEquals(0, Reflect.construct(lengthSloppy, []).a);
+ assertEquals(0, Reflect.construct(lengthStrict, {}).a);
+ assertEquals(0, Reflect.construct(lengthSloppy, {}).a);
+
+ for (var i = 0; i < 256; ++i) {
+ assertEquals(i, Reflect.construct(lengthStrict, new Array(i)).a);
+ assertEquals(i, Reflect.construct(lengthSloppy, new Array(i)).a);
+ assertEquals(i, Reflect.construct(lengthStrict, { length: i }).a);
+ assertEquals(i, Reflect.construct(lengthSloppy, { length: i }).a);
+ }
+})();
+
+
+(function testAppliedArgumentsLengthThrows() {
+ function noopStrict() { 'use strict'; }
+ function noopSloppy() { }
+ function MyError() {}
+
+ var argsList = {};
+ Object.defineProperty(argsList, "length", {
+ get: function() { throw new MyError(); }
+ });
+
+ assertThrows(function() {
+ Reflect.construct(noopStrict, argsList);
+ }, MyError);
+
+ assertThrows(function() {
+ Reflect.construct(noopSloppy, argsList);
+ }, MyError);
+})();
+
+
+(function testAppliedArgumentsElementThrows() {
+ function noopStrict() { 'use strict'; }
+ function noopSloppy() { }
+ function MyError() {}
+
+ var argsList = { length: 1 };
+ Object.defineProperty(argsList, "0", {
+ get: function() { throw new MyError(); }
+ });
+
+ assertThrows(function() {
+ Reflect.construct(noopStrict, argsList);
+ }, MyError);
+
+ assertThrows(function() {
+ Reflect.construct(noopSloppy, argsList);
+ }, MyError);
+})();
+
+
+(function testAppliedNonFunctionStrict() {
+ 'use strict';
+ assertThrows(function() { Reflect.construct(void 0, []); }, TypeError);
+ assertThrows(function() { Reflect.construct(null, []); }, TypeError);
+ assertThrows(function() { Reflect.construct(123, []); }, TypeError);
+ assertThrows(function() { Reflect.construct("str", []); }, TypeError);
+ assertThrows(function() { Reflect.construct(Symbol("x"), []); }, TypeError);
+ assertThrows(function() { Reflect.construct(/123/, []); }, TypeError);
+ assertThrows(function() { Reflect.construct(NaN, []); }, TypeError);
+ assertThrows(function() { Reflect.construct({}, []); }, TypeError);
+ assertThrows(function() { Reflect.construct([], []); }, TypeError);
+})();
+
+
+(function testAppliedNonFunctionSloppy() {
+ assertThrows(function() { Reflect.construct(void 0, []); }, TypeError);
+ assertThrows(function() { Reflect.construct(null, []); }, TypeError);
+ assertThrows(function() { Reflect.construct(123, []); }, TypeError);
+ assertThrows(function() { Reflect.construct("str", []); }, TypeError);
+ assertThrows(function() { Reflect.construct(Symbol("x"), []); }, TypeError);
+ assertThrows(function() { Reflect.construct(/123/, []); }, TypeError);
+ assertThrows(function() { Reflect.construct(NaN, []); }, TypeError);
+ assertThrows(function() { Reflect.construct({}, []); }, TypeError);
+ assertThrows(function() { Reflect.construct([], []); }, TypeError);
+})();
+
+
+(function testAppliedArgumentsNonList() {
+ function noopStrict() { 'use strict'; }
+ function noopSloppy() {}
+ assertThrows(function() { Reflect.construct(noopStrict, null); }, TypeError);
+ assertThrows(function() { Reflect.construct(noopSloppy, null); }, TypeError);
+ assertThrows(function() { Reflect.construct(noopStrict, 1); }, TypeError);
+ assertThrows(function() { Reflect.construct(noopSloppy, 1); }, TypeError);
+ assertThrows(function() { Reflect.construct(noopStrict, "BAD"); }, TypeError);
+ assertThrows(function() { Reflect.construct(noopSloppy, "BAD"); }, TypeError);
+ assertThrows(function() { Reflect.construct(noopStrict, true); }, TypeError);
+ assertThrows(function() { Reflect.construct(noopSloppy, true); }, TypeError);
+ var sym = Symbol("x");
+ assertThrows(function() { Reflect.construct(noopStrict, sym); }, TypeError);
+ assertThrows(function() { Reflect.construct(noopSloppy, sym); }, TypeError);
+})();
+
+
+(function testAppliedArgumentValue() {
+ function firstStrict(a) { 'use strict'; this.a = a; }
+ function firstSloppy(a) { this.a = a; }
+ function lastStrict(a) {
+ 'use strict'; this.a = arguments[arguments.length - 1]; }
+ function lastSloppy(a) { this.a = arguments[arguments.length - 1]; }
+ function sumStrict() {
+ 'use strict';
+ var sum = arguments[0];
+ for (var i = 1; i < arguments.length; ++i) {
+ sum += arguments[i];
+ }
+ this.a = sum;
+ }
+ function sumSloppy() {
+ var sum = arguments[0];
+ for (var i = 1; i < arguments.length; ++i) {
+ sum += arguments[i];
+ }
+ this.a = sum;
+ }
+
+ assertEquals("OK!", Reflect.construct(firstStrict, ["OK!"]).a);
+ assertEquals("OK!", Reflect.construct(firstSloppy, ["OK!"]).a);
+ assertEquals("OK!", Reflect.construct(firstStrict,
+ { 0: "OK!", length: 1 }).a);
+ assertEquals("OK!", Reflect.construct(firstSloppy,
+ { 0: "OK!", length: 1 }).a);
+ assertEquals("OK!", Reflect.construct(lastStrict,
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, "OK!"]).a);
+ assertEquals("OK!", Reflect.construct(lastSloppy,
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, "OK!"]).a);
+ assertEquals("OK!", Reflect.construct(lastStrict,
+ { 9: "OK!", length: 10 }).a);
+ assertEquals("OK!", Reflect.construct(lastSloppy,
+ { 9: "OK!", length: 10 }).a);
+ assertEquals("TEST", Reflect.construct(sumStrict,
+ ["T", "E", "S", "T"]).a);
+ assertEquals("TEST!!", Reflect.construct(sumStrict,
+ ["T", "E", "S", "T", "!", "!"]).a);
+ assertEquals(10, Reflect.construct(sumStrict,
+ { 0: 1, 1: 2, 2: 3, 3: 4, length: 4 }).a);
+ assertEquals("TEST", Reflect.construct(sumSloppy,
+ ["T", "E", "S", "T"]).a);
+ assertEquals("TEST!!", Reflect.construct(sumSloppy,
+ ["T", "E", "S", "T", "!", "!"]).a);
+ assertEquals(10, Reflect.construct(sumSloppy,
+ { 0: 1, 1: 2, 2: 3, 3: 4, length: 4 }).a);
+})();
+
+(function() {
+ function* f() { yield 1; yield 2; }
+ function* g() { yield 3; yield 4; }
+ assertThrows(()=>Reflect.construct(f, [], g));
+})();
+
+(function () {
+ var realm1 = Realm.create();
+ var realm2 = Realm.create();
+
+ var well_known_intrinsic_constructors = [
+ "Array",
+ "ArrayBuffer",
+ "Boolean",
+ ["DataView", [new ArrayBuffer()]],
+ "Date",
+ "Error",
+ "EvalError",
+ "Float32Array",
+ "Float64Array",
+ ["Function", ["return 153;"]],
+ ["Function", ["'use strict'; return 153;"]],
+ ["Function", ["'use strong'; return 153;"]],
+ ["((function*(){}).constructor)", ["yield 153;"]], // GeneratorFunction
+ ["((function*(){}).constructor)", ["'use strict'; yield 153;"]],
+ ["((function*(){}).constructor)", ["'use strong'; yield 153;"]],
+ "Int8Array",
+ "Int16Array",
+ "Int32Array",
+ "Map",
+ "Number",
+ "Object",
+ ["Promise", [(resolve, reject)=>{}]],
+ "RangeError",
+ "ReferenceError",
+ "RegExp",
+ "Set",
+ "String",
+ "SyntaxError",
+ // %TypedArray%?
+ "TypeError",
+ "Uint8Array",
+ "Uint8ClampedArray",
+ "Uint16Array",
+ "Uint32Array",
+ "URIError",
+ "WeakMap",
+ "WeakSet"
+ ];
+
+ function getname(v) {
+ return typeof v === "string" ? v : v[0];
+ }
+
+ function getargs(v) {
+ return typeof v === "string" ? [] : v[1];
+ }
+
+ function test_intrinsic_prototype(name) {
+ var own = Realm.eval(realm1, name);
+
+ // Ensure that constructor.prototype is non-writable, non-configurable.
+ var desc = Object.getOwnPropertyDescriptor(own, "prototype");
+ assertFalse(desc.configurable, name);
+ assertFalse(desc.writable, name);
+ }
+
+ for (var intrinsic of well_known_intrinsic_constructors) {
+ test_intrinsic_prototype(getname(intrinsic));
+ }
+
+ function function_with_non_instance_prototype(realm) {
+ var f = Realm.eval(realm, "(function(){})");
+ f.prototype = 1;
+ return f;
+ }
+
+ function test_intrinsic_default(realm, name, args, convert) {
+ var own = Realm.eval(realm1, name);
+ var other = Realm.eval(realm, name);
+ var o = Reflect.construct(
+ convert(own), args, function_with_non_instance_prototype(realm));
+
+ // Ensure the intrisicDefaultProto is fetched from the correct realm.
+ assertTrue(realm == realm1 || o.__proto__ !== own.prototype, [...arguments]);
+ assertTrue(o.__proto__ === other.prototype, [...arguments]);
+ }
+
+ function test_all(test, convert) {
+ for (var intrinsic of well_known_intrinsic_constructors) {
+ for (var realm of [realm1, realm2]) {
+ test(realm, getname(intrinsic), getargs(intrinsic), convert);
+ }
+ }
+ }
+
+ test_all(test_intrinsic_default, (v)=>v);
+ test_all(test_intrinsic_default,
+ (v)=>{ "use strict"; return class extends v {}});
+})();
diff --git a/test/mjsunit/es6/reflect-define-property.js b/test/mjsunit/es6/reflect-define-property.js
new file mode 100644
index 0000000..b19c5aa
--- /dev/null
+++ b/test/mjsunit/es6/reflect-define-property.js
@@ -0,0 +1,1115 @@
+// Copyright 2012-2015 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.
+
+// Tests the Reflect.defineProperty method - ES6 26.1.3
+// This is adapted from mjsunit/object-define-property.js.
+
+// Flags: --allow-natives-syntax
+
+
+// Check that an exception is thrown when null is passed as object.
+var exception = false;
+try {
+ Reflect.defineProperty(null, null, null);
+} catch (e) {
+ exception = true;
+ assertTrue(/called on non-object/.test(e));
+}
+assertTrue(exception);
+
+// Check that an exception is thrown when undefined is passed as object.
+exception = false;
+try {
+ Reflect.defineProperty(undefined, undefined, undefined);
+} catch (e) {
+ exception = true;
+ assertTrue(/called on non-object/.test(e));
+}
+assertTrue(exception);
+
+// Check that an exception is thrown when non-object is passed as object.
+exception = false;
+try {
+ Reflect.defineProperty(0, "foo", undefined);
+} catch (e) {
+ exception = true;
+ assertTrue(/called on non-object/.test(e));
+}
+assertTrue(exception);
+
+// Object.
+var obj1 = {};
+
+// Values.
+var val1 = 0;
+var val2 = 0;
+var val3 = 0;
+
+function setter1() {val1++; }
+function getter1() {return val1; }
+
+function setter2() {val2++; }
+function getter2() {return val2; }
+
+function setter3() {val3++; }
+function getter3() {return val3; }
+
+
+// Descriptors.
+var emptyDesc = {};
+
+var accessorConfigurable = {
+ set: setter1,
+ get: getter1,
+ configurable: true
+};
+
+var accessorNoConfigurable = {
+ set: setter2,
+ get: getter2,
+ configurable: false
+};
+
+var accessorOnlySet = {
+ set: setter3,
+ configurable: true
+};
+
+var accessorOnlyGet = {
+ get: getter3,
+ configurable: true
+};
+
+var accessorDefault = {set: function(){} };
+
+var dataConfigurable = { value: 1000, configurable: true };
+
+var dataNoConfigurable = { value: 2000, configurable: false };
+
+var dataWritable = { value: 3000, writable: true};
+
+
+// Check that we can't add property with undefined attributes.
+assertThrows(function() { Reflect.defineProperty(obj1, "foo", undefined) },
+ TypeError);
+
+// Make sure that we can add a property with an empty descriptor and
+// that it has the default descriptor values.
+assertTrue(Reflect.defineProperty(obj1, "foo", emptyDesc));
+
+// foo should be undefined as it has no get, set or value
+assertEquals(undefined, obj1.foo);
+
+// We should, however, be able to retrieve the propertydescriptor which should
+// have all default values (according to 8.6.1).
+var desc = Object.getOwnPropertyDescriptor(obj1, "foo");
+assertFalse(desc.configurable);
+assertFalse(desc.enumerable);
+assertFalse(desc.writable);
+assertEquals(desc.get, undefined);
+assertEquals(desc.set, undefined);
+assertEquals(desc.value, undefined);
+
+// Make sure that getOwnPropertyDescriptor does not return a descriptor
+// with default values if called with non existing property (otherwise
+// the test above is invalid).
+desc = Object.getOwnPropertyDescriptor(obj1, "bar");
+assertEquals(desc, undefined);
+
+// Make sure that foo can't be reset (as configurable is false).
+assertFalse(Reflect.defineProperty(obj1, "foo", accessorConfigurable));
+
+
+// Accessor properties
+
+assertTrue(Reflect.defineProperty(obj1, "bar", accessorConfigurable));
+desc = Object.getOwnPropertyDescriptor(obj1, "bar");
+assertTrue(desc.configurable);
+assertFalse(desc.enumerable);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.get, accessorConfigurable.get);
+assertEquals(desc.set, accessorConfigurable.set);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj1.bar = 1);
+assertEquals(1, val1);
+assertEquals(1, obj1.bar = 1);
+assertEquals(2, val1);
+assertEquals(2, obj1.bar);
+
+// Redefine bar with non configurable test
+assertTrue(Reflect.defineProperty(obj1, "bar", accessorNoConfigurable));
+desc = Object.getOwnPropertyDescriptor(obj1, "bar");
+assertFalse(desc.configurable);
+assertFalse(desc.enumerable);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.get, accessorNoConfigurable.get);
+assertEquals(desc.set, accessorNoConfigurable.set);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj1.bar = 1);
+assertEquals(2, val1);
+assertEquals(1, val2);
+assertEquals(1, obj1.bar = 1)
+assertEquals(2, val1);
+assertEquals(2, val2);
+assertEquals(2, obj1.bar);
+
+// Try to redefine bar again - should fail as configurable is false.
+assertFalse(Reflect.defineProperty(obj1, "bar", accessorConfigurable));
+
+// Try to redefine bar again using the data descriptor - should fail.
+assertFalse(Reflect.defineProperty(obj1, "bar", dataConfigurable));
+
+// Redefine using same descriptor - should succeed.
+assertTrue(Reflect.defineProperty(obj1, "bar", accessorNoConfigurable));
+desc = Object.getOwnPropertyDescriptor(obj1, "bar");
+assertFalse(desc.configurable);
+assertFalse(desc.enumerable);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.get, accessorNoConfigurable.get);
+assertEquals(desc.set, accessorNoConfigurable.set);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj1.bar = 1);
+assertEquals(2, val1);
+assertEquals(3, val2);
+assertEquals(1, obj1.bar = 1)
+assertEquals(2, val1);
+assertEquals(4, val2);
+assertEquals(4, obj1.bar);
+
+// Define an accessor that has only a setter.
+assertTrue(Reflect.defineProperty(obj1, "setOnly", accessorOnlySet));
+desc = Object.getOwnPropertyDescriptor(obj1, "setOnly");
+assertTrue(desc.configurable);
+assertFalse(desc.enumerable);
+assertEquals(desc.set, accessorOnlySet.set);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.value, undefined);
+assertEquals(desc.get, undefined);
+assertEquals(1, obj1.setOnly = 1);
+assertEquals(1, val3);
+
+// Add a getter - should not touch the setter.
+assertTrue(Reflect.defineProperty(obj1, "setOnly", accessorOnlyGet));
+desc = Object.getOwnPropertyDescriptor(obj1, "setOnly");
+assertTrue(desc.configurable);
+assertFalse(desc.enumerable);
+assertEquals(desc.get, accessorOnlyGet.get);
+assertEquals(desc.set, accessorOnlySet.set);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj1.setOnly = 1);
+assertEquals(2, val3);
+
+// The above should also work if redefining just a getter or setter on
+// an existing property with both a getter and a setter.
+assertTrue(Reflect.defineProperty(obj1, "both", accessorConfigurable));
+
+assertTrue(Reflect.defineProperty(obj1, "both", accessorOnlySet));
+desc = Object.getOwnPropertyDescriptor(obj1, "both");
+assertTrue(desc.configurable);
+assertFalse(desc.enumerable);
+assertEquals(desc.set, accessorOnlySet.set);
+assertEquals(desc.get, accessorConfigurable.get);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj1.both = 1);
+assertEquals(3, val3);
+
+
+// Data properties
+
+assertTrue(Reflect.defineProperty(obj1, "foobar", dataConfigurable));
+desc = Object.getOwnPropertyDescriptor(obj1, "foobar");
+assertEquals(obj1.foobar, 1000);
+assertEquals(desc.value, 1000);
+assertTrue(desc.configurable);
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertEquals(desc.get, undefined);
+assertEquals(desc.set, undefined);
+//Try writing to non writable attribute - should remain 1000
+obj1.foobar = 1001;
+assertEquals(obj1.foobar, 1000);
+
+
+// Redefine to writable descriptor - now writing to foobar should be allowed.
+assertTrue(Reflect.defineProperty(obj1, "foobar", dataWritable));
+desc = Object.getOwnPropertyDescriptor(obj1, "foobar");
+assertEquals(obj1.foobar, 3000);
+assertEquals(desc.value, 3000);
+// Note that since dataWritable does not define configurable the configurable
+// setting from the redefined property (in this case true) is used.
+assertTrue(desc.configurable);
+assertTrue(desc.writable);
+assertFalse(desc.enumerable);
+assertEquals(desc.get, undefined);
+assertEquals(desc.set, undefined);
+// Writing to the property should now be allowed
+obj1.foobar = 1001;
+assertEquals(obj1.foobar, 1001);
+
+
+// Redefine with non configurable data property.
+assertTrue(Reflect.defineProperty(obj1, "foobar", dataNoConfigurable));
+desc = Object.getOwnPropertyDescriptor(obj1, "foobar");
+assertEquals(obj1.foobar, 2000);
+assertEquals(desc.value, 2000);
+assertFalse(desc.configurable);
+assertTrue(desc.writable);
+assertFalse(desc.enumerable);
+assertEquals(desc.get, undefined);
+assertEquals(desc.set, undefined);
+
+// Try redefine again - shold fail because configurable is now false.
+assertFalse(Reflect.defineProperty(obj1, "foobar", dataConfigurable));
+
+// Try redefine again with accessor property - shold also fail.
+assertFalse(Reflect.defineProperty(obj1, "foobar", dataConfigurable));
+
+
+// Redifine with the same descriptor - should succeed (step 6).
+assertTrue(Reflect.defineProperty(obj1, "foobar", dataNoConfigurable));
+desc = Object.getOwnPropertyDescriptor(obj1, "foobar");
+assertEquals(obj1.foobar, 2000);
+assertEquals(desc.value, 2000);
+assertFalse(desc.configurable);
+assertTrue(desc.writable);
+assertFalse(desc.enumerable);
+assertEquals(desc.get, undefined);
+assertEquals(desc.set, undefined);
+
+
+// New object
+var obj2 = {};
+
+// Make accessor - redefine to data
+assertTrue(Reflect.defineProperty(obj2, "foo", accessorConfigurable));
+
+// Redefine to data property
+assertTrue(Reflect.defineProperty(obj2, "foo", dataConfigurable));
+desc = Object.getOwnPropertyDescriptor(obj2, "foo");
+assertEquals(obj2.foo, 1000);
+assertEquals(desc.value, 1000);
+assertTrue(desc.configurable);
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertEquals(desc.get, undefined);
+assertEquals(desc.set, undefined);
+
+
+// Redefine back to accessor
+assertTrue(Reflect.defineProperty(obj2, "foo", accessorConfigurable));
+desc = Object.getOwnPropertyDescriptor(obj2, "foo");
+assertTrue(desc.configurable);
+assertFalse(desc.enumerable);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.get, accessorConfigurable.get);
+assertEquals(desc.set, accessorConfigurable.set);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj2.foo = 1);
+assertEquals(3, val1);
+assertEquals(4, val2);
+assertEquals(3, obj2.foo);
+
+// Make data - redefine to accessor
+assertTrue(Reflect.defineProperty(obj2, "bar", dataConfigurable))
+
+// Redefine to accessor property
+assertTrue(Reflect.defineProperty(obj2, "bar", accessorConfigurable));
+desc = Object.getOwnPropertyDescriptor(obj2, "bar");
+assertTrue(desc.configurable);
+assertFalse(desc.enumerable);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.get, accessorConfigurable.get);
+assertEquals(desc.set, accessorConfigurable.set);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj2.bar = 1);
+assertEquals(4, val1);
+assertEquals(4, val2);
+assertEquals(4, obj2.foo);
+
+// Redefine back to data property
+assertTrue(Reflect.defineProperty(obj2, "bar", dataConfigurable));
+desc = Object.getOwnPropertyDescriptor(obj2, "bar");
+assertEquals(obj2.bar, 1000);
+assertEquals(desc.value, 1000);
+assertTrue(desc.configurable);
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertEquals(desc.get, undefined);
+assertEquals(desc.set, undefined);
+
+
+// Redefinition of an accessor defined using __defineGetter__ and
+// __defineSetter__.
+function get(){return this.x}
+function set(x){this.x=x};
+
+var obj3 = {x:1000};
+obj3.__defineGetter__("foo", get);
+obj3.__defineSetter__("foo", set);
+
+desc = Object.getOwnPropertyDescriptor(obj3, "foo");
+assertTrue(desc.configurable);
+assertTrue(desc.enumerable);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.get, get);
+assertEquals(desc.set, set);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj3.foo = 1);
+assertEquals(1, obj3.x);
+assertEquals(1, obj3.foo);
+
+// Redefine to accessor property (non configurable) - note that enumerable
+// which we do not redefine should remain the same (true).
+assertTrue(Reflect.defineProperty(obj3, "foo", accessorNoConfigurable));
+desc = Object.getOwnPropertyDescriptor(obj3, "foo");
+assertFalse(desc.configurable);
+assertTrue(desc.enumerable);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.get, accessorNoConfigurable.get);
+assertEquals(desc.set, accessorNoConfigurable.set);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj3.foo = 1);
+assertEquals(5, val2);
+assertEquals(5, obj3.foo);
+
+
+obj3.__defineGetter__("bar", get);
+obj3.__defineSetter__("bar", set);
+
+
+// Redefine back to data property
+assertTrue(Reflect.defineProperty(obj3, "bar", dataConfigurable));
+desc = Object.getOwnPropertyDescriptor(obj3, "bar");
+assertEquals(obj3.bar, 1000);
+assertEquals(desc.value, 1000);
+assertTrue(desc.configurable);
+assertFalse(desc.writable);
+assertTrue(desc.enumerable);
+assertEquals(desc.get, undefined);
+assertEquals(desc.set, undefined);
+
+
+var obj4 = {};
+var func = function (){return 42;};
+obj4.bar = func;
+assertEquals(42, obj4.bar());
+
+assertTrue(Reflect.defineProperty(obj4, "bar", accessorConfigurable));
+desc = Object.getOwnPropertyDescriptor(obj4, "bar");
+assertTrue(desc.configurable);
+assertTrue(desc.enumerable);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.get, accessorConfigurable.get);
+assertEquals(desc.set, accessorConfigurable.set);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj4.bar = 1);
+assertEquals(5, val1);
+assertEquals(5, obj4.bar);
+
+// Make sure an error is thrown when trying to access to redefined function.
+try {
+ obj4.bar();
+ assertTrue(false);
+} catch (e) {
+ assertTrue(/is not a function/.test(e));
+}
+
+
+// Test runtime calls to DefineDataPropertyUnchecked and
+// DefineAccessorPropertyUnchecked - make sure we don't
+// crash.
+try {
+ %DefineAccessorPropertyUnchecked(0, 0, 0, 0, 0);
+} catch (e) {
+ assertTrue(/illegal access/.test(e));
+}
+
+try {
+ %DefineDataPropertyUnchecked(0, 0, 0, 0);
+} catch (e) {
+ assertTrue(/illegal access/.test(e));
+}
+
+try {
+ %DefineDataPropertyUnchecked(null, null, null, null);
+} catch (e) {
+ assertTrue(/illegal access/.test(e));
+}
+
+try {
+ %DefineAccessorPropertyUnchecked(null, null, null, null, null);
+} catch (e) {
+ assertTrue(/illegal access/.test(e));
+}
+
+try {
+ %DefineDataPropertyUnchecked({}, null, null, null);
+} catch (e) {
+ assertTrue(/illegal access/.test(e));
+}
+
+// Defining properties null should fail even when we have
+// other allowed values
+try {
+ %DefineAccessorPropertyUnchecked(null, 'foo', func, null, 0);
+} catch (e) {
+ assertTrue(/illegal access/.test(e));
+}
+
+try {
+ %DefineDataPropertyUnchecked(null, 'foo', 0, 0);
+} catch (e) {
+ assertTrue(/illegal access/.test(e));
+}
+
+// Test that all possible differences in step 6 in DefineOwnProperty are
+// exercised, i.e., any difference in the given property descriptor and the
+// existing properties should not return true, but throw an error if the
+// existing configurable property is false.
+
+var obj5 = {};
+// Enumerable will default to false.
+assertTrue(Reflect.defineProperty(obj5, 'foo', accessorNoConfigurable));
+desc = Object.getOwnPropertyDescriptor(obj5, 'foo');
+// First, test that we are actually allowed to set the accessor if all
+// values are of the descriptor are the same as the existing one.
+assertTrue(Reflect.defineProperty(obj5, 'foo', accessorNoConfigurable));
+
+// Different setter.
+var descDifferent = {
+ configurable:false,
+ enumerable:false,
+ set: setter1,
+ get: getter2
+};
+
+assertFalse(Reflect.defineProperty(obj5, 'foo', descDifferent));
+
+// Different getter.
+descDifferent = {
+ configurable:false,
+ enumerable:false,
+ set: setter2,
+ get: getter1
+};
+
+assertFalse(Reflect.defineProperty(obj5, 'foo', descDifferent));
+
+// Different enumerable.
+descDifferent = {
+ configurable:false,
+ enumerable:true,
+ set: setter2,
+ get: getter2
+};
+
+assertFalse(Reflect.defineProperty(obj5, 'foo', descDifferent));
+
+// Different configurable.
+descDifferent = {
+ configurable:false,
+ enumerable:true,
+ set: setter2,
+ get: getter2
+};
+
+assertFalse(Reflect.defineProperty(obj5, 'foo', descDifferent));
+
+// No difference.
+descDifferent = {
+ configurable:false,
+ enumerable:false,
+ set: setter2,
+ get: getter2
+};
+// Make sure we can still redefine if all properties are the same.
+assertTrue(Reflect.defineProperty(obj5, 'foo', descDifferent));
+
+// Make sure that obj5 still holds the original values.
+desc = Object.getOwnPropertyDescriptor(obj5, 'foo');
+assertEquals(desc.get, getter2);
+assertEquals(desc.set, setter2);
+assertFalse(desc.enumerable);
+assertFalse(desc.configurable);
+
+
+// Also exercise step 6 on data property, writable and enumerable
+// defaults to false.
+assertTrue(Reflect.defineProperty(obj5, 'bar', dataNoConfigurable));
+
+// Test that redefinition with the same property descriptor is possible
+assertTrue(Reflect.defineProperty(obj5, 'bar', dataNoConfigurable));
+
+// Different value.
+descDifferent = {
+ configurable:false,
+ enumerable:false,
+ writable: false,
+ value: 1999
+};
+
+assertFalse(Reflect.defineProperty(obj5, 'bar', descDifferent));
+
+// Different writable.
+descDifferent = {
+ configurable:false,
+ enumerable:false,
+ writable: true,
+ value: 2000
+};
+
+assertFalse(Reflect.defineProperty(obj5, 'bar', descDifferent));
+
+
+// Different enumerable.
+descDifferent = {
+ configurable:false,
+ enumerable:true ,
+ writable:false,
+ value: 2000
+};
+
+assertFalse(Reflect.defineProperty(obj5, 'bar', descDifferent));
+
+
+// Different configurable.
+descDifferent = {
+ configurable:true,
+ enumerable:false,
+ writable:false,
+ value: 2000
+};
+
+assertFalse(Reflect.defineProperty(obj5, 'bar', descDifferent));
+
+// No difference.
+descDifferent = {
+ configurable:false,
+ enumerable:false,
+ writable:false,
+ value:2000
+};
+// Make sure we can still redefine if all properties are the same.
+assertTrue(Reflect.defineProperty(obj5, 'bar', descDifferent));
+
+// Make sure that obj5 still holds the original values.
+desc = Object.getOwnPropertyDescriptor(obj5, 'bar');
+assertEquals(desc.value, 2000);
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertFalse(desc.configurable);
+
+
+// Make sure that we can't overwrite +0 with -0 and vice versa.
+var descMinusZero = {value: -0, configurable: false};
+var descPlusZero = {value: +0, configurable: false};
+
+assertTrue(Reflect.defineProperty(obj5, 'minuszero', descMinusZero));
+
+// Make sure we can redefine with -0.
+assertTrue(Reflect.defineProperty(obj5, 'minuszero', descMinusZero));
+
+assertFalse(Reflect.defineProperty(obj5, 'minuszero', descPlusZero));
+
+
+assertTrue(Reflect.defineProperty(obj5, 'pluszero', descPlusZero));
+
+// Make sure we can redefine with +0.
+assertTrue(Reflect.defineProperty(obj5, 'pluszero', descPlusZero));
+
+assertFalse(Reflect.defineProperty(obj5, 'pluszero', descMinusZero));
+
+
+var obj6 = {};
+obj6[1] = 'foo';
+obj6[2] = 'bar';
+obj6[3] = '42';
+obj6[4] = '43';
+obj6[5] = '44';
+
+var descElement = { value: 'foobar' };
+var descElementNonConfigurable = { value: 'barfoo', configurable: false };
+var descElementNonWritable = { value: 'foofoo', writable: false };
+var descElementNonEnumerable = { value: 'barbar', enumerable: false };
+var descElementAllFalse = { value: 'foofalse',
+ configurable: false,
+ writable: false,
+ enumerable: false };
+
+
+// Redefine existing property.
+assertTrue(Reflect.defineProperty(obj6, '1', descElement));
+desc = Object.getOwnPropertyDescriptor(obj6, '1');
+assertEquals(desc.value, 'foobar');
+assertTrue(desc.writable);
+assertTrue(desc.enumerable);
+assertTrue(desc.configurable);
+
+// Redefine existing property with configurable: false.
+assertTrue(Reflect.defineProperty(obj6, '2', descElementNonConfigurable));
+desc = Object.getOwnPropertyDescriptor(obj6, '2');
+assertEquals(desc.value, 'barfoo');
+assertTrue(desc.writable);
+assertTrue(desc.enumerable);
+assertFalse(desc.configurable);
+
+// Can use defineProperty to change the value of a non
+// configurable property.
+try {
+ assertTrue(Reflect.defineProperty(obj6, '2', descElement));
+ desc = Object.getOwnPropertyDescriptor(obj6, '2');
+ assertEquals(desc.value, 'foobar');
+} catch (e) {
+ assertUnreachable();
+}
+
+// Ensure that we can't change the descriptor of a
+// non configurable property.
+var descAccessor = { get: function() { return 0; } };
+assertFalse(Reflect.defineProperty(obj6, '2', descAccessor));
+
+assertTrue(Reflect.defineProperty(obj6, '2', descElementNonWritable));
+desc = Object.getOwnPropertyDescriptor(obj6, '2');
+assertEquals(desc.value, 'foofoo');
+assertFalse(desc.writable);
+assertTrue(desc.enumerable);
+assertFalse(desc.configurable);
+
+assertTrue(Reflect.defineProperty(obj6, '3', descElementNonWritable));
+desc = Object.getOwnPropertyDescriptor(obj6, '3');
+assertEquals(desc.value, 'foofoo');
+assertFalse(desc.writable);
+assertTrue(desc.enumerable);
+assertTrue(desc.configurable);
+
+// Redefine existing property with configurable: false.
+assertTrue(Reflect.defineProperty(obj6, '4', descElementNonEnumerable));
+desc = Object.getOwnPropertyDescriptor(obj6, '4');
+assertEquals(desc.value, 'barbar');
+assertTrue(desc.writable);
+assertFalse(desc.enumerable);
+assertTrue(desc.configurable);
+
+// Redefine existing property with configurable: false.
+assertTrue(Reflect.defineProperty(obj6, '5', descElementAllFalse));
+desc = Object.getOwnPropertyDescriptor(obj6, '5');
+assertEquals(desc.value, 'foofalse');
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertFalse(desc.configurable);
+
+// Define non existing property - all attributes should default to false.
+assertTrue(Reflect.defineProperty(obj6, '15', descElement));
+desc = Object.getOwnPropertyDescriptor(obj6, '15');
+assertEquals(desc.value, 'foobar');
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertFalse(desc.configurable);
+
+// Make sure that we can't redefine using direct access.
+obj6[15] ='overwrite';
+assertEquals(obj6[15],'foobar');
+
+
+// Repeat the above tests on an array.
+var arr = new Array();
+arr[1] = 'foo';
+arr[2] = 'bar';
+arr[3] = '42';
+arr[4] = '43';
+arr[5] = '44';
+
+var descElement = { value: 'foobar' };
+var descElementNonConfigurable = { value: 'barfoo', configurable: false };
+var descElementNonWritable = { value: 'foofoo', writable: false };
+var descElementNonEnumerable = { value: 'barbar', enumerable: false };
+var descElementAllFalse = { value: 'foofalse',
+ configurable: false,
+ writable: false,
+ enumerable: false };
+
+
+// Redefine existing property.
+assertTrue(Reflect.defineProperty(arr, '1', descElement));
+desc = Object.getOwnPropertyDescriptor(arr, '1');
+assertEquals(desc.value, 'foobar');
+assertTrue(desc.writable);
+assertTrue(desc.enumerable);
+assertTrue(desc.configurable);
+
+// Redefine existing property with configurable: false.
+assertTrue(Reflect.defineProperty(arr, '2', descElementNonConfigurable));
+desc = Object.getOwnPropertyDescriptor(arr, '2');
+assertEquals(desc.value, 'barfoo');
+assertTrue(desc.writable);
+assertTrue(desc.enumerable);
+assertFalse(desc.configurable);
+
+// Can use defineProperty to change the value of a non
+// configurable property of an array.
+try {
+ assertTrue(Reflect.defineProperty(arr, '2', descElement));
+ desc = Object.getOwnPropertyDescriptor(arr, '2');
+ assertEquals(desc.value, 'foobar');
+} catch (e) {
+ assertUnreachable();
+}
+
+// Ensure that we can't change the descriptor of a
+// non configurable property.
+var descAccessor = { get: function() { return 0; } };
+assertFalse(Reflect.defineProperty(arr, '2', descAccessor));
+
+assertTrue(Reflect.defineProperty(arr, '2', descElementNonWritable));
+desc = Object.getOwnPropertyDescriptor(arr, '2');
+assertEquals(desc.value, 'foofoo');
+assertFalse(desc.writable);
+assertTrue(desc.enumerable);
+assertFalse(desc.configurable);
+
+assertTrue(Reflect.defineProperty(arr, '3', descElementNonWritable));
+desc = Object.getOwnPropertyDescriptor(arr, '3');
+assertEquals(desc.value, 'foofoo');
+assertFalse(desc.writable);
+assertTrue(desc.enumerable);
+assertTrue(desc.configurable);
+
+// Redefine existing property with configurable: false.
+assertTrue(Reflect.defineProperty(arr, '4', descElementNonEnumerable));
+desc = Object.getOwnPropertyDescriptor(arr, '4');
+assertEquals(desc.value, 'barbar');
+assertTrue(desc.writable);
+assertFalse(desc.enumerable);
+assertTrue(desc.configurable);
+
+// Redefine existing property with configurable: false.
+assertTrue(Reflect.defineProperty(arr, '5', descElementAllFalse));
+desc = Object.getOwnPropertyDescriptor(arr, '5');
+assertEquals(desc.value, 'foofalse');
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertFalse(desc.configurable);
+
+// Define non existing property - all attributes should default to false.
+assertTrue(Reflect.defineProperty(arr, '15', descElement));
+desc = Object.getOwnPropertyDescriptor(arr, '15');
+assertEquals(desc.value, 'foobar');
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertFalse(desc.configurable);
+
+// Define non-array property, check that .length is unaffected.
+assertEquals(16, arr.length);
+assertTrue(Reflect.defineProperty(arr, '0x20', descElement));
+assertEquals(16, arr.length);
+
+// See issue 968: http://code.google.com/p/v8/issues/detail?id=968
+var o = { x : 42 };
+assertTrue(Reflect.defineProperty(o, "x", { writable: false }));
+assertEquals(42, o.x);
+o.x = 37;
+assertEquals(42, o.x);
+
+o = { x : 42 };
+assertTrue(Reflect.defineProperty(o, "x", {}));
+assertEquals(42, o.x);
+o.x = 37;
+// Writability is preserved.
+assertEquals(37, o.x);
+
+var o = { };
+assertTrue(Reflect.defineProperty(o, "x", { writable: false }));
+assertEquals(undefined, o.x);
+o.x = 37;
+assertEquals(undefined, o.x);
+
+o = { get x() { return 87; } };
+assertTrue(Reflect.defineProperty(o, "x", { writable: false }));
+assertEquals(undefined, o.x);
+o.x = 37;
+assertEquals(undefined, o.x);
+
+// Ignore inherited properties.
+o = { __proto__ : { x : 87 } };
+assertTrue(Reflect.defineProperty(o, "x", { writable: false }));
+assertEquals(undefined, o.x);
+o.x = 37;
+assertEquals(undefined, o.x);
+
+function testDefineProperty(obj, propertyName, desc, resultDesc) {
+ assertTrue(Reflect.defineProperty(obj, propertyName, desc));
+ var actualDesc = Object.getOwnPropertyDescriptor(obj, propertyName);
+ assertEquals(resultDesc.enumerable, actualDesc.enumerable);
+ assertEquals(resultDesc.configurable, actualDesc.configurable);
+ if (resultDesc.hasOwnProperty('value')) {
+ assertEquals(resultDesc.value, actualDesc.value);
+ assertEquals(resultDesc.writable, actualDesc.writable);
+ assertFalse(resultDesc.hasOwnProperty('get'));
+ assertFalse(resultDesc.hasOwnProperty('set'));
+ } else {
+ assertEquals(resultDesc.get, actualDesc.get);
+ assertEquals(resultDesc.set, actualDesc.set);
+ assertFalse(resultDesc.hasOwnProperty('value'));
+ assertFalse(resultDesc.hasOwnProperty('writable'));
+ }
+}
+
+// tests redefining existing property with a generic descriptor
+o = { p : 42 };
+testDefineProperty(o, 'p',
+ { },
+ { value : 42, writable : true, enumerable : true, configurable : true });
+
+o = { p : 42 };
+testDefineProperty(o, 'p',
+ { enumerable : true },
+ { value : 42, writable : true, enumerable : true, configurable : true });
+
+o = { p : 42 };
+testDefineProperty(o, 'p',
+ { configurable : true },
+ { value : 42, writable : true, enumerable : true, configurable : true });
+
+o = { p : 42 };
+testDefineProperty(o, 'p',
+ { enumerable : false },
+ { value : 42, writable : true, enumerable : false, configurable : true });
+
+o = { p : 42 };
+testDefineProperty(o, 'p',
+ { configurable : false },
+ { value : 42, writable : true, enumerable : true, configurable : false });
+
+o = { p : 42 };
+testDefineProperty(o, 'p',
+ { enumerable : true, configurable : true },
+ { value : 42, writable : true, enumerable : true, configurable : true });
+
+o = { p : 42 };
+testDefineProperty(o, 'p',
+ { enumerable : false, configurable : true },
+ { value : 42, writable : true, enumerable : false, configurable : true });
+
+o = { p : 42 };
+testDefineProperty(o, 'p',
+ { enumerable : true, configurable : false },
+ { value : 42, writable : true, enumerable : true, configurable : false });
+
+o = { p : 42 };
+testDefineProperty(o, 'p',
+ { enumerable : false, configurable : false },
+ { value : 42, writable : true, enumerable : false, configurable : false });
+
+// can make a writable, non-configurable field non-writable
+o = { p : 42 };
+assertTrue(Reflect.defineProperty(o, 'p', { configurable: false }));
+testDefineProperty(o, 'p',
+ { writable: false },
+ { value : 42, writable : false, enumerable : true, configurable : false });
+
+// redefine of get only property with generic descriptor
+o = {};
+assertTrue(Reflect.defineProperty(o, 'p',
+ { get : getter1, enumerable: true, configurable: true }));
+testDefineProperty(o, 'p',
+ { enumerable : false, configurable : false },
+ { get: getter1, set: undefined, enumerable : false, configurable : false });
+
+// redefine of get/set only property with generic descriptor
+o = {};
+assertTrue(Reflect.defineProperty(o, 'p',
+ { get: getter1, set: setter1, enumerable: true, configurable: true }));
+testDefineProperty(o, 'p',
+ { enumerable : false, configurable : false },
+ { get: getter1, set: setter1, enumerable : false, configurable : false });
+
+// redefine of set only property with generic descriptor
+o = {};
+assertTrue(Reflect.defineProperty(o, 'p',
+ { set : setter1, enumerable: true, configurable: true }));
+testDefineProperty(o, 'p',
+ { enumerable : false, configurable : false },
+ { get: undefined, set: setter1, enumerable : false, configurable : false });
+
+
+// Regression test: Ensure that growing dictionaries are not ignored.
+o = {};
+for (var i = 0; i < 1000; i++) {
+ // Non-enumerable property forces dictionary mode.
+ assertTrue(Reflect.defineProperty(o, i, {value: i, enumerable: false}));
+}
+assertEquals(999, o[999]);
+
+
+// Regression test: Bizzare behavior on non-strict arguments object.
+// TODO(yangguo): Tests disabled, needs investigation!
+/*
+(function test(arg0) {
+ // Here arguments[0] is a fast alias on arg0.
+ Reflect.defineProperty(arguments, "0", {
+ value:1,
+ enumerable:false
+ });
+ // Here arguments[0] is a slow alias on arg0.
+ Reflect.defineProperty(arguments, "0", {
+ value:2,
+ writable:false
+ });
+ // Here arguments[0] is no alias at all.
+ Reflect.defineProperty(arguments, "0", {
+ value:3
+ });
+ assertEquals(2, arg0);
+ assertEquals(3, arguments[0]);
+})(0);
+*/
+
+// Regression test: We should never observe the hole value.
+var objectWithGetter = {};
+objectWithGetter.__defineGetter__('foo', function() {});
+assertEquals(undefined, objectWithGetter.__lookupSetter__('foo'));
+
+var objectWithSetter = {};
+objectWithSetter.__defineSetter__('foo', function(x) {});
+assertEquals(undefined, objectWithSetter.__lookupGetter__('foo'));
+
+// An object with a getter on the prototype chain.
+function getter() { return 111; }
+function anotherGetter() { return 222; }
+
+function testGetterOnProto(expected, o) {
+ assertEquals(expected, o.quebec);
+}
+
+obj1 = {};
+assertTrue(
+ Reflect.defineProperty(obj1, "quebec", { get: getter, configurable: true }));
+obj2 = Object.create(obj1);
+obj3 = Object.create(obj2);
+
+testGetterOnProto(111, obj3);
+testGetterOnProto(111, obj3);
+%OptimizeFunctionOnNextCall(testGetterOnProto);
+testGetterOnProto(111, obj3);
+testGetterOnProto(111, obj3);
+
+assertTrue(Reflect.defineProperty(obj1, "quebec", { get: anotherGetter }));
+
+testGetterOnProto(222, obj3);
+testGetterOnProto(222, obj3);
+%OptimizeFunctionOnNextCall(testGetterOnProto);
+testGetterOnProto(222, obj3);
+testGetterOnProto(222, obj3);
+
+// An object with a setter on the prototype chain.
+var modifyMe;
+function setter(x) { modifyMe = x+1; }
+function anotherSetter(x) { modifyMe = x+2; }
+
+function testSetterOnProto(expected, o) {
+ modifyMe = 333;
+ o.romeo = 444;
+ assertEquals(expected, modifyMe);
+}
+
+obj1 = {};
+assertTrue(
+ Reflect.defineProperty(obj1, "romeo", { set: setter, configurable: true }));
+obj2 = Object.create(obj1);
+obj3 = Object.create(obj2);
+
+testSetterOnProto(445, obj3);
+testSetterOnProto(445, obj3);
+%OptimizeFunctionOnNextCall(testSetterOnProto);
+testSetterOnProto(445, obj3);
+testSetterOnProto(445, obj3);
+
+assertTrue(Reflect.defineProperty(obj1, "romeo", { set: anotherSetter }));
+
+testSetterOnProto(446, obj3);
+testSetterOnProto(446, obj3);
+%OptimizeFunctionOnNextCall(testSetterOnProto);
+testSetterOnProto(446, obj3);
+testSetterOnProto(446, obj3);
+
+// Removing a setter on the prototype chain.
+function testSetterOnProtoStrict(o) {
+ "use strict";
+ o.sierra = 12345;
+}
+
+obj1 = {};
+assertTrue(Reflect.defineProperty(obj1, "sierra",
+ { get: getter, set: setter, configurable: true }));
+obj2 = Object.create(obj1);
+obj3 = Object.create(obj2);
+
+testSetterOnProtoStrict(obj3);
+testSetterOnProtoStrict(obj3);
+%OptimizeFunctionOnNextCall(testSetterOnProtoStrict);
+testSetterOnProtoStrict(obj3);
+testSetterOnProtoStrict(obj3);
+
+assertTrue(Reflect.defineProperty(obj1, "sierra",
+ { get: getter, set: undefined, configurable: true }));
+
+exception = false;
+try {
+ testSetterOnProtoStrict(obj3);
+} catch (e) {
+ exception = true;
+ assertTrue(/which has only a getter/.test(e));
+}
+assertTrue(exception);
+
+// Test assignment to a getter-only property on the prototype chain. This makes
+// sure that crankshaft re-checks its assumptions and doesn't rely only on type
+// feedback (which would be monomorphic here).
+
+function Assign(o) {
+ o.blubb = 123;
+}
+
+function C() {}
+
+Assign(new C);
+Assign(new C);
+%OptimizeFunctionOnNextCall(Assign);
+assertTrue(
+ Reflect.defineProperty(C.prototype, "blubb", {get: function() {return -42}}));
+Assign(new C);
+
+// Test that changes to the prototype of a simple constructor are not ignored,
+// even after creating initial instances.
+function C() {
+ this.x = 23;
+}
+assertEquals(23, new C().x);
+C.prototype.__defineSetter__('x', function(value) { this.y = 23; });
+assertEquals(void 0, new C().x);
diff --git a/test/mjsunit/es6/reflect-get-own-property-descriptor.js b/test/mjsunit/es6/reflect-get-own-property-descriptor.js
new file mode 100644
index 0000000..5e96899
--- /dev/null
+++ b/test/mjsunit/es6/reflect-get-own-property-descriptor.js
@@ -0,0 +1,121 @@
+// Copyright 2015 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.
+
+// This file only tests very simple descriptors that always have
+// configurable, enumerable, and writable set to true.
+
+// This is adapted from mjsunit/get-own-property-descriptor.js.
+
+function get() { return x; }
+function set(x) { this.x = x; }
+
+var obj = {x: 1};
+obj.__defineGetter__("accessor", get);
+obj.__defineSetter__("accessor", set);
+var a = new Array();
+a[1] = 42;
+obj[1] = 42;
+
+var descIsData = Reflect.getOwnPropertyDescriptor(obj, 'x');
+assertTrue(descIsData.enumerable);
+assertTrue(descIsData.writable);
+assertTrue(descIsData.configurable);
+
+var descIsAccessor = Reflect.getOwnPropertyDescriptor(obj, 'accessor');
+assertTrue(descIsAccessor.enumerable);
+assertTrue(descIsAccessor.configurable);
+assertTrue(descIsAccessor.get == get);
+assertTrue(descIsAccessor.set == set);
+
+var descIsNotData = Reflect.getOwnPropertyDescriptor(obj, 'not-x');
+assertTrue(descIsNotData == undefined);
+
+var descIsNotAccessor = Reflect.getOwnPropertyDescriptor(obj, 'not-accessor');
+assertTrue(descIsNotAccessor == undefined);
+
+var descArray = Reflect.getOwnPropertyDescriptor(a, '1');
+assertTrue(descArray.enumerable);
+assertTrue(descArray.configurable);
+assertTrue(descArray.writable);
+assertEquals(descArray.value, 42);
+
+var descObjectElement = Reflect.getOwnPropertyDescriptor(obj, '1');
+assertTrue(descObjectElement.enumerable);
+assertTrue(descObjectElement.configurable);
+assertTrue(descObjectElement.writable);
+assertEquals(descObjectElement.value, 42);
+
+// String objects.
+var a = new String('foobar');
+for (var i = 0; i < a.length; i++) {
+ var descStringObject = Reflect.getOwnPropertyDescriptor(a, i);
+ assertTrue(descStringObject.enumerable);
+ assertFalse(descStringObject.configurable);
+ assertFalse(descStringObject.writable);
+ assertEquals(descStringObject.value, a.substring(i, i+1));
+}
+
+// Support for additional attributes on string objects.
+a.x = 42;
+a[10] = 'foo';
+var descStringProperty = Reflect.getOwnPropertyDescriptor(a, 'x');
+assertTrue(descStringProperty.enumerable);
+assertTrue(descStringProperty.configurable);
+assertTrue(descStringProperty.writable);
+assertEquals(descStringProperty.value, 42);
+
+var descStringElement = Reflect.getOwnPropertyDescriptor(a, '10');
+assertTrue(descStringElement.enumerable);
+assertTrue(descStringElement.configurable);
+assertTrue(descStringElement.writable);
+assertEquals(descStringElement.value, 'foo');
+
+// Test that elements in the prototype chain is not returned.
+var proto = {};
+proto[10] = 42;
+
+var objWithProto = new Array();
+objWithProto.prototype = proto;
+objWithProto[0] = 'bar';
+var descWithProto = Reflect.getOwnPropertyDescriptor(objWithProto, '10');
+assertEquals(undefined, descWithProto);
+
+// Test elements on global proxy object.
+var global = (function() { return this; })();
+
+global[42] = 42;
+
+function el_getter() { return 239; };
+function el_setter() {};
+Object.defineProperty(global, '239', {get: el_getter, set: el_setter});
+
+var descRegularElement = Reflect.getOwnPropertyDescriptor(global, '42');
+assertEquals(42, descRegularElement.value);
+
+var descAccessorElement = Reflect.getOwnPropertyDescriptor(global, '239');
+assertEquals(el_getter, descAccessorElement.get);
+assertEquals(el_setter, descAccessorElement.set);
diff --git a/test/mjsunit/es6/reflect-get-prototype-of.js b/test/mjsunit/es6/reflect-get-prototype-of.js
new file mode 100644
index 0000000..9fd1559
--- /dev/null
+++ b/test/mjsunit/es6/reflect-get-prototype-of.js
@@ -0,0 +1,137 @@
+// Copyright 2010-2015 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.
+
+// Tests the Reflect.getPrototypeOf - ES6 26.1.8.
+// This is adapted from mjsunit/get-prototype-of.js.
+
+
+
+function assertPrototypeOf(func, expected) {
+ assertEquals(expected, Reflect.getPrototypeOf(func));
+}
+
+
+assertThrows(function() {
+ Reflect.getPrototypeOf(undefined);
+}, TypeError);
+
+
+assertThrows(function() {
+ Reflect.getPrototypeOf(null);
+}, TypeError);
+
+
+function F(){};
+var y = new F();
+
+assertPrototypeOf(y, F.prototype);
+assertPrototypeOf(F, Function.prototype);
+
+assertPrototypeOf({x: 5}, Object.prototype);
+assertPrototypeOf({x: 5, __proto__: null}, null);
+
+assertPrototypeOf([1, 2], Array.prototype);
+
+
+assertThrows(function () {
+ Reflect.getPrototypeOf(1);
+}, TypeError);
+assertThrows(function () {
+ Reflect.getPrototypeOf(true);
+}, TypeError);
+assertThrows(function () {
+ Reflect.getPrototypeOf(false);
+}, TypeError);
+assertThrows(function () {
+ Reflect.getPrototypeOf('str');
+}, TypeError);
+assertThrows(function () {
+ Reflect.getPrototypeOf(Symbol());
+}, TypeError);
+
+assertPrototypeOf(Object(1), Number.prototype);
+assertPrototypeOf(Object(true), Boolean.prototype);
+assertPrototypeOf(Object(false), Boolean.prototype);
+assertPrototypeOf(Object('str'), String.prototype);
+assertPrototypeOf(Object(Symbol()), Symbol.prototype);
+
+
+var errorFunctions = [
+ EvalError,
+ RangeError,
+ ReferenceError,
+ SyntaxError,
+ TypeError,
+ URIError,
+];
+
+for (var f of errorFunctions) {
+ assertPrototypeOf(f, Error);
+ assertPrototypeOf(new f(), f.prototype);
+}
+
+
+// Builtin constructors.
+var functions = [
+ Array,
+ ArrayBuffer,
+ Boolean,
+ // DataView,
+ Date,
+ Error,
+ // Float32Array, prototype is %TypedArray%
+ // Float64Array,
+ Function,
+ // Int16Array,
+ // Int32Array,
+ // Int8Array,
+ Map,
+ Number,
+ Object,
+ // Promise,
+ RegExp,
+ Set,
+ String,
+ // Symbol, not constructible
+ // Uint16Array,
+ // Uint32Array,
+ // Uint8Array,
+ // Uint8ClampedArray,
+ WeakMap,
+ WeakSet,
+];
+
+for (var f of functions) {
+ assertPrototypeOf(f, Function.prototype);
+ assertPrototypeOf(new f(), f.prototype);
+}
+
+var p = new Promise(function() {});
+assertPrototypeOf(p, Promise.prototype);
+
+var dv = new DataView(new ArrayBuffer());
+assertPrototypeOf(dv, DataView.prototype);
diff --git a/test/mjsunit/es6/reflect-own-keys.js b/test/mjsunit/es6/reflect-own-keys.js
new file mode 100644
index 0000000..5f51f40
--- /dev/null
+++ b/test/mjsunit/es6/reflect-own-keys.js
@@ -0,0 +1,91 @@
+// Copyright 2015 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.
+
+// This is adapted from mjsunit/object-get-own-property-names.js.
+
+
+// Check simple cases.
+var obj = { a: 1, b: 2};
+var keys = Reflect.ownKeys(obj);
+assertEquals(2, keys.length);
+assertEquals("a", keys[0]);
+assertEquals("b", keys[1]);
+
+var obj = { a: function(){}, b: function(){} };
+var keys = Reflect.ownKeys(obj);
+assertEquals(2, keys.length);
+assertEquals("a", keys[0]);
+assertEquals("b", keys[1]);
+
+// Check slow case
+var obj = { a: 1, b: 2, c: 3 };
+delete obj.b;
+var keys = Reflect.ownKeys(obj)
+assertEquals(2, keys.length);
+assertEquals("a", keys[0]);
+assertEquals("c", keys[1]);
+
+// Check that non-enumerable properties are being returned.
+var keys = Reflect.ownKeys([1, 2]);
+assertEquals(3, keys.length);
+assertEquals("0", keys[0]);
+assertEquals("1", keys[1]);
+assertEquals("string", typeof keys[0]);
+assertEquals("string", typeof keys[1]);
+assertEquals("length", keys[2]);
+
+// Check that no proto properties are returned.
+var obj = { foo: "foo" };
+obj.__proto__ = { bar: "bar" };
+keys = Reflect.ownKeys(obj);
+assertEquals(1, keys.length);
+assertEquals("foo", keys[0]);
+
+// Check that getter properties are returned.
+var obj = {};
+obj.__defineGetter__("getter", function() {});
+keys = Reflect.ownKeys(obj);
+assertEquals(1, keys.length);
+assertEquals("getter", keys[0]);
+
+// Check that implementation does not access Array.prototype.
+var savedConcat = Array.prototype.concat;
+Array.prototype.concat = function() { return []; }
+keys = Reflect.ownKeys({0: 'foo', bar: 'baz'});
+assertEquals(2, keys.length);
+assertEquals('0', keys[0]);
+assertEquals('bar', keys[1]);
+assertSame(Array.prototype, keys.__proto__);
+Array.prototype.concat = savedConcat;
+
+assertThrows(function() { Reflect.ownKeys(4) }, TypeError);
+assertThrows(function() { Reflect.ownKeys("foo") }, TypeError);
+assertThrows(function() { Reflect.ownKeys(true) }, TypeError);
+
+assertEquals(Reflect.ownKeys(Object(4)), []);
+assertEquals(Reflect.ownKeys(Object("foo")), ["0", "1", "2", "length"]);
+assertEquals(Reflect.ownKeys(Object(true)), []);
diff --git a/test/mjsunit/es6/reflect-prevent-extensions.js b/test/mjsunit/es6/reflect-prevent-extensions.js
new file mode 100644
index 0000000..c6f3749
--- /dev/null
+++ b/test/mjsunit/es6/reflect-prevent-extensions.js
@@ -0,0 +1,164 @@
+// Copyright 2010-2015 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.
+
+// Tests the Reflect.preventExtensions method - ES6 26.1.12.
+// This is adapted from object-prevent-extensions.js.
+
+// Flags: --allow-natives-syntax
+
+
+var obj1 = {};
+// Extensible defaults to true.
+assertTrue(Object.isExtensible(obj1));
+assertTrue(Reflect.preventExtensions(obj1));
+
+// Make sure the is_extensible flag is set.
+assertFalse(Object.isExtensible(obj1));
+obj1.x = 42;
+assertEquals(undefined, obj1.x);
+
+// Try adding a new element.
+obj1[1] = 42;
+assertEquals(undefined, obj1[1]);
+
+
+// Try when the object has an existing property.
+var obj2 = {};
+assertTrue(Object.isExtensible(obj2));
+obj2.x = 42;
+assertEquals(42, obj2.x);
+assertTrue(Object.isExtensible(obj2));
+
+assertTrue(Reflect.preventExtensions(obj2));
+assertEquals(42, obj2.x);
+
+obj2.y = 42;
+// obj2.y should still be undefined.
+assertEquals(undefined, obj2.y);
+// Make sure we can still write values to obj.x.
+obj2.x = 43;
+assertEquals(43, obj2.x)
+
+obj2.y = new function() { return 42; };
+// obj2.y should still be undefined.
+assertEquals(undefined, obj2.y);
+assertEquals(43, obj2.x)
+
+try {
+ Object.defineProperty(obj2, "y", {value: 42});
+} catch (e) {
+ assertTrue(/object is not extensible/.test(e));
+}
+
+// obj2.y should still be undefined.
+assertEquals(undefined, obj2.y);
+assertEquals(43, obj2.x);
+
+obj2[1] = 42;
+assertEquals(undefined, obj2[1]);
+
+var arr = new Array();
+arr[1] = 10;
+
+assertTrue(Reflect.preventExtensions(arr));
+
+arr[2] = 42;
+assertEquals(10, arr[1]);
+
+// We should still be able to change existing elements.
+arr[1]= 42;
+assertEquals(42, arr[1]);
+
+
+// Test the the extensible flag is not inherited.
+var parent = {};
+parent.x = 42;
+assertTrue(Reflect.preventExtensions(parent));
+
+var child = Object.create(parent);
+
+// We should be able to add new properties to the child object.
+child.y = 42;
+
+// This should have no influence on the parent class.
+parent.y = 29;
+
+
+// Test that attributes on functions are also handled correctly.
+function foo() {
+ return 42;
+}
+
+assertTrue(Reflect.preventExtensions(foo));
+
+foo.x = 29;
+assertEquals(undefined, foo.x);
+
+// when Object.isExtensible(o) === false
+// assignment should return right hand side value
+var o = {};
+assertTrue(Reflect.preventExtensions(o));
+var v = o.v = 50;
+assertEquals(undefined, o.v);
+assertEquals(50, v);
+
+// test same behavior as above, but for integer properties
+var n = o[0] = 100;
+assertEquals(undefined, o[0]);
+assertEquals(100, n);
+
+// Fast properties should remain fast
+obj = { x: 42, y: 'foo' };
+assertTrue(%HasFastProperties(obj));
+assertTrue(Reflect.preventExtensions(obj));
+assertFalse(Object.isExtensible(obj));
+assertFalse(Object.isSealed(obj));
+assertTrue(%HasFastProperties(obj));
+
+// Non-extensible objects should share maps where possible
+obj = { prop1: 1, prop2: 2 };
+obj2 = { prop1: 3, prop2: 4 };
+assertTrue(%HaveSameMap(obj, obj2));
+assertTrue(Reflect.preventExtensions(obj));
+assertTrue(Reflect.preventExtensions(obj2));
+assertFalse(Object.isExtensible(obj));
+assertFalse(Object.isExtensible(obj2));
+assertFalse(Object.isSealed(obj));
+assertFalse(Object.isSealed(obj2));
+assertTrue(%HaveSameMap(obj, obj2));
+
+// Non-extensible objects should share maps even when they have elements
+obj = { prop1: 1, prop2: 2, 75: 'foo' };
+obj2 = { prop1: 3, prop2: 4, 150: 'bar' };
+assertTrue(%HaveSameMap(obj, obj2));
+assertTrue(Reflect.preventExtensions(obj));
+assertTrue(Reflect.preventExtensions(obj2));
+assertFalse(Object.isExtensible(obj));
+assertFalse(Object.isExtensible(obj2));
+assertFalse(Object.isSealed(obj));
+assertFalse(Object.isSealed(obj2));
+assertTrue(%HaveSameMap(obj, obj2));
diff --git a/test/mjsunit/es6/reflect-set-prototype-of.js b/test/mjsunit/es6/reflect-set-prototype-of.js
new file mode 100644
index 0000000..8f2a00a
--- /dev/null
+++ b/test/mjsunit/es6/reflect-set-prototype-of.js
@@ -0,0 +1,182 @@
+// Copyright 2014-2015 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.
+
+// This is adapted from mjsunit/harmony/set-prototype-of.js.
+
+
+
+function getObjects() {
+ function func() {}
+ return [
+ func,
+ new func(),
+ {x: 5},
+ /regexp/,
+ ['array'],
+ // new Error(),
+ new Date(),
+ new Number(1),
+ new Boolean(true),
+ new String('str'),
+ Object(Symbol())
+ ];
+}
+
+
+var coercibleValues = [
+ 1,
+ true,
+ 'string',
+ Symbol()
+];
+
+
+var nonCoercibleValues = [
+ undefined,
+ null
+];
+
+
+var valuesWithoutNull = coercibleValues.concat(undefined);
+
+
+function TestSetPrototypeOfCoercibleValues() {
+ for (var i = 0; i < coercibleValues.length; i++) {
+ var value = coercibleValues[i];
+ var proto = Object.getPrototypeOf(value);
+ assertThrows(function() { Reflect.setPrototypeOf(value, {}) }, TypeError);
+ assertSame(proto, Object.getPrototypeOf(value));
+ }
+}
+TestSetPrototypeOfCoercibleValues();
+
+
+function TestSetPrototypeOfNonCoercibleValues() {
+ for (var i = 0; i < nonCoercibleValues.length; i++) {
+ var value = nonCoercibleValues[i];
+ assertThrows(function() {
+ Reflect.setPrototypeOf(value, {});
+ }, TypeError);
+ }
+}
+TestSetPrototypeOfNonCoercibleValues();
+
+
+function TestSetPrototypeToNonObject(proto) {
+ var objects = getObjects();
+ for (var i = 0; i < objects.length; i++) {
+ var object = objects[i];
+ for (var j = 0; j < valuesWithoutNull.length; j++) {
+ var proto = valuesWithoutNull[j];
+ assertThrows(function() {
+ Reflect.setPrototypeOf(object, proto);
+ }, TypeError);
+ }
+ }
+}
+TestSetPrototypeToNonObject();
+
+
+function TestSetPrototypeOf(object, proto) {
+ assertTrue(Reflect.setPrototypeOf(object, proto));
+ assertEquals(Object.getPrototypeOf(object), proto);
+}
+
+
+function TestSetPrototypeOfForObjects() {
+ var objects1 = getObjects();
+ var objects2 = getObjects();
+ for (var i = 0; i < objects1.length; i++) {
+ for (var j = 0; j < objects2.length; j++) {
+ TestSetPrototypeOf(objects1[i], objects2[j]);
+ }
+ }
+}
+TestSetPrototypeOfForObjects();
+
+
+function TestSetPrototypeToNull() {
+ var objects = getObjects();
+ for (var i = 0; i < objects.length; i++) {
+ TestSetPrototypeOf(objects[i], null);
+ }
+}
+TestSetPrototypeToNull();
+
+
+function TestSetPrototypeOfNonExtensibleObject() {
+ var objects = getObjects();
+ var proto = {};
+ for (var i = 0; i < objects.length; i++) {
+ var object = objects[i];
+ Object.preventExtensions(object);
+ // Setting the current prototype must succeed.
+ assertTrue(Reflect.setPrototypeOf(object, Object.getPrototypeOf(object)));
+ // Setting any other must fail.
+ assertFalse(Reflect.setPrototypeOf(object, proto));
+ }
+}
+TestSetPrototypeOfNonExtensibleObject();
+
+
+function TestSetPrototypeCyclic() {
+ var objects = [
+ Object.prototype, {},
+ Array.prototype, [],
+ Error.prototype, new TypeError,
+ // etc ...
+ ];
+ for (var i = 0; i < objects.length; i += 2) {
+ var object = objects[i];
+ var value = objects[i + 1];
+ assertFalse(Reflect.setPrototypeOf(object, value));
+ }
+}
+TestSetPrototypeCyclic();
+
+
+function TestLookup() {
+ var object = {};
+ assertFalse('x' in object);
+ assertFalse('y' in object);
+
+ var oldProto = {
+ x: 'old x',
+ y: 'old y'
+ };
+ assertTrue(Reflect.setPrototypeOf(object, oldProto));
+ assertEquals(object.x, 'old x');
+ assertEquals(object.y, 'old y');
+
+ var newProto = {
+ x: 'new x'
+ };
+ assertTrue(Reflect.setPrototypeOf(object, newProto));
+ assertEquals(object.x, 'new x');
+ assertFalse('y' in object);
+}
+TestLookup();
diff --git a/test/mjsunit/es6/reflect.js b/test/mjsunit/es6/reflect.js
new file mode 100644
index 0000000..ee272b0
--- /dev/null
+++ b/test/mjsunit/es6/reflect.js
@@ -0,0 +1,570 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO(neis): Test with proxies.
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// (Auxiliaries)
+
+
+"use strict";
+
+var global = this;
+
+var sym = Symbol("gaga");
+
+var objects = [
+ {},
+ [],
+ function() {},
+ function() {
+ return arguments;
+ }(),
+ function() {
+ 'use strict';
+ return arguments;
+ }(),
+ Object(1),
+ Object(true),
+ Object('bla'),
+ new Date,
+ new RegExp,
+ new Set,
+ new Map,
+ new WeakMap,
+ new WeakSet,
+ new ArrayBuffer(10),
+ new Int32Array(5),
+ Object,
+ Function,
+ Date,
+ RegExp,
+ global
+];
+
+function prepare(target) {
+ target["bla"] = true;
+ target[4] = 42;
+ target[sym] = "foo";
+ target["noconf"] = 43;
+ Object.defineProperty(target, "noconf",
+ { configurable: false });
+ Object.defineProperty(target, "nowrite",
+ { writable: false, configurable: true, value: 44 });
+ Object.defineProperty(target, "getter",
+ { get: function () {return this.bla}, configurable: true });
+ Object.defineProperty(target, "setter",
+ { set: function (x) {this.gaga = x}, configurable: true });
+ Object.defineProperty(target, "setter2",
+ { set: function (x) {}, configurable: true });
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Reflect.get
+
+
+(function testReflectGetArity() {
+ assertEquals(2, Reflect.get.length);
+})();
+
+
+(function testReflectGetOnNonObject() {
+ assertThrows(function() { Reflect.get(); }, TypeError);
+ assertThrows(function() { Reflect.get(42, "bla"); }, TypeError);
+ assertThrows(function() { Reflect.get(null, "bla"); }, TypeError);
+})();
+
+
+(function testReflectGetKeyConversion() {
+ var target = {bla: 42};
+ var a = { [Symbol.toPrimitive]: function() { return "bla" } };
+ var b = { [Symbol.toPrimitive]: function() { throw "gaga" } };
+ assertEquals(42, Reflect.get(target, a));
+ assertThrowsEquals(function() { Reflect.get(target, b); }, "gaga");
+})();
+
+
+(function testReflectGetOnObject() {
+ var receiver = {bla: false};
+ for (let target of objects) {
+ prepare(target);
+ assertEquals(true, Reflect.get(target, "bla"));
+ assertEquals(true, Reflect.get(target, "bla", target));
+ assertEquals(true, Reflect.get(target, "bla", receiver));
+ assertEquals(42, Reflect.get(target, 4));
+ assertEquals(42, Reflect.get(target, 4, target));
+ assertEquals(42, Reflect.get(target, 4, receiver));
+ assertEquals(42, Reflect.get(target, "4"));
+ assertEquals(42, Reflect.get(target, "4", target));
+ assertEquals(42, Reflect.get(target, "4", receiver));
+ assertEquals("foo", Reflect.get(target, sym));
+ assertEquals("foo", Reflect.get(target, sym, target));
+ assertEquals("foo", Reflect.get(target, sym, receiver));
+ assertEquals(43, Reflect.get(target, "noconf"));
+ assertEquals(43, Reflect.get(target, "noconf", target));
+ assertEquals(43, Reflect.get(target, "noconf", receiver));
+ assertEquals(true, Reflect.get(target, "getter"));
+ assertEquals(true, Reflect.get(target, "getter", target));
+ assertEquals(false, Reflect.get(target, "getter", receiver));
+ assertEquals(undefined, Reflect.get(target, "setter"));
+ assertEquals(undefined, Reflect.get(target, "setter", target));
+ assertEquals(undefined, Reflect.get(target, "setter", receiver));
+ assertEquals(undefined, Reflect.get(target, "foo"));
+ assertEquals(undefined, Reflect.get(target, "foo", target));
+ assertEquals(undefined, Reflect.get(target, "foo", receiver));
+ assertEquals(undefined, Reflect.get(target, 666));
+ assertEquals(undefined, Reflect.get(target, 666, target));
+ assertEquals(undefined, Reflect.get(target, 666, receiver));
+
+ let proto = target.__proto__;
+ target.__proto__ = { get foo() {return this.bla} };
+ assertEquals(true, Reflect.get(target, "foo"));
+ assertEquals(true, Reflect.get(target, "foo", target));
+ assertEquals(false, Reflect.get(target, "foo", receiver));
+ target.__proto__ = proto;
+ }
+})();
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Reflect.set
+
+
+(function testReflectSetArity() {
+ assertEquals(3, Reflect.set.length);
+})();
+
+
+(function testReflectSetOnNonObject() {
+ assertThrows(function() { Reflect.set(); }, TypeError);
+ assertThrows(function() { Reflect.set(42, "bla"); }, TypeError);
+ assertThrows(function() { Reflect.set(null, "bla"); }, TypeError);
+})();
+
+
+(function testReflectSetKeyConversion() {
+ var target = {};
+ var a = { [Symbol.toPrimitive]: function() { return "bla" } };
+ var b = { [Symbol.toPrimitive]: function() { throw "gaga" } };
+ assertTrue(Reflect.set(target, a, 42));
+ assertEquals(42, target.bla);
+ assertThrowsEquals(function() { Reflect.set(target, b, 42); }, "gaga");
+})();
+
+
+(function testReflectSetOnObject() {
+ var receiver = {bla: false};
+ var value = 34234;
+ for (let target of objects) {
+ prepare(target);
+ assertTrue(Reflect.set(target, "bla", value));
+ assertEquals(value, target.bla);
+
+ prepare(target);
+ assertTrue(Reflect.set(target, "bla", value, target));
+ assertEquals(value, target.bla);
+
+ prepare(target);
+ assertTrue(Reflect.set(target, "bla", value, receiver));
+ assertEquals(true, target.bla);
+ assertEquals(value, receiver.bla);
+ receiver.bla = false;
+
+ prepare(target);
+ assertTrue(Reflect.set(target, 4, value));
+ assertEquals(value, target[4]);
+
+ prepare(target);
+ assertTrue(Reflect.set(target, 4, value, target));
+ assertEquals(value, target[4]);
+
+ prepare(target);
+ assertTrue(Reflect.set(target, 4, value, receiver));
+ assertEquals(42, target[4]);
+ assertEquals(value, receiver[4]);
+ delete receiver[4];
+
+ prepare(target);
+ assertTrue(Reflect.set(target, sym, value));
+ assertEquals(value, target[sym]);
+
+ prepare(target);
+ assertTrue(Reflect.set(target, sym, value, target));
+ assertEquals(value, target[sym]);
+
+ prepare(target);
+ assertTrue(Reflect.set(target, sym, value, receiver));
+ assertEquals("foo", target[sym]);
+ assertEquals(value, receiver[sym]);
+ delete receiver[sym];
+
+ prepare(target);
+ assertTrue(Reflect.set(target, "noconf", value));
+ assertEquals(value, target.noconf);
+
+ prepare(target);
+ assertTrue(Reflect.set(target, "noconf", value, target));
+ assertEquals(value, target.noconf);
+
+ prepare(target);
+ assertTrue(Reflect.set(target, "noconf", value, receiver));
+ assertEquals(43, target.noconf);
+ assertEquals(value, receiver.noconf);
+ delete receiver.noconf;
+
+ assertTrue(Reflect.set(target, "setter", value));
+ assertEquals(value, target.gaga)
+ delete target.gaga;
+
+ assertTrue(Reflect.set(target, "setter", value, target));
+ assertEquals(value, target.gaga)
+ delete target.gaga;
+
+ assertTrue(Reflect.set(target, "setter", value, receiver));
+ assertFalse("gaga" in target);
+ assertEquals(value, receiver.gaga);
+ delete receiver.gaga;
+
+ assertFalse(Reflect.set(target, "nowrite", value));
+ assertEquals(44, target.nowrite);
+
+ assertFalse(Reflect.set(target, "nowrite", value, target));
+ assertEquals(44, target.nowrite);
+
+ assertFalse(Reflect.set(target, "nowrite", value, receiver));
+ assertEquals(44, target.nowrite);
+ assertFalse("nowrite" in receiver);
+
+ // Data vs Non-Writable
+ assertFalse(Reflect.set({}, "nowrite", value, target));
+
+ // Data vs Accessor
+ assertFalse(Reflect.set({}, "unknown", 0, {set unknown(x) {}}));
+ assertFalse(Reflect.set(target, "unknown", value, {set unknown(x) {}}));
+ assertFalse(Reflect.set(target, "bla", value, {set bla(x) {}}));
+ assertFalse(Reflect.set(target, "bla", value, {get bla() {}}));
+
+ // Accessor vs Data
+ assertTrue(Reflect.set({set bla(x) {}}), "bla", value, target);
+ assertFalse(Reflect.set({get bla() {}}, "bla", value, target));
+
+ // Data vs Non-Object
+ assertFalse(Reflect.set({}, "bla", value, null));
+ assertFalse(Reflect.set({bla: 42}, "bla", value, null));
+
+ // Accessor vs Non-Object
+ assertTrue(Reflect.set(target, "setter2", value, null));
+ assertFalse(Reflect.set(target, "getter", value, null));
+
+ let receiver2 = {};
+ Object.defineProperty(receiver2, "bla",
+ {configurable: false, writable: true, value: true});
+ Object.defineProperty(receiver2, "not_in_target",
+ {configurable: false, writable: true, value: true});
+ assertTrue(Reflect.set(target, "bla", value, receiver2));
+ assertTrue(Reflect.set(target, "not_in_target", value, receiver2));
+ }
+})();
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Reflect.has
+
+
+(function testReflectHasArity() {
+ assertEquals(2, Reflect.has.length);
+})();
+
+
+(function testReflectHasOnNonObject() {
+ assertThrows(function() { Reflect.has(); }, TypeError);
+ assertThrows(function() { Reflect.has(42, "bla"); }, TypeError);
+ assertThrows(function() { Reflect.has(null, "bla"); }, TypeError);
+})();
+
+
+(function testReflectHasKeyConversion() {
+ var target = {bla: 42};
+ var a = { [Symbol.toPrimitive]: function() { return "bla" } };
+ var b = { [Symbol.toPrimitive]: function() { throw "gaga" } };
+ assertTrue(Reflect.has(target, a));
+ assertThrowsEquals(function() { Reflect.has(target, b); }, "gaga");
+})();
+
+
+(function testReflectHasOnObject() {
+ for (let target of objects) {
+ prepare(target);
+ assertTrue(Reflect.has(target, "bla"));
+ assertTrue(Reflect.has(target, 4));
+ assertTrue(Reflect.has(target, "4"));
+ assertTrue(Reflect.has(target, sym));
+ assertTrue(Reflect.has(target, "noconf"));
+ assertTrue(Reflect.has(target, "getter"));
+ assertTrue(Reflect.has(target, "setter"));
+ assertFalse(Reflect.has(target, "foo"));
+ assertFalse(Reflect.has(target, 666));
+
+ let proto = target.__proto__;
+ target.__proto__ = { get foo() {return this.bla} };
+ assertEquals(true, Reflect.has(target, "foo"));
+ target.__proto__ = proto;
+ }
+})();
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Reflect.defineProperty
+
+
+(function testReflectDefinePropertyArity() {
+ assertEquals(3, Reflect.defineProperty.length);
+})();
+
+
+(function testReflectDefinePropertyOnNonObject() {
+ assertThrows(function() { Reflect.defineProperty(); }, TypeError);
+ assertThrows(function() { Reflect.defineProperty(42, "bla"); }, TypeError);
+ assertThrows(function() { Reflect.defineProperty(null, "bla"); }, TypeError);
+ assertThrows(function() { Reflect.defineProperty({}, "bla"); }, TypeError);
+ assertThrows(function() { Reflect.defineProperty({}, "bla", 42); },
+ TypeError);
+ assertThrows(function() { Reflect.defineProperty({}, "bla", null); },
+ TypeError);
+})();
+
+
+(function testReflectDefinePropertyKeyConversion() {
+ var target = {};
+ var a = { [Symbol.toPrimitive]: function() { return "bla" } };
+ var b = { [Symbol.toPrimitive]: function() { throw "gaga" } };
+ assertTrue(Reflect.defineProperty(target, a, {value: 42}));
+ assertEquals(target.bla, 42);
+ assertThrowsEquals(function() { Reflect.defineProperty(target, b); }, "gaga");
+})();
+
+
+// See reflect-define-property.js for further tests.
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Reflect.deleteProperty
+
+
+(function testReflectDeletePropertyArity() {
+ assertEquals(2, Reflect.deleteProperty.length);
+})();
+
+
+(function testReflectDeletePropertyOnNonObject() {
+ assertThrows(function() { Reflect.deleteProperty(); }, TypeError);
+ assertThrows(function() { Reflect.deleteProperty(42, "bla"); }, TypeError);
+ assertThrows(function() { Reflect.deleteProperty(null, "bla"); }, TypeError);
+})();
+
+
+(function testReflectDeletePropertyKeyConversion() {
+ var target = {bla: 42};
+ var a = { [Symbol.toPrimitive]: function() { return "bla" } };
+ var b = { [Symbol.toPrimitive]: function() { throw "gaga" } };
+ assertTrue(Reflect.deleteProperty(target, a));
+ assertThrowsEquals(function() { Reflect.deleteProperty(target, b); }, "gaga");
+})();
+
+
+(function testReflectDeletePropertyOnObject() {
+ for (let target of objects) {
+ prepare(target);
+ assertTrue(Reflect.deleteProperty(target, "bla"));
+ assertEquals(undefined, Object.getOwnPropertyDescriptor(target, "bla"));
+ if (target instanceof Int32Array) {
+ assertFalse(Reflect.deleteProperty(target, 4));
+ } else {
+ assertTrue(Reflect.deleteProperty(target, 4));
+ assertEquals(undefined, Object.getOwnPropertyDescriptor(target, 4));
+ }
+ assertTrue(Reflect.deleteProperty(target, sym));
+ assertEquals(undefined, Object.getOwnPropertyDescriptor(target, sym));
+ assertFalse(Reflect.deleteProperty(target, "noconf"));
+ assertEquals(43, target.noconf);
+ assertTrue(Reflect.deleteProperty(target, "getter"));
+ assertTrue(Reflect.deleteProperty(target, "setter"));
+ assertTrue(Reflect.deleteProperty(target, "foo"));
+ assertTrue(Reflect.deleteProperty(target, 666));
+
+ let proto = target.__proto__;
+ target.__proto__ = { get foo() {return this.bla} };
+ assertEquals(true, Reflect.deleteProperty(target, "foo"));
+ target.__proto__ = proto;
+ }
+})();
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Reflect.getPrototypeOf
+
+
+(function testReflectGetPrototypeOfArity() {
+ assertEquals(1, Reflect.getPrototypeOf.length);
+})();
+
+
+(function testReflectGetPrototypeOnNonObject() {
+ assertThrows(function() { Reflect.getPrototypeOf(); }, TypeError);
+ assertThrows(function() { Reflect.getPrototypeOf(42); }, TypeError);
+ assertThrows(function() { Reflect.getPrototypeOf(null); }, TypeError);
+})();
+
+
+// See reflect-get-prototype-of.js for further tests.
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Reflect.setPrototypeOf
+
+
+(function testReflectSetPrototypeOfArity() {
+ assertEquals(2, Reflect.setPrototypeOf.length);
+})();
+
+
+(function testReflectSetPrototypeOfOnNonObject() {
+ assertThrows(function() { Reflect.setPrototypeOf(undefined, {}); },
+ TypeError);
+ assertThrows(function() { Reflect.setPrototypeOf(42, {}); }, TypeError);
+ assertThrows(function() { Reflect.setPrototypeOf(null, {}); }, TypeError);
+
+ assertThrows(function() { Reflect.setPrototypeOf({}, undefined); },
+ TypeError);
+ assertThrows(function() { Reflect.setPrototypeOf({}, 42); }, TypeError);
+ assertTrue(Reflect.setPrototypeOf({}, null));
+})();
+
+
+// See reflect-set-prototype-of.js for further tests.
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Reflect.isExtensible
+
+
+(function testReflectIsExtensibleArity() {
+ assertEquals(1, Reflect.isExtensible.length);
+})();
+
+
+(function testReflectIsExtensibleOnNonObject() {
+ assertThrows(function() { Reflect.isExtensible(); }, TypeError);
+ assertThrows(function() { Reflect.isExtensible(42); }, TypeError);
+ assertThrows(function() { Reflect.isExtensible(null); }, TypeError);
+})();
+
+
+(function testReflectIsExtensibleOnObject() {
+ // This should be the last test on [objects] as it modifies them irreversibly.
+ for (let target of objects) {
+ prepare(target);
+ if (target instanceof Int32Array) continue; // issue v8:4460
+ assertTrue(Reflect.isExtensible(target));
+ Object.preventExtensions(target);
+ assertFalse(Reflect.isExtensible(target));
+ }
+})();
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Reflect.getOwnPropertyDescriptor
+
+
+(function testReflectGetOwnPropertyDescriptorArity() {
+ assertEquals(2, Reflect.getOwnPropertyDescriptor.length);
+})();
+
+
+(function testReflectGetOwnPropertyDescriptorOnNonObject() {
+ assertThrows(function() { Reflect.getOwnPropertyDescriptor(); }, TypeError);
+ assertThrows(function() { Reflect.getOwnPropertyDescriptor(42); },
+ TypeError);
+ assertThrows(function() { Reflect.getOwnPropertyDescriptor(null); },
+ TypeError);
+})();
+
+
+(function testReflectGetOwnPropertyDescriptorKeyConversion() {
+ var target = {bla: 42};
+ var a = { [Symbol.toPrimitive]: function() { return "bla" } };
+ var b = { [Symbol.toPrimitive]: function() { throw "gaga" } };
+ assertEquals(42, Reflect.getOwnPropertyDescriptor(target, a).value);
+ assertThrowsEquals(() => Reflect.getOwnPropertyDescriptor(target, b), "gaga");
+})();
+
+
+// See reflect-get-own-property-descriptor.js for further tests.
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Reflect.ownKeys
+
+
+(function testReflectOwnKeysArity() {
+ assertEquals(1, Reflect.ownKeys.length);
+})();
+
+
+(function testReflectOwnKeysOnNonObject() {
+ assertThrows(function() { Reflect.ownKeys(); }, TypeError);
+ assertThrows(function() { Reflect.ownKeys(42); }, TypeError);
+ assertThrows(function() { Reflect.ownKeys(null); }, TypeError);
+})();
+
+
+(function testReflectOwnKeysOnObject(){
+ assertEquals(["z", "y", "x"], Reflect.ownKeys({z: 3, y: 2, x: 1}));
+ assertEquals(["length"], Reflect.ownKeys([]));
+
+ var s1 = Symbol("foo");
+ var s2 = Symbol("bar");
+ var obj = { [s1]: 0, "bla": 0, 42: 0, "0": 0,
+ [s2]: 0, "-1": 0, "88": 0, "aaa": 0 };
+ assertEquals(["0", "42", "88", "bla", "-1", "aaa", s1, s2],
+ Reflect.ownKeys(obj));
+})();
+
+
+// See reflect-own-keys.js for further tests.
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Reflect.preventExtensions
+
+
+(function testReflectPreventExtensionsArity() {
+ assertEquals(1, Reflect.preventExtensions.length);
+})();
+
+
+(function testReflectPreventExtensionsOnNonObject() {
+ assertThrows(function() { Reflect.preventExtensions(); }, TypeError);
+ assertThrows(function() { Reflect.preventExtensions(42); }, TypeError);
+ assertThrows(function() { Reflect.preventExtensions(null); }, TypeError);
+})();
+
+
+// See reflect-prevent-extensions.js for further tests.
+
+// TODO(neis): Need proxies to test the situation where
+// [[preventExtensions]] returns false.
diff --git a/test/mjsunit/es6/regexp-constructor.js b/test/mjsunit/es6/regexp-constructor.js
index e3b7efa..559ac00 100644
--- a/test/mjsunit/es6/regexp-constructor.js
+++ b/test/mjsunit/es6/regexp-constructor.js
@@ -21,32 +21,47 @@
})();
(function() {
+ let allow = false;
class A extends RegExp {
- get source() { throw new Error("should not be called") }
- get flags() { throw new Error("should not be called") }
+ get source() {
+ if (!allow) throw new Error("should not be called");
+ return super.source;
+ }
+ get flags() {
+ if (!allow) throw new Error("should not be called");
+ return super.flags
+ }
}
var r = new A("biep");
var r2 = RegExp(r);
assertFalse(r === r2);
+ allow = true;
assertEquals(r, r2);
+ allow = false;
assertTrue(A.prototype === r.__proto__);
assertTrue(RegExp.prototype === r2.__proto__);
var r3 = RegExp(r);
assertFalse(r3 === r);
+ allow = true;
assertEquals(r3, r);
+ allow = false;
var r4 = new A(r2);
assertFalse(r4 === r2);
+ allow = true;
assertEquals(r4, r2);
+ allow = false;
assertTrue(A.prototype === r4.__proto__);
r[Symbol.match] = false;
var r5 = new A(r);
assertFalse(r5 === r);
+ allow = true;
assertEquals(r5, r);
+ allow = false;
assertTrue(A.prototype === r5.__proto__);
})();
diff --git a/test/mjsunit/es6/regexp-flags.js b/test/mjsunit/es6/regexp-flags.js
index 79b0197..480222d 100644
--- a/test/mjsunit/es6/regexp-flags.js
+++ b/test/mjsunit/es6/regexp-flags.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-regexps --harmony-unicode-regexps
+// Flags: --harmony-unicode-regexps
var r1 = /abc/gi;
assertEquals("abc", r1.source);
@@ -44,15 +44,18 @@
// Overridden flag getters affects the flags getter.
assertEquals("gi", r3.flags);
assertEquals(4, get_count);
-// Overridden flag getters do not affect the internal flags.
+// Overridden flag getters affect string.replace
+// TODO(adamk): Add more tests here once we've switched
+// to use [[OriginalFlags]] in more cases.
assertEquals(expected, string.replace(r3, "X"));
-assertEquals(4, get_count);
+assertEquals(5, get_count);
function testName(name) {
- // TODO(littledan): For web compatibility, we don't throw an exception,
- // but ES2015 expects an exception to be thrown from this getter.
- assertEquals(undefined, RegExp.prototype[name]);
+ // Test for ES2017 RegExp web compatibility semantics
+ // https://github.com/tc39/ecma262/pull/511
+ assertEquals(name === "source" ? "(?:)" : undefined,
+ RegExp.prototype[name]);
assertEquals(
"get " + name,
Object.getOwnPropertyDescriptor(RegExp.prototype, name).get.name);
@@ -64,3 +67,55 @@
testName("source");
testName("sticky");
testName("unicode");
+
+
+RegExp.prototype.flags = 'setter should be undefined';
+
+assertEquals('', RegExp('').flags);
+assertEquals('', /./.flags);
+assertEquals('gimuy', RegExp('', 'yugmi').flags);
+assertEquals('gimuy', /foo/yumig.flags);
+
+var descriptor = Object.getOwnPropertyDescriptor(RegExp.prototype, 'flags');
+assertTrue(descriptor.configurable);
+assertFalse(descriptor.enumerable);
+assertInstanceof(descriptor.get, Function);
+assertEquals(undefined, descriptor.set);
+
+function testGenericFlags(object) {
+ return descriptor.get.call(object);
+}
+
+assertEquals('', testGenericFlags({}));
+assertEquals('i', testGenericFlags({ ignoreCase: true }));
+assertEquals('uy', testGenericFlags({ global: 0, sticky: 1, unicode: 1 }));
+assertEquals('m', testGenericFlags({ __proto__: { multiline: true } }));
+assertThrows(function() { testGenericFlags(); }, TypeError);
+assertThrows(function() { testGenericFlags(undefined); }, TypeError);
+assertThrows(function() { testGenericFlags(null); }, TypeError);
+assertThrows(function() { testGenericFlags(true); }, TypeError);
+assertThrows(function() { testGenericFlags(false); }, TypeError);
+assertThrows(function() { testGenericFlags(''); }, TypeError);
+assertThrows(function() { testGenericFlags(42); }, TypeError);
+
+var counter = 0;
+var map = {};
+var object = {
+ get global() {
+ map.g = counter++;
+ },
+ get ignoreCase() {
+ map.i = counter++;
+ },
+ get multiline() {
+ map.m = counter++;
+ },
+ get unicode() {
+ map.u = counter++;
+ },
+ get sticky() {
+ map.y = counter++;
+ }
+};
+testGenericFlags(object);
+assertEquals({ g: 0, i: 1, m: 2, u: 3, y: 4 }, map);
diff --git a/test/mjsunit/es6/regexp-sticky.js b/test/mjsunit/es6/regexp-sticky.js
new file mode 100644
index 0000000..c0633f9
--- /dev/null
+++ b/test/mjsunit/es6/regexp-sticky.js
@@ -0,0 +1,130 @@
+// Copyright 2014 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.
+
+var re = /foo.bar/;
+
+assertTrue(!!"foo*bar".match(re));
+assertTrue(!!"..foo*bar".match(re));
+
+var plain = /foobar/;
+
+assertTrue(!!"foobar".match(plain));
+assertTrue(!!"..foobar".match(plain));
+
+var sticky = /foo.bar/y;
+
+assertTrue(!!"foo*bar".match(sticky));
+assertEquals(7, sticky.lastIndex);
+assertFalse(!!"..foo*bar".match(sticky));
+
+var stickyplain = /foobar/y;
+
+assertTrue(!!"foobar".match(stickyplain));
+assertEquals(6, stickyplain.lastIndex);
+assertFalse(!!"..foobar".match(stickyplain));
+
+var global = /foo.bar/g;
+
+assertTrue(global.test("foo*bar"));
+assertFalse(global.test("..foo*bar"));
+global.lastIndex = 0;
+assertTrue(global.test("..foo*bar"));
+
+var plainglobal = /foobar/g;
+
+assertTrue(plainglobal.test("foobar"));
+assertFalse(plainglobal.test("foobar"));
+plainglobal.lastIndex = 0;
+assertTrue(plainglobal.test("foobar"));
+
+var stickyglobal = /foo.bar/gy;
+
+assertTrue(stickyglobal.test("foo*bar"));
+assertEquals(7, stickyglobal.lastIndex);
+assertFalse(stickyglobal.test("..foo*bar"));
+stickyglobal.lastIndex = 0;
+assertFalse(stickyglobal.test("..foo*bar"));
+stickyglobal.lastIndex = 2;
+assertTrue(stickyglobal.test("..foo*bar"));
+assertEquals(9, stickyglobal.lastIndex);
+
+var stickyplainglobal = /foobar/yg;
+assertTrue(stickyplainglobal.sticky);
+stickyplainglobal.sticky = false;
+
+assertTrue(stickyplainglobal.test("foobar"));
+assertEquals(6, stickyplainglobal.lastIndex);
+assertFalse(stickyplainglobal.test("..foobar"));
+stickyplainglobal.lastIndex = 0;
+assertFalse(stickyplainglobal.test("..foobar"));
+stickyplainglobal.lastIndex = 2;
+assertTrue(stickyplainglobal.test("..foobar"));
+assertEquals(8, stickyplainglobal.lastIndex);
+
+assertEquals("/foo.bar/gy", "" + stickyglobal);
+assertEquals("/foo.bar/g", "" + global);
+
+assertTrue(stickyglobal.sticky);
+stickyglobal.sticky = false;
+assertTrue(stickyglobal.sticky);
+
+var stickyglobal2 = new RegExp("foo.bar", "gy");
+assertTrue(stickyglobal2.test("foo*bar"));
+assertEquals(7, stickyglobal2.lastIndex);
+assertFalse(stickyglobal2.test("..foo*bar"));
+stickyglobal2.lastIndex = 0;
+assertFalse(stickyglobal2.test("..foo*bar"));
+stickyglobal2.lastIndex = 2;
+assertTrue(stickyglobal2.test("..foo*bar"));
+assertEquals(9, stickyglobal2.lastIndex);
+
+assertEquals("/foo.bar/gy", "" + stickyglobal2);
+
+assertTrue(stickyglobal2.sticky);
+stickyglobal2.sticky = false;
+assertTrue(stickyglobal2.sticky);
+
+sticky.lastIndex = -1; // Causes sticky regexp to fail fast
+assertFalse(sticky.test("..foo.bar"));
+assertEquals(0, sticky.lastIndex);
+
+sticky.lastIndex = -1; // Causes sticky regexp to fail fast
+assertFalse(!!sticky.exec("..foo.bar"));
+assertEquals(0, sticky.lastIndex);
+
+// ES6 draft says: Even when the y flag is used with a pattern, ^ always
+// matches only at the beginning of Input, or (if Multiline is true) at the
+// beginning of a line.
+var hat = /^foo/y;
+hat.lastIndex = 2;
+assertFalse(hat.test("..foo"));
+
+var mhat = /^foo/my;
+mhat.lastIndex = 2;
+assertFalse(mhat.test("..foo"));
+mhat.lastIndex = 2;
+assertTrue(mhat.test(".\nfoo"));
diff --git a/test/mjsunit/es6/regexp-tostring.js b/test/mjsunit/es6/regexp-tostring.js
index 3deeeb7..23e137c 100644
--- a/test/mjsunit/es6/regexp-tostring.js
+++ b/test/mjsunit/es6/regexp-tostring.js
@@ -44,3 +44,14 @@
assertEquals("/pattern/flags", RegExp.prototype.toString.call(fake));
assertEquals(["p", "ps", "f", "fs"], log);
+
+// Monkey-patching is also possible on RegExp instances
+
+let weird = /foo/;
+Object.defineProperty(weird, 'flags', {value: 'bar'});
+Object.defineProperty(weird, 'source', {value: 'baz'});
+assertEquals('/baz/bar', weird.toString());
+
+assertEquals('/(?:)/', RegExp.prototype.toString());
+assertEquals('(?:)', RegExp.prototype.source);
+assertEquals('', RegExp.prototype.flags);
diff --git a/test/mjsunit/es6/regress/regress-2219.js b/test/mjsunit/es6/regress/regress-2219.js
new file mode 100644
index 0000000..79f5bfb
--- /dev/null
+++ b/test/mjsunit/es6/regress/regress-2219.js
@@ -0,0 +1,32 @@
+// 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: --expose-gc
+
+var p = new Proxy({}, {getOwnPropertyDescriptor: function() { gc() }});
+var o = Object.create(p);
+assertSame(23, o.x = 23);
diff --git a/test/mjsunit/es6/regress/regress-2225.js b/test/mjsunit/es6/regress/regress-2225.js
new file mode 100644
index 0000000..cb5cd8c
--- /dev/null
+++ b/test/mjsunit/es6/regress/regress-2225.js
@@ -0,0 +1,74 @@
+// 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.
+
+var proxy_has_x = false;
+var proxy = new Proxy({}, {
+ get(t, key, receiver) {
+ assertSame('x', key);
+ if (proxy_has_x) { return 19 }
+ return 8;
+ }
+});
+
+// Test __lookupGetter__/__lookupSetter__ with proxy.
+assertSame(undefined, Object.prototype.__lookupGetter__.call(proxy, 'foo'));
+assertSame(undefined, Object.prototype.__lookupSetter__.call(proxy, 'bar'));
+assertSame(undefined, Object.prototype.__lookupGetter__.call(proxy, '123'));
+assertSame(undefined, Object.prototype.__lookupSetter__.call(proxy, '456'));
+
+// Test __lookupGetter__/__lookupSetter__ with proxy in prototype chain.
+var object = Object.create(proxy);
+assertSame(undefined, Object.prototype.__lookupGetter__.call(object, 'foo'));
+assertSame(undefined, Object.prototype.__lookupSetter__.call(object, 'bar'));
+assertSame(undefined, Object.prototype.__lookupGetter__.call(object, '123'));
+assertSame(undefined, Object.prototype.__lookupSetter__.call(object, '456'));
+
+// Test inline constructors with proxy as prototype.
+function F() { this.x = 42 }
+F.prototype = proxy;
+var instance = new F();
+
+proxy_has_x = false;
+assertSame(42, instance.x);
+delete instance.x;
+assertSame(8, instance.x);
+
+proxy_has_x = true;
+assertSame(19, instance.x);
+
+// Test inline constructors with proxy in prototype chain.
+function G() { this.x = 42; }
+G.prototype.__proto__ = proxy;
+instance = new G();
+
+proxy_has_x = false;
+assertSame(42, instance.x);
+delete instance.x;
+assertSame(8, instance.x);
+
+proxy_has_x = true;
+assertSame(19, instance.x);
diff --git a/test/mjsunit/es6/regress/regress-4395-global-eval.js b/test/mjsunit/es6/regress/regress-4395-global-eval.js
new file mode 100644
index 0000000..72a0ece
--- /dev/null
+++ b/test/mjsunit/es6/regress/regress-4395-global-eval.js
@@ -0,0 +1,6 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+((x, y = eval('x')) => assertEquals(42, y))(42);
+((x, {y = eval('x')}) => assertEquals(42, y))(42, {});
diff --git a/test/mjsunit/es6/regress/regress-4395.js b/test/mjsunit/es6/regress/regress-4395.js
new file mode 100644
index 0000000..bdf8443
--- /dev/null
+++ b/test/mjsunit/es6/regress/regress-4395.js
@@ -0,0 +1,102 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function testExpressionTypes() {
+ "use strict";
+ ((x, y = x) => assertEquals(42, y))(42);
+
+ ((x, y = (x)) => assertEquals(42, y))(42);
+ ((x, y = `${x}`) => assertEquals("42", y))(42);
+ ((x, y = x = x + 1) => assertEquals(43, y))(42);
+ ((x, y = x()) => assertEquals(42, y))(() => 42);
+ ((x, y = new x()) => assertEquals(42, y.z))(function() { this.z = 42 });
+ ((x, y = -x) => assertEquals(-42, y))(42);
+ ((x, y = ++x) => assertEquals(43, y))(42);
+ ((x, y = x === 42) => assertTrue(y))(42);
+ ((x, y = (x == 42 ? x : 0)) => assertEquals(42, y))(42);
+
+ ((x, y = function() { return x }) => assertEquals(42, y()))(42);
+ ((x, y = () => x) => assertEquals(42, y()))(42);
+
+ // Literals
+ ((x, y = {z: x}) => assertEquals(42, y.z))(42);
+ ((x, y = {[x]: x}) => assertEquals(42, y[42]))(42);
+ ((x, y = [x]) => assertEquals(42, y[0]))(42);
+ ((x, y = [...x]) => assertEquals(42, y[0]))([42]);
+
+ ((x, y = class {
+ static [x]() { return x }
+ }) => assertEquals(42, y[42]()))(42);
+ ((x, y = (new class {
+ z() { return x }
+ })) => assertEquals(42, y.z()))(42);
+
+ ((x, y = (new class Y {
+ static [x]() { return x }
+ z() { return Y[42]() }
+ })) => assertEquals(42, y.z()))(42);
+
+ ((x, y = (new class {
+ constructor() { this.z = x }
+ })) => assertEquals(42, y.z))(42);
+ ((x, y = (new class Y {
+ constructor() { this.z = x }
+ })) => assertEquals(42, y.z))(42);
+
+ ((x, y = (new class extends x {
+ })) => assertEquals(42, y.z()))(class { z() { return 42 } });
+
+ // Defaults inside destructuring
+ ((x, {y = x}) => assertEquals(42, y))(42, {});
+ ((x, [y = x]) => assertEquals(42, y))(42, []);
+})();
+
+
+(function testMultiScopeCapture() {
+ "use strict";
+ var x = 1;
+ {
+ let y = 2;
+ ((x, y, a = x, b = y) => {
+ assertEquals(3, x);
+ assertEquals(3, a);
+ assertEquals(4, y);
+ assertEquals(4, b);
+ })(3, 4);
+ }
+})();
+
+
+(function testSuper() {
+ "use strict";
+ class A {
+ x() { return 42; }
+ }
+
+ class B extends A {
+ y() {
+ ((q = super.x()) => assertEquals(42, q))();
+ }
+ }
+
+ new B().y();
+
+ class C {
+ constructor() { return { prop: 42 } }
+ }
+
+ class D extends C{
+ constructor() {
+ ((q = super()) => assertEquals(42, q.prop))();
+ }
+ }
+
+ new D();
+})();
+
+
+(function testScopeFlags() {
+ ((x, y = eval('x')) => assertEquals(42, y))(42);
+ ((x, {y = eval('x')}) => assertEquals(42, y))(42, {});
+})();
diff --git a/test/mjsunit/es6/regress/regress-4400.js b/test/mjsunit/es6/regress/regress-4400.js
new file mode 100644
index 0000000..98ad269
--- /dev/null
+++ b/test/mjsunit/es6/regress/regress-4400.js
@@ -0,0 +1,8 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --min-preparse-length=0
+
+function borked(a = [], b = {}, c) {}
+borked();
diff --git a/test/mjsunit/es6/regress/regress-4585.js b/test/mjsunit/es6/regress/regress-4585.js
new file mode 100644
index 0000000..8ded646
--- /dev/null
+++ b/test/mjsunit/es6/regress/regress-4585.js
@@ -0,0 +1,14 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+assertThrows(`for(const { method() {} } = this) {}`, SyntaxError);
+assertThrows(`var { method() {} } = this;`, SyntaxError);
+assertThrows(`for(const { *method() {} } = this) {}`, SyntaxError);
+assertThrows(`var { *method() {} } = this;`, SyntaxError);
+assertThrows(`for(var { get foo() {} } = this) {}`, SyntaxError);
+assertThrows(`for(var { set foo() {} } = this) {}`, SyntaxError);
+
+// Still OK in other objects
+for (var { name = "" + { toString() { return "test" } } } in { a: 1}) break;
+assertEquals(name, "test");
diff --git a/test/mjsunit/es6/regress/regress-4759.js b/test/mjsunit/es6/regress/regress-4759.js
new file mode 100644
index 0000000..5f8ee68
--- /dev/null
+++ b/test/mjsunit/es6/regress/regress-4759.js
@@ -0,0 +1,23 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function iterable(done) {
+ return {
+ [Symbol.iterator]: function() {
+ return {
+ next: function() {
+ if (done) return { done: true };
+ done = true;
+ return { value: 42, done: false };
+ }
+ }
+ }
+ }
+}
+
+var [...result] = iterable(true);
+assertEquals([], result);
+
+var [...result] = iterable(false);
+assertEquals([42], result);
diff --git a/test/mjsunit/es6/regress/regress-517455.js b/test/mjsunit/es6/regress/regress-517455.js
new file mode 100644
index 0000000..9c1dfd7
--- /dev/null
+++ b/test/mjsunit/es6/regress/regress-517455.js
@@ -0,0 +1,6 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function f({x = ""}) { eval(x) }
+f({})
diff --git a/test/mjsunit/es6/regress/regress-576662.js b/test/mjsunit/es6/regress/regress-576662.js
new file mode 100644
index 0000000..ad582d6
--- /dev/null
+++ b/test/mjsunit/es6/regress/regress-576662.js
@@ -0,0 +1,9 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://code.google.com/p/chromium/issues/detail?id=576662 (simplified)
+
+Realm.create();
+this.__proto__ = new Proxy({},{});
+assertThrows(() => Realm.eval(1, "Realm.global(0).bla = 1"));
diff --git a/test/mjsunit/es6/regress/regress-cr493566.js b/test/mjsunit/es6/regress/regress-cr493566.js
index 2b0b7ea..7fbbd7d 100644
--- a/test/mjsunit/es6/regress/regress-cr493566.js
+++ b/test/mjsunit/es6/regress/regress-cr493566.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-proxies --harmony-reflect
-
"use strict";
var global = this;
diff --git a/test/mjsunit/es6/regress/regress-cr512574.js b/test/mjsunit/es6/regress/regress-cr512574.js
index 8d843ee..2bff763 100644
--- a/test/mjsunit/es6/regress/regress-cr512574.js
+++ b/test/mjsunit/es6/regress/regress-cr512574.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-destructuring-bind
-
function f({}) {
for (var v in []);
};
diff --git a/test/mjsunit/es6/regress/regress-crbug-448730.js b/test/mjsunit/es6/regress/regress-crbug-448730.js
new file mode 100644
index 0000000..a3c70ac
--- /dev/null
+++ b/test/mjsunit/es6/regress/regress-crbug-448730.js
@@ -0,0 +1,14 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function bar() {}
+bar({ a: new Proxy({}, {}) });
+function foo(x) { x.a.b == ""; }
+var x = {a: {b: "" }};
+foo(x);
+foo(x);
+%OptimizeFunctionOnNextCall(foo);
+foo(x);
diff --git a/test/mjsunit/es6/regress/regress-crbug-461520.js b/test/mjsunit/es6/regress/regress-crbug-461520.js
new file mode 100644
index 0000000..d12ec53
--- /dev/null
+++ b/test/mjsunit/es6/regress/regress-crbug-461520.js
@@ -0,0 +1,18 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var fuse = 1;
+
+var handler = {
+ get: function() { return function() {} },
+ has() { return true },
+ getOwnPropertyDescriptor: function() {
+ if (fuse-- == 0) throw "please die";
+ return {value: function() {}, configurable: true};
+ }
+};
+
+var p = new Proxy({}, handler);
+var o = Object.create(p);
+with (o) { f() }
diff --git a/test/mjsunit/es6/regress/regress-lookup-transition.js b/test/mjsunit/es6/regress/regress-lookup-transition.js
new file mode 100644
index 0000000..c6da9bd
--- /dev/null
+++ b/test/mjsunit/es6/regress/regress-lookup-transition.js
@@ -0,0 +1,14 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-gc
+
+var proxy = new Proxy({}, { getOwnPropertyDescriptor:function() {
+ gc();
+}});
+
+function f() { this.x = 23; }
+f.prototype = proxy;
+new f();
+new f();
diff --git a/test/mjsunit/es6/string-endswith.js b/test/mjsunit/es6/string-endswith.js
index cbf2ed8..4246f16 100644
--- a/test/mjsunit/es6/string-endswith.js
+++ b/test/mjsunit/es6/string-endswith.js
@@ -408,3 +408,11 @@
"toString": function() { return "abc"; }
}, [/./]);
}, TypeError);
+
+// endsWith does its brand checks with Symbol.match
+var re = /./;
+assertThrows(function() {
+ "".startsWith(re);
+}, TypeError);
+re[Symbol.match] = false;
+assertEquals(false, "".startsWith(re));
diff --git a/test/mjsunit/es6/string-includes.js b/test/mjsunit/es6/string-includes.js
index 61bf779..c825ffd 100644
--- a/test/mjsunit/es6/string-includes.js
+++ b/test/mjsunit/es6/string-includes.js
@@ -162,3 +162,11 @@
"throw RangeError(); } }, [/./])", RangeError);
assertThrows("String.prototype.includes.apply({ 'toString': function() { " +
"return 'abc'; } }, [/./])", TypeError);
+
+// includes does its brand checks with Symbol.match
+var re = /./;
+assertThrows(function() {
+ "".includes(re);
+}, TypeError);
+re[Symbol.match] = false;
+assertEquals(false, "".includes(re));
diff --git a/test/mjsunit/es6/string-iterator.js b/test/mjsunit/es6/string-iterator.js
index 769f549..8eb27b1 100644
--- a/test/mjsunit/es6/string-iterator.js
+++ b/test/mjsunit/es6/string-iterator.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-tostring
-
function TestStringPrototypeIterator() {
assertTrue(String.prototype.hasOwnProperty(Symbol.iterator));
assertFalse("".hasOwnProperty(Symbol.iterator));
diff --git a/test/mjsunit/es6/string-startswith.js b/test/mjsunit/es6/string-startswith.js
index 887db99..f38f7b9 100644
--- a/test/mjsunit/es6/string-startswith.js
+++ b/test/mjsunit/es6/string-startswith.js
@@ -399,3 +399,11 @@
"toString": function() { return "abc"; }
}, [/./]);
}, TypeError);
+
+// startsWith does its brand checks with Symbol.match
+var re = /./;
+assertThrows(function() {
+ "".startsWith(re);
+}, TypeError);
+re[Symbol.match] = false;
+assertEquals(false, "".startsWith(re));
diff --git a/test/mjsunit/es6/super.js b/test/mjsunit/es6/super.js
index 67cb45f..a2ba1e8 100644
--- a/test/mjsunit/es6/super.js
+++ b/test/mjsunit/es6/super.js
@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Flags: --allow-natives-syntax
-// Flags: --harmony-destructuring-bind --harmony-sloppy
+// Flags: --harmony-sloppy
(function TestSuperNamedLoads() {
function Base() { }
diff --git a/test/mjsunit/es6/symbols.js b/test/mjsunit/es6/symbols.js
index 3833857..9bac41f 100644
--- a/test/mjsunit/es6/symbols.js
+++ b/test/mjsunit/es6/symbols.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: --expose-gc --allow-natives-syntax --harmony-tostring
+// Flags: --expose-gc --allow-natives-syntax
var symbols = []
@@ -86,6 +86,7 @@
function TestConstructor() {
+ assertEquals(0, Symbol.length);
assertSame(Function.prototype, Symbol.__proto__)
assertFalse(Object === Symbol.prototype.constructor)
assertFalse(Symbol === Object.prototype.constructor)
diff --git a/test/mjsunit/es6/tail-call-megatest-shard0.js b/test/mjsunit/es6/tail-call-megatest-shard0.js
new file mode 100644
index 0000000..87fe29e
--- /dev/null
+++ b/test/mjsunit/es6/tail-call-megatest-shard0.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-tailcalls
+
+try {
+ load("mjsunit/es6/tail-call-megatest.js");
+} catch(e) {
+ load("test/mjsunit/es6/tail-call-megatest.js");
+}
+
+run_tests(0);
diff --git a/test/mjsunit/es6/tail-call-megatest-shard1.js b/test/mjsunit/es6/tail-call-megatest-shard1.js
new file mode 100644
index 0000000..10deb28
--- /dev/null
+++ b/test/mjsunit/es6/tail-call-megatest-shard1.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-tailcalls
+
+try {
+ load("mjsunit/es6/tail-call-megatest.js");
+} catch(e) {
+ load("test/mjsunit/es6/tail-call-megatest.js");
+}
+
+run_tests(1);
diff --git a/test/mjsunit/es6/tail-call-megatest-shard2.js b/test/mjsunit/es6/tail-call-megatest-shard2.js
new file mode 100644
index 0000000..7d2bd97
--- /dev/null
+++ b/test/mjsunit/es6/tail-call-megatest-shard2.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-tailcalls
+
+try {
+ load("mjsunit/es6/tail-call-megatest.js");
+} catch(e) {
+ load("test/mjsunit/es6/tail-call-megatest.js");
+}
+
+run_tests(2);
diff --git a/test/mjsunit/es6/tail-call-megatest-shard3.js b/test/mjsunit/es6/tail-call-megatest-shard3.js
new file mode 100644
index 0000000..7bce6c4
--- /dev/null
+++ b/test/mjsunit/es6/tail-call-megatest-shard3.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-tailcalls
+
+try {
+ load("mjsunit/es6/tail-call-megatest.js");
+} catch(e) {
+ load("test/mjsunit/es6/tail-call-megatest.js");
+}
+
+run_tests(3);
diff --git a/test/mjsunit/es6/tail-call-megatest-shard4.js b/test/mjsunit/es6/tail-call-megatest-shard4.js
new file mode 100644
index 0000000..6c43d3e
--- /dev/null
+++ b/test/mjsunit/es6/tail-call-megatest-shard4.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-tailcalls
+
+try {
+ load("mjsunit/es6/tail-call-megatest.js");
+} catch(e) {
+ load("test/mjsunit/es6/tail-call-megatest.js");
+}
+
+run_tests(4);
diff --git a/test/mjsunit/es6/tail-call-megatest-shard5.js b/test/mjsunit/es6/tail-call-megatest-shard5.js
new file mode 100644
index 0000000..a91bd3f
--- /dev/null
+++ b/test/mjsunit/es6/tail-call-megatest-shard5.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-tailcalls
+
+try {
+ load("mjsunit/es6/tail-call-megatest.js");
+} catch(e) {
+ load("test/mjsunit/es6/tail-call-megatest.js");
+}
+
+run_tests(5);
diff --git a/test/mjsunit/es6/tail-call-megatest-shard6.js b/test/mjsunit/es6/tail-call-megatest-shard6.js
new file mode 100644
index 0000000..0d70a42
--- /dev/null
+++ b/test/mjsunit/es6/tail-call-megatest-shard6.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-tailcalls
+
+try {
+ load("mjsunit/es6/tail-call-megatest.js");
+} catch(e) {
+ load("test/mjsunit/es6/tail-call-megatest.js");
+}
+
+run_tests(6);
diff --git a/test/mjsunit/es6/tail-call-megatest-shard7.js b/test/mjsunit/es6/tail-call-megatest-shard7.js
new file mode 100644
index 0000000..63477af
--- /dev/null
+++ b/test/mjsunit/es6/tail-call-megatest-shard7.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-tailcalls
+
+try {
+ load("mjsunit/es6/tail-call-megatest.js");
+} catch(e) {
+ load("test/mjsunit/es6/tail-call-megatest.js");
+}
+
+run_tests(7);
diff --git a/test/mjsunit/es6/tail-call-megatest-shard8.js b/test/mjsunit/es6/tail-call-megatest-shard8.js
new file mode 100644
index 0000000..0c68827
--- /dev/null
+++ b/test/mjsunit/es6/tail-call-megatest-shard8.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-tailcalls
+
+try {
+ load("mjsunit/es6/tail-call-megatest.js");
+} catch(e) {
+ load("test/mjsunit/es6/tail-call-megatest.js");
+}
+
+run_tests(8);
diff --git a/test/mjsunit/es6/tail-call-megatest-shard9.js b/test/mjsunit/es6/tail-call-megatest-shard9.js
new file mode 100644
index 0000000..82f991a
--- /dev/null
+++ b/test/mjsunit/es6/tail-call-megatest-shard9.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-tailcalls
+
+try {
+ load("mjsunit/es6/tail-call-megatest.js");
+} catch(e) {
+ load("test/mjsunit/es6/tail-call-megatest.js");
+}
+
+run_tests(9);
diff --git a/test/mjsunit/es6/tail-call-megatest.js b/test/mjsunit/es6/tail-call-megatest.js
index 0057961..1de8ec6 100644
--- a/test/mjsunit/es6/tail-call-megatest.js
+++ b/test/mjsunit/es6/tail-call-megatest.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --harmony-tailcalls --no-turbo-inlining
+// Flags: --allow-natives-syntax --harmony-tailcalls
Error.prepareStackTrace = (error,stack) => {
@@ -11,23 +11,15 @@
}
-function CheckStackTrace(expected) {
+function checkStackTrace(expected) {
var e = new Error();
e.stack; // prepare stack trace
var stack = e.strace;
- assertEquals("CheckStackTrace", stack[0].getFunctionName());
+ assertEquals("checkStackTrace", stack[0].getFunctionName());
for (var i = 0; i < expected.length; i++) {
assertEquals(expected[i].name, stack[i + 1].getFunctionName());
}
}
-%NeverOptimizeFunction(CheckStackTrace);
-
-
-function CheckArguments(expected, args) {
- args = Array.prototype.slice.call(args);
- assertEquals(expected, args);
-}
-%NeverOptimizeFunction(CheckArguments);
var CAN_INLINE_COMMENT = "// Let it be inlined.";
@@ -45,28 +37,59 @@
return ident + source.replace(/\n/gi, "\n" + ident);
}
-var global = Function('return this')();
-var the_receiver = {receiver: 1};
+var SHARDS_COUNT = 10;
-function run_tests() {
+function run_tests(shard) {
function inlinable_comment(inlinable) {
return inlinable ? CAN_INLINE_COMMENT : DONT_INLINE_COMMENT;
}
+ // Check arguments manually to avoid bailing out with reason "bad value
+ // context for arguments value".
+ function check_arguments_template(expected_name) {
+ var lines = [
+ ` assertEquals_(${expected_name}.length, arguments.length);`,
+ ` for (var i = 0; i < ${expected_name}.length; i++) {`,
+ ` assertEquals_(${expected_name}[i], arguments[i]);`,
+ ` }`,
+ ];
+ return lines.join("\n");
+ }
+ var check_arguments = check_arguments_template("expected_args");
+
+ function deopt_template(deopt_mode) {
+ switch(deopt_mode) {
+ case "none":
+ return " // Don't deoptimize";
+ case "f":
+ case "g":
+ case "test":
+ return ` %DeoptimizeFunction(${deopt_mode});`;
+ default:
+ assertUnreachable();
+ }
+ }
+
var f_cfg_sloppy = {
func_name: 'f',
source_template: function(cfg) {
var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
: "global";
+ var do_checks = [
+ ` assertEquals_(${receiver}, this);`,
+ ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.target);`,
+ check_arguments,
+ ` checkStackTrace_([f, test]);`,
+ ].join("\n");
+
var lines = [
`function f(a) {`,
` ${inlinable_comment(cfg.f_inlinable)}`,
- ` assertEquals(${receiver}, this);`,
- ` CheckArguments([${cfg.f_args}], arguments);`,
- ` CheckStackTrace([f, test]);`,
- ` %DeoptimizeNow();`,
- ` CheckArguments([${cfg.f_args}], arguments);`,
- ` CheckStackTrace([f, test]);`,
+ ` counter++;`,
+ ` var expected_args = [${cfg.f_args}];`,
+ do_checks,
+ deopt_template(cfg.deopt_mode),
+ do_checks,
` return 42;`,
`}`,
];
@@ -79,16 +102,22 @@
source_template: function(cfg) {
var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
: "undefined";
+ var do_checks = [
+ ` assertEquals_(${receiver}, this);`,
+ ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.target);`,
+ check_arguments,
+ ` checkStackTrace_([f, test]);`,
+ ].join("\n");
+
var lines = [
`function f(a) {`,
` "use strict";`,
` ${inlinable_comment(cfg.f_inlinable)}`,
- ` assertEquals(${receiver}, this);`,
- ` CheckArguments([${cfg.f_args}], arguments);`,
- ` CheckStackTrace([f, test]);`,
- ` %DeoptimizeNow();`,
- ` CheckArguments([${cfg.f_args}], arguments);`,
- ` CheckStackTrace([f, test]);`,
+ ` counter++;`,
+ ` var expected_args = [${cfg.f_args}];`,
+ do_checks,
+ deopt_template(cfg.deopt_mode),
+ do_checks,
` return 42;`,
`}`,
];
@@ -101,15 +130,21 @@
source_template: function(cfg) {
var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
: "global";
+ var do_checks = [
+ ` assertEquals_(${receiver}, this);`,
+ ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.target);`,
+ check_arguments,
+ ` checkStackTrace_([f, test]);`,
+ ].join("\n");
+
var lines = [
`function f(a) {`,
` ${inlinable_comment(cfg.f_inlinable)}`,
- ` assertEquals(${receiver}, this);`,
- ` CheckArguments([${cfg.f_args}], arguments);`,
- ` CheckStackTrace([f, test]);`,
- ` %DeoptimizeNow();`,
- ` CheckArguments([${cfg.f_args}], arguments);`,
- ` CheckStackTrace([f, test]);`,
+ ` counter++;`,
+ ` var expected_args = [${cfg.f_args}];`,
+ do_checks,
+ deopt_template(cfg.deopt_mode),
+ do_checks,
` return 42;`,
`}`,
`var eval = f;`,
@@ -121,16 +156,22 @@
var f_cfg_bound = {
func_name: 'bound',
source_template: function(cfg) {
+ var do_checks = [
+ ` assertEquals_(receiver, this);`,
+ ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.target);`,
+ check_arguments,
+ ` checkStackTrace_([f, test]);`,
+ ].join("\n");
+
var lines = [
`function f(a) {`,
` "use strict";`,
` ${inlinable_comment(cfg.f_inlinable)}`,
- ` assertEquals(receiver, this);`,
- ` CheckArguments([${cfg.f_args}], arguments);`,
- ` CheckStackTrace([f, test]);`,
- ` %DeoptimizeNow();`,
- ` CheckArguments([${cfg.f_args}], arguments);`,
- ` CheckStackTrace([f, test]);`,
+ ` counter++;`,
+ ` var expected_args = [${cfg.f_args}];`,
+ do_checks,
+ deopt_template(cfg.deopt_mode),
+ do_checks,
` return 42;`,
`}`,
`var receiver = {a: 153};`,
@@ -145,15 +186,21 @@
source_template: function(cfg) {
var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
: "global";
+ var do_checks = [
+ ` assertEquals_(${receiver}, this);`,
+ ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.target);`,
+ check_arguments,
+ ` checkStackTrace_([f, test]);`,
+ ].join("\n");
+
var lines = [
`function f(a) {`,
` ${inlinable_comment(cfg.f_inlinable)}`,
- ` assertEquals(${receiver}, this);`,
- ` CheckArguments([${cfg.f_args}], arguments);`,
- ` CheckStackTrace([f, test]);`,
- ` %DeoptimizeNow();`,
- ` CheckArguments([${cfg.f_args}], arguments);`,
- ` CheckStackTrace([f, test]);`,
+ ` counter++;`,
+ ` var expected_args = [${cfg.f_args}];`,
+ do_checks,
+ deopt_template(cfg.deopt_mode),
+ do_checks,
` return 42;`,
`}`,
`var p = new Proxy(f, {});`,
@@ -169,7 +216,8 @@
`function g(a) {`,
` "use strict";`,
` ${inlinable_comment(cfg.g_inlinable)}`,
- ` CheckArguments([${cfg.g_args}], arguments);`,
+ ` var expected_args = [${cfg.g_args}];`,
+ check_arguments,
` return ${cfg.f_name}(${cfg.f_args});`,
`}`,
];
@@ -178,6 +226,23 @@
};
+ var g_cfg_reflect_apply = {
+ receiver: "the_receiver",
+ source_template: function(cfg) {
+ var lines = [
+ `function g(a) {`,
+ ` "use strict";`,
+ ` ${inlinable_comment(cfg.g_inlinable)}`,
+ ` var expected_args = [${cfg.g_args}];`,
+ check_arguments,
+ ` return Reflect.apply(${cfg.f_name}, the_receiver, [${cfg.f_args}]);`,
+ `}`,
+ ];
+ return lines.join("\n");
+ },
+ };
+
+
var g_cfg_function_apply = {
receiver: "the_receiver",
source_template: function(cfg) {
@@ -185,7 +250,8 @@
`function g(a) {`,
` "use strict";`,
` ${inlinable_comment(cfg.g_inlinable)}`,
- ` CheckArguments([${cfg.g_args}], arguments);`,
+ ` var expected_args = [${cfg.g_args}];`,
+ check_arguments,
` return ${cfg.f_name}.apply(the_receiver, [${cfg.f_args}]);`,
`}`,
];
@@ -194,6 +260,24 @@
};
+ var g_cfg_function_apply_arguments_object = {
+ receiver: "the_receiver",
+ source_template: function(cfg) {
+ cfg.f_args = cfg.g_args;
+ var lines = [
+ `function g(a) {`,
+ ` "use strict";`,
+ ` ${inlinable_comment(cfg.g_inlinable)}`,
+ ` var expected_args = [${cfg.g_args}];`,
+ check_arguments,
+ ` return ${cfg.f_name}.apply(the_receiver, arguments);`,
+ `}`,
+ ];
+ return lines.join("\n");
+ },
+ };
+
+
var g_cfg_function_call = {
receiver: "the_receiver",
source_template: function(cfg) {
@@ -205,7 +289,8 @@
`function g(a) {`,
` "use strict";`,
` ${inlinable_comment(cfg.g_inlinable)}`,
- ` CheckArguments([${cfg.g_args}], arguments);`,
+ ` var expected_args = [${cfg.g_args}];`,
+ check_arguments,
` return ${cfg.f_name}.call(${f_args});`,
`}`,
];
@@ -215,27 +300,39 @@
function test_template(cfg) {
- var f_source = cfg.f_source_template(cfg);
+ // Note: g_source_template modifies cfg.f_args in some cases.
var g_source = cfg.g_source_template(cfg);
- f_source = ident_source(f_source, 2);
g_source = ident_source(g_source, 2);
+ var f_source = cfg.f_source_template(cfg);
+ f_source = ident_source(f_source, 2);
+
var lines = [
`(function() {`,
+ ` // Avoid bailing out because of "Reference to a variable which requires dynamic lookup".`,
+ ` var assertEquals_ = assertEquals;`,
+ ` var checkStackTrace_ = checkStackTrace;`,
+ ` var undefined = void 0;`,
+ ` var global = Function('return this')();`,
+ ` var the_receiver = {receiver: 1};`,
+ ` var counter = 0;`,
+ ``,
+ ` // Don't inline helper functions`,
+ ` %NeverOptimizeFunction(assertEquals);`,
+ ` %NeverOptimizeFunction(checkStackTrace);`,
+ ``,
f_source,
g_source,
` function test() {`,
` "use strict";`,
- ` assertEquals(42, g(${cfg.g_args}));`,
+ ` assertEquals_(42, g(${cfg.g_args}));`,
` }`,
- ` ${cfg.f_inlinable ? "%SetForceInlineFlag(f)" : ""};`,
- ` ${cfg.g_inlinable ? "%SetForceInlineFlag(g)" : ""};`,
- ``,
- ` test();`,
+ ` ${"test();".repeat(cfg.test_warmup_count)}`,
+ ` ${cfg.f_inlinable ? "%SetForceInlineFlag(f)" : "%OptimizeFunctionOnNextCall(f)"};`,
+ ` ${cfg.g_inlinable ? "%SetForceInlineFlag(g)" : "%OptimizeFunctionOnNextCall(g)"};`,
` %OptimizeFunctionOnNextCall(test);`,
- ` %OptimizeFunctionOnNextCall(f);`,
- ` %OptimizeFunctionOnNextCall(g);`,
` test();`,
+ ` assertEquals(${1 + cfg.test_warmup_count}, counter);`,
`})();`,
``,
];
@@ -243,11 +340,13 @@
return source;
}
- // TODO(v8:4698), TODO(ishell): support all commented cases.
var f_args_variants = ["", "1", "1, 2"];
- var g_args_variants = [/*"",*/ "10", /*"10, 20"*/];
- var f_inlinable_variants = [/*true,*/ false];
+ var g_args_variants = ["", "10", "10, 20"];
+ var f_inlinable_variants = [true, false];
var g_inlinable_variants = [true, false];
+ // This is to avoid bailing out because of referencing new.target.
+ var check_new_target_variants = [true, false];
+ var deopt_mode_variants = ["none", "f", "g", "test"];
var f_variants = [
f_cfg_sloppy,
f_cfg_strict,
@@ -257,36 +356,60 @@
];
var g_variants = [
g_cfg_normal,
- g_cfg_function_call,
+ g_cfg_reflect_apply,
g_cfg_function_apply,
+ g_cfg_function_apply_arguments_object,
+ g_cfg_function_call,
];
+ var test_warmup_counts = [0, 1, 2];
+ var iter = 0;
+ var tests_executed = 0;
+ if (shard !== undefined) {
+ print("Running shard #" + shard);
+ }
f_variants.forEach((f_cfg) => {
- g_variants.forEach((g_cfg) => {
- f_args_variants.forEach((f_args) => {
- g_args_variants.forEach((g_args) => {
- f_inlinable_variants.forEach((f_inlinable) => {
- g_inlinable_variants.forEach((g_inlinable) => {
- var cfg = {
- f_source_template: f_cfg.source_template,
- f_inlinable,
- f_args,
- f_name: f_cfg.func_name,
- f_receiver: g_cfg.receiver,
- g_source_template: g_cfg.source_template,
- g_inlinable,
- g_args,
- };
- var source = test_template(cfg);
- print("====================");
- print(source);
- eval(source);
+ check_new_target_variants.forEach((check_new_target) => {
+ deopt_mode_variants.forEach((deopt_mode) => {
+ g_variants.forEach((g_cfg) => {
+ f_args_variants.forEach((f_args) => {
+ g_args_variants.forEach((g_args) => {
+ f_inlinable_variants.forEach((f_inlinable) => {
+ g_inlinable_variants.forEach((g_inlinable) => {
+ test_warmup_counts.forEach((test_warmup_count) => {
+ if (shard !== undefined && (iter++) % SHARDS_COUNT != shard) {
+ print("skipping...");
+ return;
+ }
+ tests_executed++;
+ var cfg = {
+ f_source_template: f_cfg.source_template,
+ f_inlinable,
+ f_args,
+ f_name: f_cfg.func_name,
+ f_receiver: g_cfg.receiver,
+ g_source_template: g_cfg.source_template,
+ g_inlinable,
+ g_args,
+ test_warmup_count,
+ check_new_target,
+ deopt_mode,
+ };
+ var source = test_template(cfg);
+ print("====================");
+ print(source);
+ eval(source);
+ });
+ });
+ });
});
});
});
});
});
});
+ print("Number of tests executed: " + tests_executed);
}
-run_tests();
+// Uncomment to run all the tests at once or use shard runners.
+//run_tests();
diff --git a/test/mjsunit/es6/tail-call-proxies.js b/test/mjsunit/es6/tail-call-proxies.js
index 25f9fcf..251ac0c 100644
--- a/test/mjsunit/es6/tail-call-proxies.js
+++ b/test/mjsunit/es6/tail-call-proxies.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --harmony-tailcalls --harmony-proxies
+// Flags: --allow-natives-syntax --harmony-tailcalls
"use strict";
Error.prepareStackTrace = (e,s) => s;
diff --git a/test/mjsunit/es6/tail-call-simple.js b/test/mjsunit/es6/tail-call-simple.js
index d2890b0..cc63808 100644
--- a/test/mjsunit/es6/tail-call-simple.js
+++ b/test/mjsunit/es6/tail-call-simple.js
@@ -10,7 +10,7 @@
(function() {
function f(n) {
if (n <= 0) {
- return "foo";
+ return "foo";
}
return f(n - 1);
}
@@ -27,7 +27,7 @@
"use strict";
function f(n) {
if (n <= 0) {
- return "foo";
+ return "foo";
}
return f(n - 1);
}
@@ -39,6 +39,20 @@
(function() {
"use strict";
+ function f(n) {
+ if (n <= 0) {
+ return "foo";
+ }
+ return f(n - 1, 42); // Call with arguments adaptor.
+ }
+ assertEquals("foo", f(1e5));
+ %OptimizeFunctionOnNextCall(f);
+ assertEquals("foo", f(1e5));
+})();
+
+
+(function() {
+ "use strict";
function f(n){
if (n <= 0) {
return "foo";
@@ -59,6 +73,28 @@
})();
+(function() {
+ "use strict";
+ function f(n){
+ if (n <= 0) {
+ return "foo";
+ }
+ return g(n - 1, 42); // Call with arguments adaptor.
+ }
+ function g(n){
+ if (n <= 0) {
+ return "bar";
+ }
+ return f(n - 1, 42); // Call with arguments adaptor.
+ }
+ assertEquals("foo", f(1e5));
+ assertEquals("bar", f(1e5 + 1));
+ %OptimizeFunctionOnNextCall(f);
+ assertEquals("foo", f(1e5));
+ assertEquals("bar", f(1e5 + 1));
+})();
+
+
//
// Tail call bound functions.
//
diff --git a/test/mjsunit/es6/tail-call.js b/test/mjsunit/es6/tail-call.js
index e9539c3..d0d00f4 100644
--- a/test/mjsunit/es6/tail-call.js
+++ b/test/mjsunit/es6/tail-call.js
@@ -20,6 +20,8 @@
assertEquals(expected[i].name, stack[i + 1].getFunctionName());
}
}
+%NeverOptimizeFunction(CheckStackTrace);
+
function f(expected_call_stack, a, b) {
CheckStackTrace(expected_call_stack);
@@ -69,6 +71,7 @@
assertEquals(12, g4(1));
}
test();
+ test();
%OptimizeFunctionOnNextCall(test);
test();
})();
@@ -111,6 +114,7 @@
assertEquals(12, g4());
}
test();
+ test();
%OptimizeFunctionOnNextCall(test);
test();
})();
@@ -162,6 +166,7 @@
assertEquals(12, g4(1));
}
test();
+ test();
%OptimizeFunctionOnNextCall(test);
test();
})();
@@ -212,6 +217,89 @@
assertEquals(12, g4());
}
test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Tail calling from getter.
+(function() {
+ function g(v) {
+ CheckStackTrace([g, test]);
+ %DeoptimizeFunction(test);
+ return 153;
+ }
+ %NeverOptimizeFunction(g);
+
+ function f(v) {
+ return g();
+ }
+ %SetForceInlineFlag(f);
+
+ function test() {
+ var o = {};
+ o.__defineGetter__('p', f);
+ assertEquals(153, o.p);
+ }
+
+ test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Tail calling from setter.
+(function() {
+ function g() {
+ CheckStackTrace([g, test]);
+ %DeoptimizeFunction(test);
+ return 153;
+ }
+ %NeverOptimizeFunction(g);
+
+ var context = 10;
+ function f(v) {
+ return g(context);
+ }
+ %SetForceInlineFlag(f);
+
+ function test() {
+ var o = {};
+ o.__defineSetter__('q', f);
+ assertEquals(1, o.q = 1);
+ }
+
+ test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Tail calling from constructor.
+(function() {
+ function g(context) {
+ CheckStackTrace([g, test]);
+ %DeoptimizeFunction(test);
+ return {x: 153};
+ }
+ %NeverOptimizeFunction(g);
+
+ function A() {
+ this.x = 42;
+ return g();
+ }
+
+ function test() {
+ var o = new A();
+ %DebugPrint(o);
+ assertEquals(153, o.x);
+ }
+
+ test();
+ test();
%OptimizeFunctionOnNextCall(test);
test();
})();
@@ -237,6 +325,53 @@
assertEquals(153, g3());
}
test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Tail calling from various statements.
+(function() {
+ function g1() {
+ for (var v in {a:0}) {
+ return f_153([f_153, g1, test]);
+ }
+ }
+
+ function g2() {
+ for (var v of [1, 2, 3]) {
+ return f_153([f_153, g2, test]);
+ }
+ }
+
+ function g3() {
+ for (var i = 0; i < 10; i++) {
+ return f_153([f_153, test]);
+ }
+ }
+
+ function g4() {
+ while (true) {
+ return f_153([f_153, test]);
+ }
+ }
+
+ function g5() {
+ do {
+ return f_153([f_153, test]);
+ } while (true);
+ }
+
+ function test() {
+ assertEquals(153, g1());
+ assertEquals(153, g2());
+ assertEquals(153, g3());
+ assertEquals(153, g4());
+ assertEquals(153, g5());
+ }
+ test();
+ test();
%OptimizeFunctionOnNextCall(test);
test();
})();
@@ -280,6 +415,7 @@
assertEquals(153, tc3());
}
test();
+ test();
%OptimizeFunctionOnNextCall(test);
test();
})();
@@ -321,6 +457,7 @@
assertEquals(153, tf3());
}
test();
+ test();
%OptimizeFunctionOnNextCall(test);
test();
})();
@@ -381,6 +518,28 @@
assertEquals(153, tcf4());
}
test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Test tail calls from arrow functions.
+(function () {
+ function g1(a) {
+ return (() => { return f_153([f_153, test]); })();
+ }
+
+ function g2(a) {
+ return (() => f_153([f_153, test]))();
+ }
+
+ function test() {
+ assertEquals(153, g1());
+ assertEquals(153, g2());
+ }
+ test();
+ test();
%OptimizeFunctionOnNextCall(test);
test();
})();
diff --git a/test/mjsunit/es6/typed-array-iterator.js b/test/mjsunit/es6/typed-array-iterator.js
index 0b27625..7970bba 100644
--- a/test/mjsunit/es6/typed-array-iterator.js
+++ b/test/mjsunit/es6/typed-array-iterator.js
@@ -21,10 +21,10 @@
assertFalse(TypedArrayPrototype.propertyIsEnumerable('keys'));
assertFalse(TypedArrayPrototype.propertyIsEnumerable(Symbol.iterator));
-assertEquals(Array.prototype.entries, TypedArrayPrototype.entries);
-assertEquals(Array.prototype[Symbol.iterator], TypedArrayPrototype.values);
-assertEquals(Array.prototype.keys, TypedArrayPrototype.keys);
-assertEquals(Array.prototype[Symbol.iterator], TypedArrayPrototype[Symbol.iterator]);
+assertFalse(Array.prototype.entries === TypedArrayPrototype.entries);
+assertFalse(Array.prototype[Symbol.iterator] === TypedArrayPrototype.values);
+assertFalse(Array.prototype.keys === TypedArrayPrototype.keys);
+assertFalse(Array.prototype[Symbol.iterator] === TypedArrayPrototype[Symbol.iterator]);
function TestTypedArrayValues(constructor) {
diff --git a/test/mjsunit/es6/typedarray-of.js b/test/mjsunit/es6/typedarray-of.js
index a6df29a..eaa7bde 100644
--- a/test/mjsunit/es6/typedarray-of.js
+++ b/test/mjsunit/es6/typedarray-of.js
@@ -115,9 +115,9 @@
// Check superficial features of %TypedArray%.of.
var desc = Object.getOwnPropertyDescriptor(constructor.__proto__, "of");
- assertEquals(desc.configurable, false);
+ assertEquals(desc.configurable, true);
assertEquals(desc.enumerable, false);
- assertEquals(desc.writable, false);
+ assertEquals(desc.writable, true);
assertEquals(constructor.of.length, 0);
// %TypedArray%.of is not a constructor.
diff --git a/test/mjsunit/es6/typedarray-proto.js b/test/mjsunit/es6/typedarray-proto.js
index 346b2ea..0bd90d1 100644
--- a/test/mjsunit/es6/typedarray-proto.js
+++ b/test/mjsunit/es6/typedarray-proto.js
@@ -28,17 +28,13 @@
let classProperties = new Set([
"length", "name", "arguments", "caller", "prototype", "BYTES_PER_ELEMENT"
]);
-let instanceProperties = new Set([
- "BYTES_PER_ELEMENT", "constructor", "prototype",
- // length is also an instance property as a temporary workaround to
- // BUG(chromium:579905). TODO(littledan): remove the workaround
- "length"
-]);
+let instanceProperties = new Set(["BYTES_PER_ELEMENT", "constructor", "prototype"]);
function functionProperties(object) {
return Object.getOwnPropertyNames(object).filter(function(name) {
return typeof Object.getOwnPropertyDescriptor(object, name).value
- == "function" && name != 'constructor';
+ == "function"
+ && name != 'constructor' && name != 'subarray';
});
}
diff --git a/test/mjsunit/es6/typedarray.js b/test/mjsunit/es6/typedarray.js
index e6a949c..4bdf822 100644
--- a/test/mjsunit/es6/typedarray.js
+++ b/test/mjsunit/es6/typedarray.js
@@ -25,8 +25,6 @@
// (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-tostring
-
// ArrayBuffer
function TestByteLength(param, expectedByteLength) {