Commit abaf53fb authored by Paul Jolly's avatar Paul Jolly Committed by Paul Jolly

misc/wasm: use single map for string, symbol and object id mapping.

Currently we use a globally unique symbol property on objects that get
passed from JavaScript to Go to store a unique ID that Go then uses when
referring back to the JavaScript object (via js.Value.ref). This
approach fails however when a JavaScript object cannot be modified, i.e.
cannot have new properties added or is frozen. The test that is added as
part of this commit currently fails with:

  Cannot add property Symbol(), object is not extensible

Instead we consolidate the string, symbol and object unique ID mapping
into a single map. Map key equality is determined via strict equality,
which is the semantic we want in this situation.

Change-Id: Ieb2b50fc36d3c30e148aa7a41557f3c59cd33766
Reviewed-on: https://go-review.googlesource.com/121799
Run-TryBot: Paul Jolly <paul@myitcv.org.uk>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarRichard Musiol <neelance@gmail.com>
parent 5d4f0474
...@@ -118,33 +118,11 @@ ...@@ -118,33 +118,11 @@
return; return;
} }
if (typeof v === "string") { let ref = this._refs.get(v);
let ref = this._stringRefs.get(v); if (ref === undefined) {
if (ref === undefined) {
ref = this._values.length;
this._values.push(v);
this._stringRefs.set(v, ref);
}
mem().setUint32(addr, ref, true);
return;
}
if (typeof v === "symbol") {
let ref = this._symbolRefs.get(v);
if (ref === undefined) {
ref = this._values.length;
this._values.push(v);
this._symbolRefs.set(v, ref);
}
mem().setUint32(addr, ref, true);
return;
}
let ref = v[this._refProp];
if (ref === undefined || this._values[ref] !== v) {
ref = this._values.length; ref = this._values.length;
this._values.push(v); this._values.push(v);
v[this._refProp] = ref; this._refs.set(v, ref);
} }
mem().setUint32(addr, ref, true); mem().setUint32(addr, ref, true);
} }
...@@ -335,9 +313,7 @@ ...@@ -335,9 +313,7 @@
setTimeout(this._resolveCallbackPromise, 0); // make sure it is asynchronous setTimeout(this._resolveCallbackPromise, 0); // make sure it is asynchronous
}, },
]; ];
this._stringRefs = new Map(); this._refs = new Map();
this._symbolRefs = new Map();
this._refProp = Symbol();
this.exited = false; this.exited = false;
const mem = new DataView(this._inst.exports.mem.buffer) const mem = new DataView(this._inst.exports.mem.buffer)
......
...@@ -116,6 +116,14 @@ func TestObject(t *testing.T) { ...@@ -116,6 +116,14 @@ func TestObject(t *testing.T) {
} }
} }
func TestFrozenObject(t *testing.T) {
o := js.Global().Call("eval", "(function () { let o = new Object(); o.field = 5; Object.freeze(o); return o; })()")
want := 5
if got := o.Get("field").Int(); want != got {
t.Errorf("got %#v, want %#v", got, want)
}
}
func TestTypedArrayOf(t *testing.T) { func TestTypedArrayOf(t *testing.T) {
testTypedArrayOf(t, "[]int8", []int8{0, -42, 0}, -42) testTypedArrayOf(t, "[]int8", []int8{0, -42, 0}, -42)
testTypedArrayOf(t, "[]int16", []int16{0, -42, 0}, -42) testTypedArrayOf(t, "[]int16", []int16{0, -42, 0}, -42)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment