summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/proxy/testDirectProxySet10.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/proxy/testDirectProxySet10.js')
-rw-r--r--js/src/jit-test/tests/proxy/testDirectProxySet10.js60
1 files changed, 60 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/proxy/testDirectProxySet10.js b/js/src/jit-test/tests/proxy/testDirectProxySet10.js
new file mode 100644
index 0000000000..287cced8f3
--- /dev/null
+++ b/js/src/jit-test/tests/proxy/testDirectProxySet10.js
@@ -0,0 +1,60 @@
+// Assigning to a non-existing property of a plain object defines that
+// property on that object, even if a proxy is on the proto chain.
+
+// Create an object that behaves just like obj except it throws (instead of
+// returning undefined) if you try to get a property that doesn't exist.
+function throwIfNoSuchProperty(obj) {
+ return new Proxy(obj, {
+ get(t, id) {
+ if (id in t)
+ return t[id];
+ throw new Error("no such handler method: " + id);
+ }
+ });
+}
+
+// Use a touchy object as our proxy handler in this test.
+var hits = 0, savedDesc = undefined;
+var touchyHandler = throwIfNoSuchProperty({
+ set: undefined
+});
+var target = {};
+var proto = new Proxy(target, touchyHandler);
+var receiver = Object.create(proto);
+
+// This assignment `receiver.x = 2` results in a series of [[Set]] calls,
+// starting with:
+//
+// - receiver.[[Set]]()
+// - receiver is an ordinary object.
+// - This looks for an own property "x" on receiver. There is none.
+// - So it walks the prototype chain, doing a tail-call to:
+// - proto.[[Set]]()
+// - proto is a proxy.
+// - This does handler.[[Get]]("set") to look for a set trap
+// (that's why we need `set: undefined` on the handler, above)
+// - Since there's no "set" handler, it tail-calls:
+// - target.[[Set]]()
+// - ordinary
+// - no own property "x"
+// - tail call to:
+// - Object.prototype.[[Set]]()
+// - ordinary
+// - no own property "x"
+// - We're at the end of the line: there's nothing left on the proto chain.
+// - So at last we call:
+// - receiver.[[DefineOwnProperty]]()
+// - ordinary
+// - creates the property
+//
+// Got all that? Let's try it.
+//
+receiver.x = 2;
+assertEq(receiver.x, 2);
+
+var desc = Object.getOwnPropertyDescriptor(receiver, "x");
+assertEq(desc.enumerable, true);
+assertEq(desc.configurable, true);
+assertEq(desc.writable, true);
+assertEq(desc.value, 2);
+