Skip to content

Commit dfa4ee6

Browse files
committed
Add syscall/js
1 parent bd77b11 commit dfa4ee6

File tree

4 files changed

+564
-4
lines changed

4 files changed

+564
-4
lines changed

build/build.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ func importWithSrcDir(bctx build.Context, path string, srcDir string, mode build
139139
if installSuffix != "" {
140140
bctx.InstallSuffix += "_" + installSuffix
141141
}
142+
case "syscall/js":
143+
// There are no buildable files in this package, but we need to use files in the virtual directory.
144+
mode |= build.FindOnly
142145
case "math/big":
143146
// Use pure Go version of math/big; we don't want non-Go assembly versions.
144147
bctx.BuildTags = append(bctx.BuildTags, "math_big_pure_go")

compiler/natives/fs_vfsdata.go

Lines changed: 19 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

compiler/natives/src/syscall/js/js.go

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
// +build js
2+
3+
package js
4+
5+
import (
6+
"reflect"
7+
"unsafe"
8+
9+
"github.com/gopherjs/gopherjs/js"
10+
)
11+
12+
type Type int
13+
14+
const (
15+
TypeUndefined Type = iota
16+
TypeNull
17+
TypeBoolean
18+
TypeNumber
19+
TypeString
20+
TypeSymbol
21+
TypeObject
22+
TypeFunction
23+
)
24+
25+
func (t Type) String() string {
26+
switch t {
27+
case TypeUndefined:
28+
return "undefined"
29+
case TypeNull:
30+
return "null"
31+
case TypeBoolean:
32+
return "boolean"
33+
case TypeNumber:
34+
return "number"
35+
case TypeString:
36+
return "string"
37+
case TypeSymbol:
38+
return "symbol"
39+
case TypeObject:
40+
return "object"
41+
case TypeFunction:
42+
return "function"
43+
default:
44+
panic("bad type")
45+
}
46+
}
47+
48+
func Global() Value {
49+
return Value{v: js.Global}
50+
}
51+
52+
func Null() Value {
53+
return Value{v: nil}
54+
}
55+
56+
func Undefined() Value {
57+
return Value{v: js.Undefined}
58+
}
59+
60+
type Func struct {
61+
Value
62+
}
63+
64+
func (f Func) Release() {
65+
f.Value = Null()
66+
}
67+
68+
func FuncOf(fn func(this Value, args []Value) interface{}) Func {
69+
return Func{
70+
Value: Value{
71+
v: js.MakeFunc(func(this *js.Object, args []*js.Object) interface{} {
72+
vargs := make([]Value, len(args))
73+
for i, a := range args {
74+
vargs[i] = Value{a}
75+
}
76+
return fn(Value{this}, vargs)
77+
}),
78+
},
79+
}
80+
}
81+
82+
type Error struct {
83+
Value
84+
}
85+
86+
func (e Error) Error() string {
87+
return "JavaScript error: " + e.Get("message").String()
88+
}
89+
90+
type Value struct {
91+
v *js.Object
92+
}
93+
94+
var (
95+
id *js.Object
96+
instanceOf *js.Object
97+
getValueType *js.Object
98+
)
99+
100+
func init() {
101+
if js.Global != nil {
102+
id = js.Global.Call("eval", "(function(x) { return x; })")
103+
instanceOf = js.Global.Call("eval", "(function(x, y) { return x instanceof y; })")
104+
getValueType = js.Global.Call("eval", `(function(x) {
105+
if (typeof(x) === "undefined") {
106+
return 0; // TypeUndefined
107+
}
108+
if (x === null) {
109+
return 1; // TypeNull
110+
}
111+
if (typeof(x) === "boolean") {
112+
return 2; // TypeBoolean
113+
}
114+
if (typeof(x) === "number") {
115+
return 3; // TypeNumber
116+
}
117+
if (typeof(x) === "string") {
118+
return 4; // TypeString
119+
}
120+
if (typeof(x) === "symbol") {
121+
return 5; // TypeSymbol
122+
}
123+
if (typeof(x) === "function") {
124+
return 7; // TypeFunction
125+
}
126+
return 6; // TypeObject
127+
})`)
128+
}
129+
}
130+
131+
func ValueOf(x interface{}) Value {
132+
switch x := x.(type) {
133+
case Value:
134+
return x
135+
case Func:
136+
return x.Value
137+
case TypedArray:
138+
return x.Value
139+
case nil:
140+
return Null()
141+
case bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, unsafe.Pointer, string, map[string]interface{}, []interface{}:
142+
return Value{v: id.Invoke(x)}
143+
default:
144+
panic(`invalid arg: ` + reflect.TypeOf(x).String())
145+
}
146+
}
147+
148+
func (v Value) Bool() bool {
149+
if vType := v.Type(); vType != TypeBoolean {
150+
panic(&ValueError{"Value.Bool", vType})
151+
}
152+
return v.v.Bool()
153+
}
154+
155+
func convertArgs(args []interface{}) []interface{} {
156+
newArgs := []interface{}{}
157+
for _, arg := range args {
158+
v := ValueOf(arg)
159+
newArgs = append(newArgs, v.v)
160+
}
161+
return newArgs
162+
}
163+
164+
func (v Value) Call(m string, args ...interface{}) Value {
165+
if vType := v.Type(); vType != TypeObject && vType != TypeFunction {
166+
panic(&ValueError{"Value.Call", vType})
167+
}
168+
if propType := v.Get(m).Type(); propType != TypeFunction {
169+
panic("js: Value.Call: property " + m + " is not a function, got " + propType.String())
170+
}
171+
return Value{v: v.v.Call(m, convertArgs(args)...)}
172+
}
173+
174+
func (v Value) Float() float64 {
175+
if vType := v.Type(); vType != TypeNumber {
176+
panic(&ValueError{"Value.Float", vType})
177+
}
178+
return v.v.Float()
179+
}
180+
181+
func (v Value) Get(p string) Value {
182+
return Value{v: v.v.Get(p)}
183+
}
184+
185+
func (v Value) Index(i int) Value {
186+
return Value{v: v.v.Index(i)}
187+
}
188+
189+
func (v Value) Int() int {
190+
if vType := v.Type(); vType != TypeNumber {
191+
panic(&ValueError{"Value.Int", vType})
192+
}
193+
return v.v.Int()
194+
}
195+
196+
func (v Value) InstanceOf(t Value) bool {
197+
return instanceOf.Invoke(v, t).Bool()
198+
}
199+
200+
func (v Value) Invoke(args ...interface{}) Value {
201+
if vType := v.Type(); vType != TypeFunction {
202+
panic(&ValueError{"Value.Invoke", vType})
203+
}
204+
return Value{v: v.v.Invoke(convertArgs(args)...)}
205+
}
206+
207+
func (v Value) JSValue() Value {
208+
return v
209+
}
210+
211+
func (v Value) Length() int {
212+
return v.v.Length()
213+
}
214+
215+
func (v Value) New(args ...interface{}) Value {
216+
return Value{v: v.v.New(convertArgs(args)...)}
217+
}
218+
219+
func (v Value) Set(p string, x interface{}) {
220+
v.v.Set(p, x)
221+
}
222+
223+
func (v Value) SetIndex(i int, x interface{}) {
224+
v.v.SetIndex(i, x)
225+
}
226+
227+
func (v Value) String() string {
228+
return v.v.String()
229+
}
230+
231+
func (v Value) Truthy() bool {
232+
return v.v.Bool()
233+
}
234+
235+
func (v Value) Type() Type {
236+
return Type(getValueType.Invoke(v).Int())
237+
}
238+
239+
type TypedArray struct {
240+
Value
241+
}
242+
243+
func TypedArrayOf(slice interface{}) TypedArray {
244+
switch slice := slice.(type) {
245+
case []int8, []int16, []int32, []uint8, []uint16, []uint32, []float32, []float64:
246+
return TypedArray{Value{v: id.Invoke(slice)}}
247+
default:
248+
panic("TypedArrayOf: not a supported slice")
249+
}
250+
}
251+
252+
func (t *TypedArray) Release() {
253+
t.Value = Null()
254+
}
255+
256+
type ValueError struct {
257+
Method string
258+
Type Type
259+
}
260+
261+
func (e *ValueError) Error() string {
262+
return "syscall/js: call of " + e.Method + " on " + e.Type.String()
263+
}
264+
265+
type Wrapper interface {
266+
JSValue() Value
267+
}

0 commit comments

Comments
 (0)