Skip to content

Commit 91b1445

Browse files
committed
syscall/js: revise for go1.12
Update #3
1 parent 37b5a51 commit 91b1445

File tree

4 files changed

+147
-133
lines changed

4 files changed

+147
-133
lines changed

gosrc/1.11.5/syscall/js/callback.go

Lines changed: 0 additions & 122 deletions
This file was deleted.

gosrc/1.11.5/syscall/js/func.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
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.
4+
5+
// +build js,wasm
6+
7+
package js
8+
9+
import "sync"
10+
11+
var (
12+
funcsMu sync.Mutex
13+
funcs = make(map[uint32]func(Value, []Value) interface{})
14+
nextFuncID uint32 = 1
15+
)
16+
17+
var _ Wrapper = Func{} // Func must implement Wrapper
18+
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
23+
}
24+
25+
// FuncOf returns a wrapped function.
26+
//
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.
30+
//
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.
36+
//
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),
47+
}
48+
}
49+
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()
56+
}
57+
58+
// setEventHandler is defined in the runtime package.
59+
func setEventHandler(fn func())
60+
61+
func init() {
62+
setEventHandler(handleEvent)
63+
}
64+
65+
func handleEvent() {
66+
cb := jsGo.Get("_pendingEvent")
67+
if cb == Null() {
68+
return
69+
}
70+
jsGo.Set("_pendingEvent", Null())
71+
72+
id := uint32(cb.Get("id").Int())
73+
if id == 0 { // zero indicates deadlock
74+
select {}
75+
}
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
82+
}
83+
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)
89+
}
90+
result := f(this, args)
91+
cb.Set("result", result)
92+
}

gosrc/1.11.5/syscall/js/js.go

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,32 @@ import (
1616
)
1717

1818
// ref is used to identify a JavaScript value, since the value itself can not be passed to WebAssembly.
19-
// A JavaScript number (64-bit float, except NaN) is represented by its IEEE 754 binary representation.
19+
//
20+
// The JavaScript value "undefined" is represented by the value 0.
21+
// A JavaScript number (64-bit float, except 0 and NaN) is represented by its IEEE 754 binary representation.
2022
// All other values are represented as an IEEE 754 binary representation of NaN with bits 0-31 used as
2123
// an ID and bits 32-33 used to differentiate between string, symbol, function and object.
2224
type ref uint64
2325

24-
// nanHead are the upper 32 bits of a ref which are set if the value is not a JavaScript number or NaN itself.
26+
// nanHead are the upper 32 bits of a ref which are set if the value is not encoded as an IEEE 754 number (see above).
2527
const nanHead = 0x7FF80000
2628

27-
// Value represents a JavaScript value.
29+
// Wrapper is implemented by types that are backed by a JavaScript value.
30+
type Wrapper interface {
31+
// JSValue returns a JavaScript value associated with an object.
32+
JSValue() Value
33+
}
34+
35+
// Value represents a JavaScript value. The zero value is the JavaScript value "undefined".
2836
type Value struct {
2937
ref ref
3038
}
3139

40+
// JSValue implements Wrapper interface.
41+
func (v Value) JSValue() Value {
42+
return v
43+
}
44+
3245
func makeValue(v ref) Value {
3346
return Value{ref: v}
3447
}
@@ -38,6 +51,9 @@ func predefValue(id uint32) Value {
3851
}
3952

4053
func floatValue(f float64) Value {
54+
if f == 0 {
55+
return valueZero
56+
}
4157
if f != f {
4258
return valueNaN
4359
}
@@ -56,8 +72,9 @@ func (e Error) Error() string {
5672
}
5773

5874
var (
75+
valueUndefined = Value{ref: 0}
5976
valueNaN = predefValue(0)
60-
valueUndefined = predefValue(1)
77+
valueZero = predefValue(1)
6178
valueNull = predefValue(2)
6279
valueTrue = predefValue(3)
6380
valueFalse = predefValue(4)
@@ -90,21 +107,21 @@ func Global() Value {
90107
// | ---------------------- | ---------------------- |
91108
// | js.Value | [its value] |
92109
// | js.TypedArray | typed array |
93-
// | js.Callback | function |
110+
// | js.Func | function |
94111
// | nil | null |
95112
// | bool | boolean |
96113
// | integers and floats | number |
97114
// | string | string |
98115
// | []interface{} | new array |
99116
// | map[string]interface{} | new object |
117+
//
118+
// Panics if x is not one of the expected types.
100119
func ValueOf(x interface{}) Value {
101120
switch x := x.(type) {
102-
case Value:
121+
case Value: // should precede Wrapper to avoid a loop
103122
return x
104-
case TypedArray:
105-
return x.Value
106-
case Callback:
107-
return x.Value
123+
case Wrapper:
124+
return x.JSValue()
108125
case nil:
109126
return valueNull
110127
case bool:
@@ -318,13 +335,18 @@ func (v Value) New(args ...interface{}) Value {
318335
func valueNew(v ref, args []ref) (ref, bool)
319336

320337
func (v Value) isNumber() bool {
321-
return v.ref>>32&nanHead != nanHead || v.ref == valueNaN.ref
338+
return v.ref == valueZero.ref ||
339+
v.ref == valueNaN.ref ||
340+
(v.ref != valueUndefined.ref && v.ref>>32&nanHead != nanHead)
322341
}
323342

324343
func (v Value) float(method string) float64 {
325344
if !v.isNumber() {
326345
panic(&ValueError{method, v.Type()})
327346
}
347+
if v.ref == valueZero.ref {
348+
return 0
349+
}
328350
return *(*float64)(unsafe.Pointer(&v.ref))
329351
}
330352

@@ -350,6 +372,26 @@ func (v Value) Bool() bool {
350372
}
351373
}
352374

375+
// Truthy returns the JavaScript "truthiness" of the value v. In JavaScript,
376+
// false, 0, "", null, undefined, and NaN are "falsy", and everything else is
377+
// "truthy". See https://developer.mozilla.org/en-US/docs/Glossary/Truthy.
378+
func (v Value) Truthy() bool {
379+
switch v.Type() {
380+
case TypeUndefined, TypeNull:
381+
return false
382+
case TypeBoolean:
383+
return v.Bool()
384+
case TypeNumber:
385+
return v.ref != valueNaN.ref && v.ref != valueZero.ref
386+
case TypeString:
387+
return v.String() != ""
388+
case TypeSymbol, TypeFunction, TypeObject:
389+
return true
390+
default:
391+
panic("bad type")
392+
}
393+
}
394+
353395
// String returns the value v converted to string according to JavaScript type conversions.
354396
func (v Value) String() string {
355397
str, length := valuePrepareString(v.ref)

gosrc/1.11.5/syscall/js/typedarray.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ var (
2222
float64Array = Global().Get("Float64Array")
2323
)
2424

25+
var _ Wrapper = TypedArray{} // TypedArray must implement Wrapper
26+
2527
// TypedArray represents a JavaScript typed array.
2628
type TypedArray struct {
2729
Value

0 commit comments

Comments
 (0)