summaryrefslogtreecommitdiffstats
path: root/js/src/tests/test262/built-ins/Proxy/set
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-boolean-return-false.js22
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-null-return-false.js22
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-number-return-false.js22
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-string-return-false.js22
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-undefined-return-false.js22
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/call-parameters-prototype-dunder-proto.js58
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/call-parameters-prototype-index.js57
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/call-parameters-prototype.js55
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/call-parameters.js39
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/null-handler.js24
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/return-is-abrupt.js31
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/return-true-target-property-accessor-is-configurable-set-is-undefined.js28
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/return-true-target-property-accessor-is-not-configurable.js30
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/return-true-target-property-is-not-configurable.js29
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/return-true-target-property-is-not-writable.js29
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/shell.js33
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/target-property-is-accessor-not-configurable-set-is-undefined.js39
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/target-property-is-not-configurable-not-writable-not-equal-to-v.js41
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/trap-is-missing-receiver-multiple-calls-index.js81
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/trap-is-missing-receiver-multiple-calls.js80
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/trap-is-missing-target-is-proxy.js49
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/trap-is-not-callable-realm.js33
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/trap-is-not-callable.js31
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/trap-is-null-receiver.js32
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/trap-is-null-target-is-proxy.js51
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/trap-is-undefined-no-property.js22
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/trap-is-undefined-target-is-proxy.js54
-rw-r--r--js/src/tests/test262/built-ins/Proxy/set/trap-is-undefined.js25
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/call-parameters.js41
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/internals-call-order.js50
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/not-extensible-target-not-same-target-prototype.js55
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/not-extensible-target-same-target-prototype.js56
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/null-handler.js18
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/return-abrupt-from-get-trap.js26
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/return-abrupt-from-isextensible-target.js31
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/return-abrupt-from-target-getprototypeof.js33
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/return-abrupt-from-trap.js27
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/toboolean-trap-result-false.js77
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/toboolean-trap-result-true-target-is-extensible.js80
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-missing-target-is-proxy.js38
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-not-callable-realm.js36
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-not-callable.js35
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-null-target-is-proxy.js42
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-undefined-or-null.js47
-rw-r--r--js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-undefined-target-is-proxy.js40
48 files changed, 1793 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-boolean-return-false.js b/js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-boolean-return-false.js
new file mode 100644
index 0000000000..0d69437b4a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-boolean-return-false.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.9
+description: >
+ [[Set]] ( P, V, Receiver)
+
+ 11. If booleanTrapResult is false, return false.
+features: [Proxy, Reflect, Reflect.set]
+---*/
+
+var target = {};
+var handler = {
+ set: function(t, prop, value, receiver) {
+ return false;
+ }
+};
+var p = new Proxy(target, handler);
+
+assert.sameValue(Reflect.set(p, "attr", "foo"), false);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-null-return-false.js b/js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-null-return-false.js
new file mode 100644
index 0000000000..f904449f7d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-null-return-false.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.9
+description: >
+ [[Set]] ( P, V, Receiver)
+
+ 11. If booleanTrapResult is false, return false.
+features: [Proxy, Reflect, Reflect.set]
+---*/
+
+var target = {};
+var handler = {
+ set: function(t, prop, value, receiver) {
+ return null;
+ }
+};
+var p = new Proxy(target, handler);
+
+assert.sameValue(Reflect.set(p, "attr", "foo"), false);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-number-return-false.js b/js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-number-return-false.js
new file mode 100644
index 0000000000..edf18a07ea
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-number-return-false.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.9
+description: >
+ [[Set]] ( P, V, Receiver)
+
+ 11. If booleanTrapResult is false, return false.
+features: [Proxy, Reflect, Reflect.set]
+---*/
+
+var target = {};
+var handler = {
+ set: function(t, prop, value, receiver) {
+ return 0;
+ }
+};
+var p = new Proxy(target, handler);
+
+assert.sameValue(Reflect.set(p, "attr", "foo"), false);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-string-return-false.js b/js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-string-return-false.js
new file mode 100644
index 0000000000..2eab3a0c63
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-string-return-false.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.9
+description: >
+ [[Set]] ( P, V, Receiver)
+
+ 11. If booleanTrapResult is false, return false.
+features: [Proxy, Reflect, Reflect.set]
+---*/
+
+var target = {};
+var handler = {
+ set: function(t, prop, value, receiver) {
+ return "";
+ }
+};
+var p = new Proxy(target, handler);
+
+assert.sameValue(Reflect.set(p, "attr", "foo"), false);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-undefined-return-false.js b/js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-undefined-return-false.js
new file mode 100644
index 0000000000..0ff8ca59a4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/boolean-trap-result-is-false-undefined-return-false.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.9
+description: >
+ [[Set]] ( P, V, Receiver)
+
+ 11. If booleanTrapResult is false, return false.
+features: [Proxy, Reflect, Reflect.set]
+---*/
+
+var target = {};
+var handler = {
+ set: function(t, prop, value, receiver) {
+ return undefined;
+ }
+};
+var p = new Proxy(target, handler);
+
+assert.sameValue(Reflect.set(p, "attr", "foo"), false);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/browser.js b/js/src/tests/test262/built-ins/Proxy/set/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/browser.js
diff --git a/js/src/tests/test262/built-ins/Proxy/set/call-parameters-prototype-dunder-proto.js b/js/src/tests/test262/built-ins/Proxy/set/call-parameters-prototype-dunder-proto.js
new file mode 100644
index 0000000000..8b4ec874d2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/call-parameters-prototype-dunder-proto.js
@@ -0,0 +1,58 @@
+// Copyright (C) 2019 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
+description: >
+ Ordinary [[Set]] forwards call to Proxy "set" trap with correct arguments.
+ Property name is "__proto__".
+info: |
+ OrdinarySet ( O, P, V, Receiver )
+
+ ...
+ 3. Return OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc).
+
+ OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc )
+
+ ...
+ 2. If ownDesc is undefined, then
+ a. Let parent be ? O.[[GetPrototypeOf]]().
+ b. If parent is not null, then
+ i. Return ? parent.[[Set]](P, V, Receiver).
+
+ [[Set]] ( P, V, Receiver )
+
+ ...
+ 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, V, Receiver »)).
+ ...
+ 12. Return true.
+includes: [proxyTrapsHelper.js]
+features: [Proxy, __proto__]
+---*/
+
+var _handler, _target, _prop, _value, _receiver;
+var target = {};
+var handler = allowProxyTraps({
+ set: function(target, prop, value, receiver) {
+ _handler = this;
+ _target = target;
+ _prop = prop;
+ _value = value;
+ _receiver = receiver;
+ return true;
+ },
+});
+
+var proxy = new Proxy(target, handler);
+var receiver = Object.create(proxy);
+var prop = '__proto__';
+var value = {};
+
+receiver[prop] = value;
+
+assert.sameValue(_handler, handler, 'handler object is the trap context');
+assert.sameValue(_target, target, 'first argument is the target object');
+assert.sameValue(_prop, prop, 'second argument is the property name');
+assert.sameValue(_value, value, 'third argument is the new value');
+assert.sameValue(_receiver, receiver, 'fourth argument is the receiver object');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/call-parameters-prototype-index.js b/js/src/tests/test262/built-ins/Proxy/set/call-parameters-prototype-index.js
new file mode 100644
index 0000000000..e57e40c3e0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/call-parameters-prototype-index.js
@@ -0,0 +1,57 @@
+// Copyright (C) 2019 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
+description: >
+ Ordinary [[Set]] forwards call to Proxy "set" trap with correct arguments.
+ (integer index property name)
+info: |
+ OrdinarySet ( O, P, V, Receiver )
+
+ ...
+ 3. Return OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc).
+
+ OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc )
+
+ ...
+ 2. If ownDesc is undefined, then
+ a. Let parent be ? O.[[GetPrototypeOf]]().
+ b. If parent is not null, then
+ i. Return ? parent.[[Set]](P, V, Receiver).
+
+ [[Set]] ( P, V, Receiver )
+
+ ...
+ 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, V, Receiver »)).
+ ...
+ 12. Return true.
+includes: [proxyTrapsHelper.js]
+features: [Proxy]
+---*/
+
+var _handler, _target, _prop, _value, _receiver;
+var target = {};
+var handler = allowProxyTraps({
+ set: function(target, prop, value, receiver) {
+ _handler = this;
+ _target = target;
+ _prop = prop;
+ _value = value;
+ _receiver = receiver;
+ return true;
+ },
+});
+
+var proxy = new Proxy(target, handler);
+var array = new Array(1);
+Object.setPrototypeOf(array, proxy);
+
+array[0] = 1;
+
+assert.sameValue(_handler, handler, 'handler object is the trap context');
+assert.sameValue(_target, target, 'first argument is the target object');
+assert.sameValue(_prop, '0', 'second argument is the property name');
+assert.sameValue(_value, 1, 'third argument is the new value');
+assert.sameValue(_receiver, array, 'fourth argument is the receiver object');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/call-parameters-prototype.js b/js/src/tests/test262/built-ins/Proxy/set/call-parameters-prototype.js
new file mode 100644
index 0000000000..c11f535d95
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/call-parameters-prototype.js
@@ -0,0 +1,55 @@
+// Copyright (C) 2019 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
+description: >
+ Ordinary [[Set]] forwards call to Proxy "set" trap with correct arguments.
+info: |
+ OrdinarySet ( O, P, V, Receiver )
+
+ ...
+ 3. Return OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc).
+
+ OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc )
+
+ ...
+ 2. If ownDesc is undefined, then
+ a. Let parent be ? O.[[GetPrototypeOf]]().
+ b. If parent is not null, then
+ i. Return ? parent.[[Set]](P, V, Receiver).
+
+ [[Set]] ( P, V, Receiver )
+
+ ...
+ 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, V, Receiver »)).
+ ...
+ 12. Return true.
+includes: [proxyTrapsHelper.js]
+features: [Proxy]
+---*/
+
+var _handler, _target, _prop, _value, _receiver;
+var target = {};
+var handler = allowProxyTraps({
+ set: function(target, prop, value, receiver) {
+ _handler = this;
+ _target = target;
+ _prop = prop;
+ _value = value;
+ _receiver = receiver;
+ return true;
+ },
+});
+
+var proxy = new Proxy(target, handler);
+var receiver = Object.create(proxy);
+
+receiver.prop = 'value';
+
+assert.sameValue(_handler, handler, 'handler object is the trap context');
+assert.sameValue(_target, target, 'first argument is the target object');
+assert.sameValue(_prop, 'prop', 'second argument is the property name');
+assert.sameValue(_value, 'value', 'third argument is the new value');
+assert.sameValue(_receiver, receiver, 'fourth argument is the receiver object');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/call-parameters.js b/js/src/tests/test262/built-ins/Proxy/set/call-parameters.js
new file mode 100644
index 0000000000..304fc661c9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/call-parameters.js
@@ -0,0 +1,39 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
+description: >
+ Proxy "set" trap is called with correct arguments.
+info: |
+ [[Set]] ( P, V, Receiver )
+
+ ...
+ 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, V, Receiver »)).
+ ...
+ 12. Return true.
+features: [Proxy]
+---*/
+
+var _target, _handler, _prop, _value, _receiver;
+var target = {};
+var handler = {
+ set: function(t, prop, value, receiver) {
+ _handler = this;
+ _target = t;
+ _prop = prop;
+ _value = value;
+ _receiver = receiver;
+ return true;
+ }
+};
+var p = new Proxy(target, handler);
+
+p.attr = "foo";
+
+assert.sameValue(_handler, handler, "handler object as the trap context");
+assert.sameValue(_target, target, "first argument is the target object");
+assert.sameValue(_prop, "attr", "second argument is the property name");
+assert.sameValue(_value, "foo", "third argument is the new value");
+assert.sameValue(_receiver, p, "forth argument is the proxy object");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/null-handler.js b/js/src/tests/test262/built-ins/Proxy/set/null-handler.js
new file mode 100644
index 0000000000..dd5c16829f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/null-handler.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.9
+description: >
+ [[Set]] ( P, V, Receiver)
+
+ 3. If handler is null, throw a TypeError exception.
+features: [Proxy]
+---*/
+
+var p = Proxy.revocable({}, {});
+
+p.revoke();
+
+assert.throws(TypeError, function() {
+ p.proxy.attr = 1;
+});
+
+assert.throws(TypeError, function() {
+ p.proxy['attr'] = 1;
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/return-is-abrupt.js b/js/src/tests/test262/built-ins/Proxy/set/return-is-abrupt.js
new file mode 100644
index 0000000000..4dbff93a3c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/return-is-abrupt.js
@@ -0,0 +1,31 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.9
+description: >
+ Trap returns abrupt.
+info: |
+ [[Set]] ( P, V, Receiver)
+
+ ...
+ 9. Let booleanTrapResult be ToBoolean(Call(trap, handler, «target, P, V, Receiver»)).
+ 10. ReturnIfAbrupt(booleanTrapResult).
+ ...
+features: [Proxy]
+---*/
+
+var p = new Proxy({}, {
+ set: function(t, prop, value, receiver) {
+ throw new Test262Error();
+ }
+});
+
+assert.throws(Test262Error, function() {
+ p.attr = "bar";
+});
+
+assert.throws(Test262Error, function() {
+ p["attr"] = "bar";
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/return-true-target-property-accessor-is-configurable-set-is-undefined.js b/js/src/tests/test262/built-ins/Proxy/set/return-true-target-property-accessor-is-configurable-set-is-undefined.js
new file mode 100644
index 0000000000..5d9cf8144e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/return-true-target-property-accessor-is-configurable-set-is-undefined.js
@@ -0,0 +1,28 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.9
+description: >
+ [[Set]] ( P, V, Receiver)
+
+ Returns true if trap returns true and target property accessor is
+ configurable and set is undefined.
+features: [Proxy, Reflect, Reflect.set]
+---*/
+
+var target = {};
+var handler = {
+ set: function(t, prop, value, receiver) {
+ return true;
+ }
+};
+var p = new Proxy(target, handler);
+
+Object.defineProperty(target, "attr", {
+ configurable: true,
+ set: undefined
+});
+
+assert(Reflect.set(p, "attr", "bar"));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/return-true-target-property-accessor-is-not-configurable.js b/js/src/tests/test262/built-ins/Proxy/set/return-true-target-property-accessor-is-not-configurable.js
new file mode 100644
index 0000000000..536429bf75
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/return-true-target-property-accessor-is-not-configurable.js
@@ -0,0 +1,30 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.9
+description: >
+ [[Set]] ( P, V, Receiver)
+
+ Returns true if trap returns true and target property accessor is not
+ configurable and set is not undefined.
+features: [Proxy, Reflect, Reflect.set]
+---*/
+
+var target = {};
+var handler = {
+ set: function(t, prop, value, receiver) {
+ return true;
+ }
+};
+var p = new Proxy(target, handler);
+
+Object.defineProperty(target, 'attr', {
+ configurable: false,
+ set: function(value) {
+ return value;
+ }
+});
+
+assert(Reflect.set(p, "attr", 1));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/return-true-target-property-is-not-configurable.js b/js/src/tests/test262/built-ins/Proxy/set/return-true-target-property-is-not-configurable.js
new file mode 100644
index 0000000000..6d0ed0f8f1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/return-true-target-property-is-not-configurable.js
@@ -0,0 +1,29 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.9
+description: >
+ [[Set]] ( P, V, Receiver)
+
+ Returns true if trap returns true and target property is not configurable
+ but writable.
+features: [Proxy, Reflect, Reflect.set]
+---*/
+
+var target = {};
+var handler = {
+ set: function(t, prop, value, receiver) {
+ return true;
+ }
+};
+var p = new Proxy(target, handler);
+
+Object.defineProperty(target, 'attr', {
+ configurable: false,
+ writable: true,
+ value: 'foo'
+});
+
+assert(Reflect.set(p, "attr", 1));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/return-true-target-property-is-not-writable.js b/js/src/tests/test262/built-ins/Proxy/set/return-true-target-property-is-not-writable.js
new file mode 100644
index 0000000000..04bd86bdcc
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/return-true-target-property-is-not-writable.js
@@ -0,0 +1,29 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.9
+description: >
+ [[Set]] ( P, V, Receiver)
+
+ Returns true if trap returns true and target property is configurable
+ but not writable.
+features: [Proxy, Reflect, Reflect.set]
+---*/
+
+var target = {};
+var handler = {
+ set: function(t, prop, value, receiver) {
+ return true;
+ }
+};
+var p = new Proxy(target, handler);
+
+Object.defineProperty(target, "attr", {
+ configurable: true,
+ writable: false,
+ value: "foo"
+});
+
+assert(Reflect.set(p, "attr", "foo"));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/shell.js b/js/src/tests/test262/built-ins/Proxy/set/shell.js
new file mode 100644
index 0000000000..bc72493f03
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/shell.js
@@ -0,0 +1,33 @@
+// GENERATED, DO NOT EDIT
+// file: proxyTrapsHelper.js
+// Copyright (C) 2016 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Used to assert the correctness of object behavior in the presence
+ and context of Proxy objects.
+defines: [allowProxyTraps]
+---*/
+
+function allowProxyTraps(overrides) {
+ function throwTest262Error(msg) {
+ return function () { throw new Test262Error(msg); };
+ }
+ if (!overrides) { overrides = {}; }
+ return {
+ getPrototypeOf: overrides.getPrototypeOf || throwTest262Error('[[GetPrototypeOf]] trap called'),
+ setPrototypeOf: overrides.setPrototypeOf || throwTest262Error('[[SetPrototypeOf]] trap called'),
+ isExtensible: overrides.isExtensible || throwTest262Error('[[IsExtensible]] trap called'),
+ preventExtensions: overrides.preventExtensions || throwTest262Error('[[PreventExtensions]] trap called'),
+ getOwnPropertyDescriptor: overrides.getOwnPropertyDescriptor || throwTest262Error('[[GetOwnProperty]] trap called'),
+ has: overrides.has || throwTest262Error('[[HasProperty]] trap called'),
+ get: overrides.get || throwTest262Error('[[Get]] trap called'),
+ set: overrides.set || throwTest262Error('[[Set]] trap called'),
+ deleteProperty: overrides.deleteProperty || throwTest262Error('[[Delete]] trap called'),
+ defineProperty: overrides.defineProperty || throwTest262Error('[[DefineOwnProperty]] trap called'),
+ enumerate: throwTest262Error('[[Enumerate]] trap called: this trap has been removed'),
+ ownKeys: overrides.ownKeys || throwTest262Error('[[OwnPropertyKeys]] trap called'),
+ apply: overrides.apply || throwTest262Error('[[Call]] trap called'),
+ construct: overrides.construct || throwTest262Error('[[Construct]] trap called')
+ };
+}
diff --git a/js/src/tests/test262/built-ins/Proxy/set/target-property-is-accessor-not-configurable-set-is-undefined.js b/js/src/tests/test262/built-ins/Proxy/set/target-property-is-accessor-not-configurable-set-is-undefined.js
new file mode 100644
index 0000000000..da4292f791
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/target-property-is-accessor-not-configurable-set-is-undefined.js
@@ -0,0 +1,39 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.9
+description: >
+ [[Set]] ( P, V, Receiver)
+
+ Throws a TypeError when target property is an accessor not configurable and
+ and set is undefined.
+info: |
+ 14. If targetDesc is not undefined, then
+ b. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]] is false, then
+ i. If targetDesc.[[Set]] is undefined, throw a TypeError exception.
+
+features: [Proxy]
+---*/
+
+var target = {};
+var handler = {
+ set: function(t, prop, value, receiver) {
+ return true;
+ }
+};
+var p = new Proxy(target, handler);
+
+Object.defineProperty(target, 'attr', {
+ configurable: false,
+ set: undefined
+});
+
+assert.throws(TypeError, function() {
+ p.attr = 'bar';
+});
+
+assert.throws(TypeError, function() {
+ p['attr'] = 'bar';
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/target-property-is-not-configurable-not-writable-not-equal-to-v.js b/js/src/tests/test262/built-ins/Proxy/set/target-property-is-not-configurable-not-writable-not-equal-to-v.js
new file mode 100644
index 0000000000..73fd9c7ae4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/target-property-is-not-configurable-not-writable-not-equal-to-v.js
@@ -0,0 +1,41 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.9
+description: >
+ [[Set]] ( P, V, Receiver)
+
+ Throws a TypeError when target property is not configurable neither writable
+ and its value is not strictly equal to V.
+info: |
+ 14. If targetDesc is not undefined, then
+ a. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is
+ false and targetDesc.[[Writable]] is false, then
+ i. If SameValue(V, targetDesc.[[Value]]) is false, throw a TypeError
+ exception.
+features: [Proxy]
+---*/
+
+var target = {};
+var handler = {
+ set: function(t, prop, value, receiver) {
+ return true;
+ }
+};
+var p = new Proxy(target, handler);
+
+Object.defineProperty(target, 'attr', {
+ configurable: false,
+ writable: false,
+ value: 'foo'
+});
+
+assert.throws(TypeError, function() {
+ p.attr = 'bar';
+});
+
+assert.throws(TypeError, function() {
+ p['attr'] = 'bar';
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/trap-is-missing-receiver-multiple-calls-index.js b/js/src/tests/test262/built-ins/Proxy/set/trap-is-missing-receiver-multiple-calls-index.js
new file mode 100644
index 0000000000..37a7cac0e9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/trap-is-missing-receiver-multiple-calls-index.js
@@ -0,0 +1,81 @@
+// Copyright (C) 2020 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
+description: >
+ If "set" trap is missing, the call is properly forwarded to ordinary
+ [[Set]] that invokes [[GetOwnProperty]] and [[DefineOwnProperty]] methods
+ on receiver (that is a Proxy itself) every time it is called.
+ (integer index property name)
+info: |
+ [[Set]] ( P, V, Receiver )
+
+ [...]
+ 6. Let trap be ? GetMethod(handler, "set").
+ 7. If trap is undefined, then
+ a. Return ? target.[[Set]](P, V, Receiver).
+
+ OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc )
+
+ [...]
+ 3. If IsDataDescriptor(ownDesc) is true, then
+ [...]
+ c. Let existingDescriptor be ? Receiver.[[GetOwnProperty]](P).
+ d. If existingDescriptor is not undefined, then
+ [...]
+ iii. Let valueDesc be the PropertyDescriptor { [[Value]]: V }.
+ iv. Return ? Receiver.[[DefineOwnProperty]](P, valueDesc).
+ e. Else,
+ i. Assert: Receiver does not currently have a property P.
+ ii. Return ? CreateDataProperty(Receiver, P, V).
+ [...]
+
+ [[DefineOwnProperty]] ( P, Desc )
+
+ [...]
+ 9. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, descObj »)).
+ [...]
+ 17. Return true.
+features: [Proxy, Reflect]
+includes: [compareArray.js]
+---*/
+
+var getOwnPropertyKeys = [];
+var definePropertyKeys = [];
+
+var p = new Proxy({
+ "0": null,
+}, {
+ getOwnPropertyDescriptor: function(target, key) {
+ getOwnPropertyKeys.push(key);
+ return Reflect.getOwnPropertyDescriptor(target, key);
+ },
+ defineProperty: function(target, key, desc) {
+ definePropertyKeys.push(key);
+ return Reflect.defineProperty(target, key, desc);
+ },
+});
+
+p[0] = true;
+p[0] = true;
+p["0"] = true;
+
+assert.compareArray(getOwnPropertyKeys, ["0", "0", "0"],
+ "getOwnPropertyDescriptor: key present on [[ProxyTarget]]");
+assert.compareArray(definePropertyKeys, ["0", "0", "0"],
+ "defineProperty: key present on [[ProxyTarget]]");
+
+getOwnPropertyKeys = [];
+definePropertyKeys = [];
+
+p[22] = false;
+p["22"] = false;
+p[22] = false;
+
+assert.compareArray(getOwnPropertyKeys, ["22", "22", "22"],
+ "getOwnPropertyDescriptor: key absent on [[ProxyTarget]]");
+assert.compareArray(definePropertyKeys, ["22", "22", "22"],
+ "defineProperty: key absent on [[ProxyTarget]]");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/trap-is-missing-receiver-multiple-calls.js b/js/src/tests/test262/built-ins/Proxy/set/trap-is-missing-receiver-multiple-calls.js
new file mode 100644
index 0000000000..3144580a4b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/trap-is-missing-receiver-multiple-calls.js
@@ -0,0 +1,80 @@
+// Copyright (C) 2020 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
+description: >
+ If "set" trap is missing, the call is properly forwarded to ordinary
+ [[Set]] that invokes [[GetOwnProperty]] and [[DefineOwnProperty]] methods
+ on receiver (that is a Proxy itself) every time it is called.
+info: |
+ [[Set]] ( P, V, Receiver )
+
+ [...]
+ 6. Let trap be ? GetMethod(handler, "set").
+ 7. If trap is undefined, then
+ a. Return ? target.[[Set]](P, V, Receiver).
+
+ OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc )
+
+ [...]
+ 3. If IsDataDescriptor(ownDesc) is true, then
+ [...]
+ c. Let existingDescriptor be ? Receiver.[[GetOwnProperty]](P).
+ d. If existingDescriptor is not undefined, then
+ [...]
+ iii. Let valueDesc be the PropertyDescriptor { [[Value]]: V }.
+ iv. Return ? Receiver.[[DefineOwnProperty]](P, valueDesc).
+ e. Else,
+ i. Assert: Receiver does not currently have a property P.
+ ii. Return ? CreateDataProperty(Receiver, P, V).
+ [...]
+
+ [[DefineOwnProperty]] ( P, Desc )
+
+ [...]
+ 9. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, descObj »)).
+ [...]
+ 17. Return true.
+features: [Proxy, Reflect]
+includes: [compareArray.js]
+---*/
+
+var getOwnPropertyKeys = [];
+var definePropertyKeys = [];
+
+var p = new Proxy({
+ foo: 1,
+}, {
+ getOwnPropertyDescriptor: function(target, key) {
+ getOwnPropertyKeys.push(key);
+ return Reflect.getOwnPropertyDescriptor(target, key);
+ },
+ defineProperty: function(target, key, desc) {
+ definePropertyKeys.push(key);
+ return Reflect.defineProperty(target, key, desc);
+ },
+});
+
+p["foo"] = 2;
+p.foo = 2;
+p.foo = 2;
+
+assert.compareArray(getOwnPropertyKeys, ["foo", "foo", "foo"],
+ "getOwnPropertyDescriptor: key present on [[ProxyTarget]]");
+assert.compareArray(definePropertyKeys, ["foo", "foo", "foo"],
+ "defineProperty: key present on [[ProxyTarget]]");
+
+getOwnPropertyKeys = [];
+definePropertyKeys = [];
+
+p.bar = 3;
+p["bar"] = 3;
+p.bar = 3;
+
+assert.compareArray(getOwnPropertyKeys, ["bar", "bar", "bar"],
+ "getOwnPropertyDescriptor: key absent on [[ProxyTarget]]");
+assert.compareArray(definePropertyKeys, ["bar", "bar", "bar"],
+ "defineProperty: key absent on [[ProxyTarget]]");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/trap-is-missing-target-is-proxy.js b/js/src/tests/test262/built-ins/Proxy/set/trap-is-missing-target-is-proxy.js
new file mode 100644
index 0000000000..1ef5cd59ac
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/trap-is-missing-target-is-proxy.js
@@ -0,0 +1,49 @@
+// Copyright (C) 2020 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
+description: >
+ If "set" trap is null or undefined, [[Set]] call is properly
+ forwarded to [[ProxyTarget]] (which is also a Proxy object).
+info: |
+ [[Set]] ( P, V, Receiver )
+
+ [...]
+ 5. Let target be O.[[ProxyTarget]].
+ 6. Let trap be ? GetMethod(handler, "set").
+ 7. If trap is undefined, then
+ a. Return ? target.[[Set]](P, V, Receiver).
+features: [Proxy, Reflect]
+---*/
+
+var barValue;
+var plainObject = {
+ get foo() {},
+ set bar(value) {
+ barValue = value;
+ },
+};
+
+var plainObjectTarget = new Proxy(plainObject, {});
+var plainObjectProxy = new Proxy(plainObjectTarget, {});
+
+plainObjectProxy.bar = 1;
+assert.sameValue(barValue, 1);
+
+assert.throws(TypeError, function() {
+ "use strict";
+ plainObjectProxy.foo = 2;
+});
+
+
+var regExp = /(?:)/g;
+var regExpTarget = new Proxy(regExp, {});
+var regExpProxy = new Proxy(regExpTarget, {});
+
+assert(!Reflect.set(regExpProxy, "global", true));
+
+regExpProxy.lastIndex = 1;
+assert.sameValue(regExp.lastIndex, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/trap-is-not-callable-realm.js b/js/src/tests/test262/built-ins/Proxy/set/trap-is-not-callable-realm.js
new file mode 100644
index 0000000000..07e710b1ee
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/trap-is-not-callable-realm.js
@@ -0,0 +1,33 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
+description: >
+ Throws if trap is not callable (honoring the Realm of the current execution
+ context)
+info: |
+ [[Set]] ( P, V, Receiver)
+
+ 6. Let trap be GetMethod(handler, "set").
+ ...
+
+ 7.3.9 GetMethod (O, P)
+
+ 5. If IsCallable(func) is false, throw a TypeError exception.
+features: [cross-realm, Proxy]
+---*/
+
+var OProxy = $262.createRealm().global.Proxy;
+var p = new OProxy({}, {
+ set: {}
+});
+
+assert.throws(TypeError, function() {
+ p.attr = 1;
+});
+
+assert.throws(TypeError, function() {
+ p["attr"] = 1;
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/trap-is-not-callable.js b/js/src/tests/test262/built-ins/Proxy/set/trap-is-not-callable.js
new file mode 100644
index 0000000000..60ca4a96d0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/trap-is-not-callable.js
@@ -0,0 +1,31 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.9
+description: >
+ Trap is not callable.
+info: |
+ [[Set]] ( P, V, Receiver)
+
+ 6. Let trap be GetMethod(handler, "set").
+ ...
+
+ 7.3.9 GetMethod (O, P)
+
+ 5. If IsCallable(func) is false, throw a TypeError exception.
+features: [Proxy]
+---*/
+
+var p = new Proxy({}, {
+ set: {}
+});
+
+assert.throws(TypeError, function() {
+ p.attr = 1;
+});
+
+assert.throws(TypeError, function() {
+ p["attr"] = 1;
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/trap-is-null-receiver.js b/js/src/tests/test262/built-ins/Proxy/set/trap-is-null-receiver.js
new file mode 100644
index 0000000000..ae93a63b62
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/trap-is-null-receiver.js
@@ -0,0 +1,32 @@
+// Copyright (C) 2016 Aleksey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
+description: >
+ Pass to target's [[Set]] correct receiver if trap is missing
+info: |
+ [[Set]] (P, V, Receiver)
+
+ 7. If trap is undefined, then
+ a. Return ? target.[[Set]](P, V, Receiver).
+features: [Proxy]
+---*/
+
+var context;
+var target = {
+ set attr(val) {
+ context = this;
+ }
+};
+
+var p = new Proxy(target, {
+ set: null
+});
+p.attr = 1;
+assert.sameValue(context, p);
+
+var pParent = Object.create(new Proxy(target, {}));
+pParent.attr = 3;
+assert.sameValue(context, pParent);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/trap-is-null-target-is-proxy.js b/js/src/tests/test262/built-ins/Proxy/set/trap-is-null-target-is-proxy.js
new file mode 100644
index 0000000000..4687576ddd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/trap-is-null-target-is-proxy.js
@@ -0,0 +1,51 @@
+// Copyright (C) 2020 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
+description: >
+ If "set" trap is null or undefined, [[Set]] call is properly
+ forwarded to [[ProxyTarget]] (which is also a Proxy object).
+info: |
+ [[Set]] ( P, V, Receiver )
+
+ [...]
+ 5. Let target be O.[[ProxyTarget]].
+ 6. Let trap be ? GetMethod(handler, "set").
+ 7. If trap is undefined, then
+ a. Return ? target.[[Set]](P, V, Receiver).
+features: [Proxy, Reflect]
+includes: [compareArray.js]
+---*/
+
+var array = [1, 2, 3];
+var arrayTarget = new Proxy(array, {});
+var arrayProxy = new Proxy(arrayTarget, {
+ set: null,
+});
+
+arrayProxy.length = 0;
+assert.compareArray(array, []);
+
+Object.preventExtensions(array);
+
+assert(!Reflect.set(arrayProxy, "foo", 2));
+assert.throws(TypeError, function() {
+ "use strict";
+ arrayProxy[0] = 3;
+});
+
+
+var string = new String("str");
+var stringTarget = new Proxy(string, {});
+var stringProxy = new Proxy(stringTarget, {
+ set: null,
+});
+
+stringProxy[4] = 1;
+assert.sameValue(string[4], 1);
+
+assert(!Reflect.set(stringProxy, "0", "s"));
+assert(!Reflect.set(stringProxy, "length", 3));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/trap-is-undefined-no-property.js b/js/src/tests/test262/built-ins/Proxy/set/trap-is-undefined-no-property.js
new file mode 100644
index 0000000000..8929897575
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/trap-is-undefined-no-property.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.9
+description: >
+ [[Set]] ( P, V, Receiver)
+
+ 8. If trap is undefined, then return target.[[Set]](P, V, Receiver).
+
+features: [Proxy]
+---*/
+
+var target = {
+ attr: 1
+};
+var p = new Proxy(target, {});
+
+p.attr = 2;
+
+assert.sameValue(target.attr, 2);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/trap-is-undefined-target-is-proxy.js b/js/src/tests/test262/built-ins/Proxy/set/trap-is-undefined-target-is-proxy.js
new file mode 100644
index 0000000000..ac2f7a8497
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/trap-is-undefined-target-is-proxy.js
@@ -0,0 +1,54 @@
+// Copyright (C) 2020 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
+description: >
+ If "set" trap is null or undefined, [[Set]] call is properly
+ forwarded to [[ProxyTarget]] (which is also a Proxy object).
+info: |
+ [[Set]] ( P, V, Receiver )
+
+ [...]
+ 5. Let target be O.[[ProxyTarget]].
+ 6. Let trap be ? GetMethod(handler, "set").
+ 7. If trap is undefined, then
+ a. Return ? target.[[Set]](P, V, Receiver).
+features: [Proxy, Reflect]
+---*/
+
+var func = function() {};
+var funcTarget = new Proxy(func, {});
+var funcProxy = new Proxy(funcTarget, {
+ set: undefined,
+});
+
+assert(Reflect.set(funcProxy, "prototype", null));
+assert.sameValue(func.prototype, null);
+
+assert(!Reflect.set(funcProxy, "length", 2));
+assert.throws(TypeError, function() {
+ "use strict";
+ funcProxy.name = "foo";
+});
+
+
+var trapCalls = 0;
+var target = new Proxy({}, {
+ set: function(_target, key) {
+ trapCalls++;
+ return key === "foo";
+ },
+});
+
+var proxy = new Proxy(target, {
+ set: undefined,
+});
+
+assert(Reflect.set(Object.create(proxy), "foo", 1));
+assert.sameValue(trapCalls, 1);
+
+assert(!Reflect.set(proxy, "bar", 2));
+assert.sameValue(trapCalls, 2);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/set/trap-is-undefined.js b/js/src/tests/test262/built-ins/Proxy/set/trap-is-undefined.js
new file mode 100644
index 0000000000..3bc6d09e01
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/set/trap-is-undefined.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
+description: >
+ [[Set]] ( P, V, Receiver)
+
+ 7. If trap is undefined, then
+ a. Return ? target.[[Set]](P, V, Receiver)
+
+features: [Proxy]
+---*/
+
+var target = {
+ attr: 1
+};
+var p = new Proxy(target, {
+ set: undefined
+});
+
+p.attr = 2;
+
+assert.sameValue(target.attr, 2);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/browser.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/browser.js
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/call-parameters.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/call-parameters.js
new file mode 100644
index 0000000000..bc5ac03d57
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/call-parameters.js
@@ -0,0 +1,41 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.2
+description: >
+ Trap is called with handler on its context, first parameter is target and
+ second parameter is the given value.
+info: |
+ [[SetPrototypeOf]] (V)
+
+ ...
+ 9. Let booleanTrapResult be ToBoolean(Call(trap, handler, «target, V»)).
+ ...
+features: [Proxy]
+---*/
+
+var _handler, _target, _value;
+var target = {};
+var val = {
+ foo: 1
+};
+var handler = {
+ setPrototypeOf: function(t, v) {
+ _handler = this;
+ _target = t;
+ _value = v;
+
+ Object.setPrototypeOf(t, v);
+
+ return true;
+ }
+};
+var p = new Proxy(target, handler);
+
+Object.setPrototypeOf(p, val);
+
+assert.sameValue(_handler, handler);
+assert.sameValue(_target, target);
+assert.sameValue(_value, val);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/internals-call-order.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/internals-call-order.js
new file mode 100644
index 0000000000..e6f3e20551
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/internals-call-order.js
@@ -0,0 +1,50 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v
+description: >
+ Calls target.[[GetPrototypeOf]] after trap result as false and not extensible
+ target
+info: |
+ [[SetPrototypeOf]] (V)
+
+ 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, « target, V »)).
+ 9. If booleanTrapResult is false, return false.
+ 10. Let extensibleTarget be ? IsExtensible(target).
+ 11. If extensibleTarget is true, return true.
+ 12. Let targetProto be ? target.[[GetPrototypeOf]]().
+features: [Proxy, Reflect, Reflect.setPrototypeOf]
+---*/
+
+var calls = [];
+var proto = {};
+
+var target = new Proxy(Object.create(proto), {
+ isExtensible: function() {
+ calls.push("target.[[IsExtensible]]");
+ return false;
+ },
+ getPrototypeOf: function() {
+ calls.push("target.[[GetPrototypeOf]]");
+ return proto;
+ }
+});
+
+// Proxy must report same extensiblitity as target
+Object.preventExtensions(target);
+
+var proxy = new Proxy(target, {
+ setPrototypeOf: function() {
+ calls.push("proxy.[[setPrototypeOf]]");
+ return true;
+ }
+});
+
+assert.sameValue(Reflect.setPrototypeOf(proxy, proto), true);
+assert.sameValue(calls.length, 3);
+assert.sameValue(calls[0], "proxy.[[setPrototypeOf]]");
+assert.sameValue(calls[1], "target.[[IsExtensible]]");
+assert.sameValue(calls[2], "target.[[GetPrototypeOf]]");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/not-extensible-target-not-same-target-prototype.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/not-extensible-target-not-same-target-prototype.js
new file mode 100644
index 0000000000..3c59f9a50e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/not-extensible-target-not-same-target-prototype.js
@@ -0,0 +1,55 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.2
+description: >
+ Throws a TypeError exception if boolean trap result is true, target is
+ not extensible, and the given parameter is not the same object as the target
+ prototype.
+info: |
+ [[SetPrototypeOf]] (V)
+
+ ...
+ 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
+ ...
+ 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
+ 6. Let trap be GetMethod(handler, "setPrototypeOf").
+ ...
+ 9. Let booleanTrapResult be ToBoolean(Call(trap, handler, «target, V»)).
+ 14. Let targetProto be target.[[GetPrototypeOf]]().
+ 15. ReturnIfAbrupt(targetProto).
+ 16. If booleanTrapResult is true and SameValue(V, targetProto) is false,
+ throw a TypeError exception.
+ ...
+features: [Proxy, Reflect, Reflect.setPrototypeOf]
+---*/
+
+var target, proxy;
+target = {};
+proxy = new Proxy(target, {
+ setPrototypeOf: function() {
+ return true;
+ }
+});
+
+Object.preventExtensions(target);
+
+assert.throws(TypeError, function() {
+ Reflect.setPrototypeOf(proxy, {});
+}, "target prototype is different");
+
+var proto = {};
+target = Object.setPrototypeOf({}, proto);
+proxy = new Proxy(target, {
+ setPrototypeOf: function() {
+ Object.setPrototypeOf(target, {});
+ Object.preventExtensions(target);
+ return true;
+ }
+});
+
+assert.throws(TypeError, function() {
+ Reflect.setPrototypeOf(proxy, proto);
+}, "target prototype is changed inside trap handler");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/not-extensible-target-same-target-prototype.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/not-extensible-target-same-target-prototype.js
new file mode 100644
index 0000000000..8910a2ddcd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/not-extensible-target-same-target-prototype.js
@@ -0,0 +1,56 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v
+description: >
+ Handler can only return true for non-extensible targets if the given prototype
+ is the same as target's prototype
+info: |
+ [[SetPrototypeOf]] (V)
+
+ 12. Let targetProto be ? target.[[GetPrototypeOf]]().
+ 13. If SameValue(V, targetProto) is false, throw a TypeError exception.
+ 14. Return true.
+features: [Proxy, Reflect, Reflect.setPrototypeOf]
+---*/
+
+var proto = {};
+var target = Object.setPrototypeOf({}, proto);
+
+Object.preventExtensions(target);
+
+var proxy;
+
+proxy = new Proxy(target, {
+ setPrototypeOf: function() {
+ return true;
+ }
+});
+
+assert.sameValue(
+ Reflect.setPrototypeOf(proxy, proto),
+ true,
+ "prototype arg is the same in target"
+);
+
+var outro = {};
+proxy = new Proxy(outro, {
+ setPrototypeOf: function(t, p) {
+ Object.setPrototypeOf(t, p);
+ Object.preventExtensions(t);
+ return true;
+ }
+});
+
+assert.sameValue(
+ Reflect.setPrototypeOf(proxy, proto),
+ true,
+ "prototype is set to target inside handler trap"
+);
+assert.sameValue(
+ Object.getPrototypeOf(outro),
+ proto,
+ "target has the custom set prototype"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/null-handler.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/null-handler.js
new file mode 100644
index 0000000000..71aa84b3ad
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/null-handler.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.2
+description: >
+ Throws a TypeError exception if handler is null
+features: [Proxy]
+---*/
+
+var p = Proxy.revocable({}, {});
+
+p.revoke();
+
+assert.throws(TypeError, function() {
+ Object.setPrototypeOf(p.proxy, {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/return-abrupt-from-get-trap.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/return-abrupt-from-get-trap.js
new file mode 100644
index 0000000000..aa525697bc
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/return-abrupt-from-get-trap.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-call-thisargument-argumentslist
+description: >
+ Return abrupt getting handler trap
+info: |
+ [[SetPrototypeOf]] (V)
+
+ 6. Let trap be ? GetMethod(handler, "setPrototypeOf").
+features: [Proxy]
+---*/
+
+var handler = Object.defineProperty({}, "setPrototypeOf", {
+ get: function() {
+ throw new Test262Error();
+ }
+});
+
+var proxy = new Proxy({}, handler);
+
+assert.throws(Test262Error, function() {
+ Object.setPrototypeOf(proxy, {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/return-abrupt-from-isextensible-target.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/return-abrupt-from-isextensible-target.js
new file mode 100644
index 0000000000..1ff2cb555c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/return-abrupt-from-isextensible-target.js
@@ -0,0 +1,31 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v
+description: >
+ Return abrupt from IsExtensible(target)
+info: |
+ [[SetPrototypeOf]] (V)
+
+ 10. Let extensibleTarget be ? IsExtensible(target).
+features: [Proxy]
+---*/
+
+var target = new Proxy({}, {
+ isExtensible: function() {
+ throw new Test262Error();
+ }
+});
+
+var proxy = new Proxy(target, {
+ setPrototypeOf: function() {
+ return true;
+ }
+});
+
+assert.throws(Test262Error, function() {
+ Object.setPrototypeOf(proxy, {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/return-abrupt-from-target-getprototypeof.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/return-abrupt-from-target-getprototypeof.js
new file mode 100644
index 0000000000..49173d7f77
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/return-abrupt-from-target-getprototypeof.js
@@ -0,0 +1,33 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v
+description: >
+ Return abrupt from target.[[GetPrototypeOf]]()
+info: |
+ [[SetPrototypeOf]] (V)
+
+ 12. Let targetProto be ? target.[[GetPrototypeOf]]().
+features: [Proxy]
+---*/
+
+var target = new Proxy({}, {
+ getPrototypeOf: function() {
+ throw new Test262Error();
+ }
+});
+
+Object.preventExtensions(target);
+
+var proxy = new Proxy(target, {
+ setPrototypeOf: function() {
+ return true;
+ }
+});
+
+assert.throws(Test262Error, function() {
+ Object.setPrototypeOf(proxy, {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/return-abrupt-from-trap.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/return-abrupt-from-trap.js
new file mode 100644
index 0000000000..b5d0c90d17
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/return-abrupt-from-trap.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.2
+description: >
+ Trap returns abrupt.
+info: |
+ [[SetPrototypeOf]] (V)
+
+ 9. Let booleanTrapResult be ToBoolean(Call(trap, handler, «target, V»)).
+ 10. ReturnIfAbrupt(booleanTrapResult).
+features: [Proxy]
+---*/
+
+var p = new Proxy({}, {
+ setPrototypeOf: function() {
+ throw new Test262Error();
+ }
+});
+
+assert.throws(Test262Error, function() {
+ Object.setPrototypeOf(p, {
+ value: 1
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/shell.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/shell.js
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/toboolean-trap-result-false.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/toboolean-trap-result-false.js
new file mode 100644
index 0000000000..8720cffbc7
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/toboolean-trap-result-false.js
@@ -0,0 +1,77 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v
+description: >
+ Return false if ToBoolean(trap result) is false, without checking
+ target.[[IsExtensible]]
+info: |
+ [[SetPrototypeOf]] (V)
+
+ 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, « target, V »)).
+ 9. If booleanTrapResult is false, return false.
+ 10. Let extensibleTarget be ? IsExtensible(target).
+ 11. If extensibleTarget is true, return true.
+features: [Proxy, Reflect, Reflect.setPrototypeOf]
+---*/
+
+var called = 0;
+
+var target = new Proxy({}, {
+ isExtensible: function() {
+ called += 1;
+ }
+});
+
+var p = new Proxy(target, {
+ setPrototypeOf: function(t, v) {
+ return v.attr;
+ }
+});
+
+var result;
+
+result = Reflect.setPrototypeOf(p, {
+ attr: false
+});
+assert.sameValue(result, false, "false");
+assert.sameValue(called, 0, "false - isExtensible is not called");
+
+result = Reflect.setPrototypeOf(p, {
+ attr: ""
+});
+assert.sameValue(result, false, "the empty string");
+assert.sameValue(called, 0, "the empty string - isExtensible is not called");
+
+result = Reflect.setPrototypeOf(p, {
+ attr: 0
+});
+assert.sameValue(result, false, "0");
+assert.sameValue(called, 0, "0 - isExtensible is not called");
+
+result = Reflect.setPrototypeOf(p, {
+ attr: -0
+});
+assert.sameValue(result, false, "-0");
+assert.sameValue(called, 0, "-0 - isExtensible is not called");
+
+result = Reflect.setPrototypeOf(p, {
+ attr: null
+});
+assert.sameValue(result, false, "null");
+assert.sameValue(called, 0, "null - isExtensible is not called");
+
+result = Reflect.setPrototypeOf(p, {
+ attr: undefined
+});
+assert.sameValue(result, false, "undefined");
+assert.sameValue(called, 0, "undefined - isExtensible is not called");
+
+result = Reflect.setPrototypeOf(p, {
+ attr: NaN
+});
+assert.sameValue(result, false, "NaN");
+assert.sameValue(called, 0, "NaN - isExtensible is not called");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/toboolean-trap-result-true-target-is-extensible.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/toboolean-trap-result-true-target-is-extensible.js
new file mode 100644
index 0000000000..6da14809f0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/toboolean-trap-result-true-target-is-extensible.js
@@ -0,0 +1,80 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v
+description: >
+ Return true if ToBoolean(trap result) is true, and target.[[IsExtensible]] is
+ true
+info: |
+ [[SetPrototypeOf]] (V)
+
+ 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, « target, V »)).
+ 9. If booleanTrapResult is false, return false.
+ 10. Let extensibleTarget be ? IsExtensible(target).
+ 11. If extensibleTarget is true, return true.
+features: [Proxy, Reflect, Reflect.setPrototypeOf, Symbol]
+---*/
+
+var called;
+var target = new Proxy({}, {
+ isExtensible: function() {
+ called += 1;
+ return true;
+ },
+ getPrototypeOf: function() {
+ throw new Test262Error("target.[[GetPrototypeOf]] is not called");
+ }
+});
+
+var p = new Proxy(target, {
+ setPrototypeOf: function(t, v) {
+ return v.attr;
+ }
+});
+
+var result;
+
+called = 0;
+result = Reflect.setPrototypeOf(p, {
+ attr: true
+});
+assert.sameValue(result, true, "true");
+assert.sameValue(called, 1, "true - isExtensible is called");
+
+called = 0;
+result = Reflect.setPrototypeOf(p, {
+ attr: "false"
+});
+assert.sameValue(result, true, "string");
+assert.sameValue(called, 1, "string - isExtensible is called");
+
+called = 0;
+result = Reflect.setPrototypeOf(p, {
+ attr: 42
+});
+assert.sameValue(result, true, "42");
+assert.sameValue(called, 1, "number - isExtensible is called");
+
+called = 0;
+result = Reflect.setPrototypeOf(p, {
+ attr: p
+});
+assert.sameValue(result, true, "p");
+assert.sameValue(called, 1, "object - isExtensible is called");
+
+called = 0;
+result = Reflect.setPrototypeOf(p, {
+ attr: []
+});
+assert.sameValue(result, true, "[]");
+assert.sameValue(called, 1, "[] - isExtensible is called");
+
+called = 0;
+result = Reflect.setPrototypeOf(p, {
+ attr: Symbol(1)
+});
+assert.sameValue(result, true, "symbol");
+assert.sameValue(called, 1, "symbol - isExtensible is called");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-missing-target-is-proxy.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-missing-target-is-proxy.js
new file mode 100644
index 0000000000..8a3f56b5cb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-missing-target-is-proxy.js
@@ -0,0 +1,38 @@
+// Copyright (C) 2020 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v
+description: >
+ If "setPrototypeOf" trap is null or undefined, [[SetPrototypeOf]] call
+ is properly forwarded to [[ProxyTarget]] (which is also a Proxy object).
+info: |
+ [[SetPrototypeOf]] ( V )
+
+ [...]
+ 5. Let target be O.[[ProxyTarget]].
+ 6. Let trap be ? GetMethod(handler, "setPrototypeOf").
+ 7. If trap is undefined, then
+ a. Return ? target.[[SetPrototypeOf]](V).
+
+ [[SetPrototypeOf]] ( V )
+
+ [...]
+ 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, V »)).
+ 9. If booleanTrapResult is false, return false.
+features: [Proxy]
+---*/
+
+var target = new Proxy({}, {
+ setPrototypeOf: function(_target, _value) {
+ return false;
+ },
+});
+
+var proxy = new Proxy(target, {});
+
+assert.throws(TypeError, function() {
+ Object.setPrototypeOf(proxy, null);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-not-callable-realm.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-not-callable-realm.js
new file mode 100644
index 0000000000..6bcdbf6d11
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-not-callable-realm.js
@@ -0,0 +1,36 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v
+description: >
+ Throws if trap is not callable (honoring the Realm of the current execution
+ context)
+info: |
+ [[SetPrototypeOf]] (V)
+
+ ...
+ 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
+ ...
+ 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
+ 6. Let trap be GetMethod(handler, "setPrototypeOf").
+ ...
+ 7.3.9 GetMethod (O, P)
+ ...
+ 2. Let func be GetV(O, P).
+ 5. If IsCallable(func) is false, throw a TypeError exception.
+ ...
+features: [cross-realm, Proxy]
+---*/
+
+var OProxy = $262.createRealm().global.Proxy;
+var p = new OProxy({}, {
+ setPrototypeOf: {}
+});
+
+assert.throws(TypeError, function() {
+ Object.setPrototypeOf(p, {
+ value: 1
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-not-callable.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-not-callable.js
new file mode 100644
index 0000000000..358588e831
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-not-callable.js
@@ -0,0 +1,35 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 9.5.2
+description: >
+ Throws a TypeError exception if trap is not callable.
+info: |
+ [[SetPrototypeOf]] (V)
+
+ ...
+ 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
+ ...
+ 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
+ 6. Let trap be GetMethod(handler, "setPrototypeOf").
+ ...
+ 7.3.9 GetMethod (O, P)
+ ...
+ 2. Let func be GetV(O, P).
+ 5. If IsCallable(func) is false, throw a TypeError exception.
+ ...
+features: [Proxy, Reflect, Reflect.setPrototypeOf]
+---*/
+
+var target = {};
+var p = new Proxy(target, {
+ setPrototypeOf: {}
+});
+
+assert.throws(TypeError, function() {
+ Reflect.setPrototypeOf(p, {
+ value: 1
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-null-target-is-proxy.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-null-target-is-proxy.js
new file mode 100644
index 0000000000..c9857e94aa
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-null-target-is-proxy.js
@@ -0,0 +1,42 @@
+// Copyright (C) 2020 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v
+description: >
+ If "setPrototypeOf" trap is null or undefined, [[SetPrototypeOf]] call
+ is properly forwarded to [[ProxyTarget]] (which is also a Proxy object).
+info: |
+ [[SetPrototypeOf]] ( V )
+
+ [...]
+ 5. Let target be O.[[ProxyTarget]].
+ 6. Let trap be ? GetMethod(handler, "setPrototypeOf").
+ 7. If trap is undefined, then
+ a. Return ? target.[[SetPrototypeOf]](V).
+
+ OrdinarySetPrototypeOf ( O, V )
+
+ [...]
+ 8. Repeat, while done is false,
+ a. If p is null, set done to true.
+ b. Else if SameValue(p, O) is true, return false.
+ [...]
+features: [Proxy]
+---*/
+
+var plainObject = {};
+var plainObjectTarget = new Proxy(plainObject, {});
+var plainObjectProxy = new Proxy(plainObjectTarget, {
+ setPrototypeOf: null,
+});
+
+Object.setPrototypeOf(plainObjectProxy, null);
+assert.sameValue(Object.getPrototypeOf(plainObject), null);
+
+var cyclicPrototype = Object.create(plainObject);
+assert.throws(TypeError, function() {
+ Object.setPrototypeOf(plainObjectProxy, cyclicPrototype);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-undefined-or-null.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-undefined-or-null.js
new file mode 100644
index 0000000000..84fa1c2d77
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-undefined-or-null.js
@@ -0,0 +1,47 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v
+description: >
+ Return target.[[SetPrototypeOf]] (V) if trap is undefined or null.
+info: |
+ [[SetPrototypeOf]] (V)
+
+ 6. Let trap be ? GetMethod(handler, "setPrototypeOf").
+ 7. If trap is undefined, then
+ a. Return ? target.[[SetPrototypeOf]](V).
+
+ GetMethod (V, P)
+
+ 2. Let func be ? GetV(V, P).
+ 3. If func is either undefined or null, return undefined.
+features: [Proxy]
+---*/
+
+var proxy, called, value;
+var target = new Proxy({}, {
+ setPrototypeOf: function(t, v) {
+ called += 1;
+ value = v;
+ return true;
+ }
+});
+var proto = {};
+
+proxy = new Proxy(target, {});
+called = 0;
+value = false;
+Object.setPrototypeOf(proxy, proto);
+assert.sameValue(called, 1, "undefined, target.[[SetPrototypeOf]] is called");
+assert.sameValue(value, proto, "undefined, called with V");
+
+proxy = new Proxy(target, {
+ setPrototypeOf: null
+});
+called = 0;
+value = false;
+Object.setPrototypeOf(proxy, proto);
+assert.sameValue(called, 1, "null, target.[[SetPrototypeOf]] is called");
+assert.sameValue(value, proto, "null, called with V");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-undefined-target-is-proxy.js b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-undefined-target-is-proxy.js
new file mode 100644
index 0000000000..091fe8abb4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Proxy/setPrototypeOf/trap-is-undefined-target-is-proxy.js
@@ -0,0 +1,40 @@
+// Copyright (C) 2020 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v
+description: >
+ If "setPrototypeOf" trap is null or undefined, [[SetPrototypeOf]] call
+ is properly forwarded to [[ProxyTarget]] (which is also a Proxy object).
+info: |
+ [[SetPrototypeOf]] ( V )
+
+ [...]
+ 5. Let target be O.[[ProxyTarget]].
+ 6. Let trap be ? GetMethod(handler, "setPrototypeOf").
+ 7. If trap is undefined, then
+ a. Return ? target.[[SetPrototypeOf]](V).
+
+ OrdinarySetPrototypeOf ( O, V )
+
+ [...]
+ 4. Let extensible be O.[[Extensible]].
+ 5. If extensible is false, return false.
+features: [Proxy]
+---*/
+
+var array = [];
+var arrayTarget = new Proxy(array, {});
+var arrayProxy = new Proxy(arrayTarget, {
+ setPrototypeOf: undefined,
+});
+
+Object.setPrototypeOf(arrayProxy, Number.prototype);
+assert.sameValue(Object.getPrototypeOf(array), Number.prototype);
+
+Object.preventExtensions(array);
+assert.throws(TypeError, function() {
+ Object.setPrototypeOf(arrayProxy, null);
+});
+
+reportCompare(0, 0);