From: Paul Jolly Date: Mon, 2 Jul 2018 07:08:14 +0000 (+0100) Subject: misc/wasm: use single map for string, symbol and object id mapping. X-Git-Tag: go1.11beta2~215 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=abaf53fb8e7dfbb9d513745e8280488b159ceb1e;p=gostls13.git 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 TryBot-Result: Gobot Gobot Reviewed-by: Richard Musiol --- diff --git a/misc/wasm/wasm_exec.js b/misc/wasm/wasm_exec.js index 3617c49866..7246d7bc71 100644 --- a/misc/wasm/wasm_exec.js +++ b/misc/wasm/wasm_exec.js @@ -118,33 +118,11 @@ return; } - if (typeof v === "string") { - let ref = this._stringRefs.get(v); - 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) { + let ref = this._refs.get(v); + if (ref === undefined) { ref = this._values.length; this._values.push(v); - v[this._refProp] = ref; + this._refs.set(v, ref); } mem().setUint32(addr, ref, true); } @@ -335,9 +313,7 @@ setTimeout(this._resolveCallbackPromise, 0); // make sure it is asynchronous }, ]; - this._stringRefs = new Map(); - this._symbolRefs = new Map(); - this._refProp = Symbol(); + this._refs = new Map(); this.exited = false; const mem = new DataView(this._inst.exports.mem.buffer) diff --git a/src/syscall/js/js_test.go b/src/syscall/js/js_test.go index c4141c2196..69b5209821 100644 --- a/src/syscall/js/js_test.go +++ b/src/syscall/js/js_test.go @@ -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) { testTypedArrayOf(t, "[]int8", []int8{0, -42, 0}, -42) testTypedArrayOf(t, "[]int16", []int16{0, -42, 0}, -42)