syscall/js: prepare IDs for the preset objects

Fixes #38899

Change-Id: Ib8131c3078c60dc3fe2cf0eaac45b25a4f6e4649
Reviewed-on: https://go-review.googlesource.com/c/go/+/232518
Run-TryBot: Hajime Hoshi <hajimehoshi@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Richard Musiol <neelance@gmail.com>
This commit is contained in:
Hajime Hoshi 2020-05-06 23:00:58 +09:00
parent 8c1db77a92
commit a0698a6b60
2 changed files with 32 additions and 27 deletions

View File

@ -175,37 +175,19 @@
const storeValue = (addr, v) => { const storeValue = (addr, v) => {
const nanHead = 0x7FF80000; const nanHead = 0x7FF80000;
if (typeof v === "number") { if (typeof v === "number" && v !== 0) {
if (isNaN(v)) { if (isNaN(v)) {
this.mem.setUint32(addr + 4, nanHead, true); this.mem.setUint32(addr + 4, nanHead, true);
this.mem.setUint32(addr, 0, true); this.mem.setUint32(addr, 0, true);
return; return;
} }
if (v === 0) {
this.mem.setUint32(addr + 4, nanHead, true);
this.mem.setUint32(addr, 1, true);
return;
}
this.mem.setFloat64(addr, v, true); this.mem.setFloat64(addr, v, true);
return; return;
} }
switch (v) { if (v === undefined) {
case undefined: this.mem.setFloat64(addr, 0, true);
this.mem.setFloat64(addr, 0, true); return;
return;
case null:
this.mem.setUint32(addr + 4, nanHead, true);
this.mem.setUint32(addr, 2, true);
return;
case true:
this.mem.setUint32(addr + 4, nanHead, true);
this.mem.setUint32(addr, 3, true);
return;
case false:
this.mem.setUint32(addr + 4, nanHead, true);
this.mem.setUint32(addr, 4, true);
return;
} }
let id = this._ids.get(v); let id = this._ids.get(v);
@ -219,8 +201,13 @@
this._ids.set(v, id); this._ids.set(v, id);
} }
this._goRefCounts[id]++; this._goRefCounts[id]++;
let typeFlag = 1; let typeFlag = 0;
switch (typeof v) { switch (typeof v) {
case "object":
if (v !== null) {
typeFlag = 1;
}
break;
case "string": case "string":
typeFlag = 2; typeFlag = 2;
break; break;
@ -493,10 +480,17 @@
global, global,
this, this,
]; ];
this._goRefCounts = []; // number of references that Go has to a JS value, indexed by reference id this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id
this._ids = new Map(); // mapping from JS values to reference ids this._ids = new Map([ // mapping from JS values to reference ids
this._idPool = []; // unused ids that have been garbage collected [0, 1],
this.exited = false; // whether the Go program has exited [null, 2],
[true, 3],
[false, 4],
[global, 5],
[this, 6],
]);
this._idPool = []; // unused ids that have been garbage collected
this.exited = false; // whether the Go program has exited
// Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory. // Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory.
let offset = 4096; let offset = 4096;

View File

@ -591,3 +591,14 @@ func BenchmarkDOM(b *testing.B) {
document.Get("body").Call("removeChild", div) document.Get("body").Call("removeChild", div)
} }
} }
func TestGlobal(t *testing.T) {
ident := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
return args[0]
})
defer ident.Release()
if got := ident.Invoke(js.Global()); !got.Equal(js.Global()) {
t.Errorf("got %#v, want %#v", got, js.Global())
}
}