Fix "PR c++/92804 ICE trying to use concept as a nested-name-specifier"
[official-gcc.git] / libgo / go / syscall / js / func.go
blob6c145c9da6f44bcb660323e225ca26f68b8e80f8
1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // +build js,wasm
7 package js
9 import "sync"
11 var (
12 funcsMu sync.Mutex
13 funcs = make(map[uint32]func(Value, []Value) interface{})
14 nextFuncID uint32 = 1
17 var _ Wrapper = Func{} // Func must implement Wrapper
19 // Func is a wrapped Go function to be called by JavaScript.
20 type Func struct {
21 Value // the JavaScript function that invokes the Go function
22 id uint32
25 // FuncOf returns a wrapped function.
27 // Invoking the JavaScript function will synchronously call the Go function fn with the value of JavaScript's
28 // "this" keyword and the arguments of the invocation.
29 // The return value of the invocation is the result of the Go function mapped back to JavaScript according to ValueOf.
31 // A wrapped function triggered during a call from Go to JavaScript gets executed on the same goroutine.
32 // A wrapped function triggered by JavaScript's event loop gets executed on an extra goroutine.
33 // Blocking operations in the wrapped function will block the event loop.
34 // As a consequence, if one wrapped function blocks, other wrapped funcs will not be processed.
35 // A blocking function should therefore explicitly start a new goroutine.
37 // Func.Release must be called to free up resources when the function will not be used any more.
38 func FuncOf(fn func(this Value, args []Value) interface{}) Func {
39 funcsMu.Lock()
40 id := nextFuncID
41 nextFuncID++
42 funcs[id] = fn
43 funcsMu.Unlock()
44 return Func{
45 id: id,
46 Value: jsGo.Call("_makeFuncWrapper", id),
50 // Release frees up resources allocated for the function.
51 // The function must not be invoked after calling Release.
52 func (c Func) Release() {
53 funcsMu.Lock()
54 delete(funcs, c.id)
55 funcsMu.Unlock()
58 // setEventHandler is defined in the runtime package.
59 func setEventHandler(fn func())
61 func init() {
62 setEventHandler(handleEvent)
65 func handleEvent() {
66 cb := jsGo.Get("_pendingEvent")
67 if cb.IsNull() {
68 return
70 jsGo.Set("_pendingEvent", Null())
72 id := uint32(cb.Get("id").Int())
73 if id == 0 { // zero indicates deadlock
74 select {}
76 funcsMu.Lock()
77 f, ok := funcs[id]
78 funcsMu.Unlock()
79 if !ok {
80 Global().Get("console").Call("error", "call to released function")
81 return
84 this := cb.Get("this")
85 argsObj := cb.Get("args")
86 args := make([]Value, argsObj.Length())
87 for i := range args {
88 args[i] = argsObj.Index(i)
90 result := f(this, args)
91 cb.Set("result", result)