mirror of
https://github.com/golang/go
synced 2024-11-21 17:14:45 -07:00
syscall/js: auto recycle Func
This commit is contained in:
parent
807e01db48
commit
0f6f58fa9b
@ -115,6 +115,12 @@
|
|||||||
this._pendingEvent = null;
|
this._pendingEvent = null;
|
||||||
this._scheduledTimeouts = new Map();
|
this._scheduledTimeouts = new Map();
|
||||||
this._nextCallbackTimeoutID = 1;
|
this._nextCallbackTimeoutID = 1;
|
||||||
|
this._cleanup = null;
|
||||||
|
this._registry = new FinalizationRegistry((func, id) => {
|
||||||
|
if (this._cleanup) {
|
||||||
|
this._cleanup(id);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const setInt64 = (addr, v) => {
|
const setInt64 = (addr, v) => {
|
||||||
this.mem.setUint32(addr + 0, v, true);
|
this.mem.setUint32(addr + 0, v, true);
|
||||||
@ -563,12 +569,17 @@
|
|||||||
|
|
||||||
_makeFuncWrapper(id) {
|
_makeFuncWrapper(id) {
|
||||||
const go = this;
|
const go = this;
|
||||||
return function () {
|
const f = function () {
|
||||||
const event = { id: id, this: this, args: arguments };
|
const event = { id: id, this: this, args: arguments };
|
||||||
go._pendingEvent = event;
|
go._pendingEvent = event;
|
||||||
go._resume();
|
go._resume();
|
||||||
return event.result;
|
return event.result;
|
||||||
};
|
};
|
||||||
|
// Should never remove the cleanup function
|
||||||
|
if (id !== 1) {
|
||||||
|
this._registry.register(f, id);
|
||||||
|
}
|
||||||
|
return f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -9,7 +9,8 @@ package js
|
|||||||
import "sync"
|
import "sync"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
funcsMu sync.Mutex
|
funcsMu sync.Mutex
|
||||||
|
// funcID 1 is reserved for func garbage collection callback.
|
||||||
funcs = make(map[uint32]func(Value, []Value) any)
|
funcs = make(map[uint32]func(Value, []Value) any)
|
||||||
nextFuncID uint32 = 1
|
nextFuncID uint32 = 1
|
||||||
)
|
)
|
||||||
@ -36,8 +37,6 @@ type Func struct {
|
|||||||
// API, which requires the event loop, like fetch (http.Client), will cause an
|
// API, which requires the event loop, like fetch (http.Client), will cause an
|
||||||
// immediate deadlock. Therefore a blocking function should explicitly start a
|
// immediate deadlock. Therefore a blocking function should explicitly start a
|
||||||
// new goroutine.
|
// new goroutine.
|
||||||
//
|
|
||||||
// Func.Release must be called to free up resources when the function will not be invoked any more.
|
|
||||||
func FuncOf(fn func(this Value, args []Value) any) Func {
|
func FuncOf(fn func(this Value, args []Value) any) Func {
|
||||||
funcsMu.Lock()
|
funcsMu.Lock()
|
||||||
id := nextFuncID
|
id := nextFuncID
|
||||||
@ -50,13 +49,9 @@ func FuncOf(fn func(this Value, args []Value) any) Func {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release frees up resources allocated for the function.
|
// Release is a no-op method, the function is automatically released
|
||||||
// The function must not be invoked after calling Release.
|
// when it is garbage collected on the JavaScript side.
|
||||||
// It is allowed to call Release while the function is still running.
|
|
||||||
func (c Func) Release() {
|
func (c Func) Release() {
|
||||||
funcsMu.Lock()
|
|
||||||
delete(funcs, c.id)
|
|
||||||
funcsMu.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// setEventHandler is defined in the runtime package.
|
// setEventHandler is defined in the runtime package.
|
||||||
@ -64,6 +59,19 @@ func setEventHandler(fn func() bool)
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
setEventHandler(handleEvent)
|
setEventHandler(handleEvent)
|
||||||
|
|
||||||
|
// Set func garbage collection callback.
|
||||||
|
cleanup := FuncOf(func(this Value, args []Value) any {
|
||||||
|
id := uint32(args[0].Int())
|
||||||
|
funcsMu.Lock()
|
||||||
|
delete(funcs, id)
|
||||||
|
funcsMu.Unlock()
|
||||||
|
return Undefined()
|
||||||
|
})
|
||||||
|
if cleanup.id != 1 {
|
||||||
|
panic("bad function id for cleanup")
|
||||||
|
}
|
||||||
|
jsGo.Set("_cleanup", cleanup)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleEvent retrieves the pending event (window._pendingEvent) and calls the js.Func on it.
|
// handleEvent retrieves the pending event (window._pendingEvent) and calls the js.Func on it.
|
||||||
|
Loading…
Reference in New Issue
Block a user