├── .gitignore ├── .travis.yml ├── AUTHORS ├── LICENSE ├── README.md ├── go.mod ├── go.sum └── js ├── callback.go ├── doc.go ├── func_test.go ├── go111_wasm.go ├── go112_wasm.go ├── js_notwasm.go ├── js_test.go ├── js_wasm.go └── testmain_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | # Use the original Go 1.11 instead of the Go 1.11 installed by gimme. 4 | # It looks like gimme Go causes some errors on go-test for Wasm. 5 | 6 | install: 7 | - unset GOROOT 8 | - wget -O go.tar.gz https://dl.google.com/go/go1.11.4.linux-amd64.tar.gz 9 | - mkdir ~/gocode 10 | - tar -C ~/gocode -xzf go.tar.gz 11 | - rm go.tar.gz 12 | - export PATH=~/gocode/go/bin:$PATH 13 | - go get golang.org/dl/go1.12beta2 14 | - go1.12beta2 download 15 | - nvm install node 16 | - nvm use node 17 | - mkdir /tmp/work 18 | - cd /tmp/work 19 | - go mod init example.com/m 20 | - go get github.com/gopherjs/gopherwasm@$TRAVIS_BRANCH 21 | - GO111MODULE=off go get github.com/gopherjs/gopherjs/... 22 | - GO111MODULE=off go get github.com/gopherjs/gopherwasm/... 23 | - cd $(go env GOPATH)/src/github.com/gopherjs/gopherwasm 24 | - git checkout $TRAVIS_BRANCH 25 | 26 | script: 27 | - cd /tmp/work 28 | - PATH=$(go env GOROOT)/misc/wasm:$PATH GOOS=js GOARCH=wasm go test github.com/gopherjs/gopherwasm/js/... -v 29 | - PATH=$(go1.12beta2 env GOROOT)/misc/wasm:$PATH GOOS=js GOARCH=wasm go1.12beta2 test github.com/gopherjs/gopherwasm/js/... -v 30 | - gopherjs test github.com/gopherjs/gopherwasm/js/... -v 31 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Hajime Hoshi 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 The GopherWasm Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This package is deprecated. Use `syscall/js` of GopherJS instead. 2 | 3 | For more details, see [GopherJS issue #899](https://github.com/gopherjs/gopherjs/issues/899) 4 | 5 | # GopherWasm 6 | 7 | [![Build Status](https://travis-ci.org/gopherjs/gopherwasm.svg?branch=master)](https://travis-ci.org/gopherjs/gopherwasm) 8 | [![GoDoc](https://godoc.org/github.com/gopherjs/gopherwasm/js?status.svg)](http://godoc.org/github.com/gopherjs/gopherwasm/js) 9 | 10 | A wrapper for GopherJS (`gopherjs/js`) and Wasm (`syscall/js`). With this, you can make your application work with both GopherJS and Wasm. 11 | 12 | GopherWasm's API emulates `syscall/js`, so please refer [`syscall/js` API document](https://golang.org/pkg/syscall/js/) to know how to use API of GopherWasm. 13 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gopherjs/gopherwasm 2 | 3 | require github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c 4 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c h1:16eHWuMGvCjSfgRJKqIzapE78onvvTbdi1rMkU00lZw= 2 | github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 3 | -------------------------------------------------------------------------------- /js/callback.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The GopherWasm 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 go1.12 !wasm 6 | 7 | package js 8 | 9 | // Callback is for backward compatibility. Use Func instead. 10 | type Callback = Func 11 | 12 | // EventCallbackFlag is for backward compatibility. 13 | type EventCallbackFlag int 14 | 15 | const ( 16 | PreventDefault EventCallbackFlag = 1 << iota 17 | StopPropagation 18 | StopImmediatePropagation 19 | ) 20 | 21 | // NewCallback is for backward compatibility. Use FuncOf instead. 22 | func NewCallback(fn func([]Value)) Callback { 23 | return FuncOf(func(this Value, args []Value) interface{} { 24 | go func() { 25 | fn(args) 26 | }() 27 | return nil 28 | }) 29 | } 30 | 31 | // NewEventCallback is for backward compatibility. Use FuncOf instead. 32 | func NewEventCallback(flags EventCallbackFlag, fn func(event Value)) Callback { 33 | return FuncOf(func(this Value, args []Value) interface{} { 34 | e := args[0] 35 | if flags&PreventDefault != 0 { 36 | e.Call("preventDefault") 37 | } 38 | if flags&StopPropagation != 0 { 39 | e.Call("stopPropagation") 40 | } 41 | if flags&StopImmediatePropagation != 0 { 42 | e.Call("stopImmediatePropagation") 43 | } 44 | go func() { 45 | fn(e) 46 | }() 47 | return nil 48 | }) 49 | } 50 | -------------------------------------------------------------------------------- /js/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The GopherWasm 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 | // Package js offers API that works with both GopherJS and Wasm. 6 | // 7 | // The API emulates syscall/js API, so please refer syscall/js API document (https://golang.org/pkg/syscall/js/) for more detail. 8 | package js 9 | -------------------------------------------------------------------------------- /js/func_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The GopherWasm 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 go1.12 !wasm 6 | 7 | package js_test 8 | 9 | import ( 10 | "testing" 11 | 12 | "github.com/gopherjs/gopherwasm/js" 13 | ) 14 | 15 | func TestFuncObject(t *testing.T) { 16 | got := "" 17 | f := js.FuncOf(func(this js.Value, args []js.Value) interface{} { 18 | got = args[0].Get("foo").String() + this.Get("name").String() 19 | return nil 20 | }) 21 | defer f.Release() 22 | 23 | obj := js.Global().Call("eval", `({})`) 24 | obj.Set("func", f) 25 | obj.Set("name", "baz") 26 | arg := js.Global().Call("eval", `({"foo": "bar"})`) 27 | obj.Call("func", arg) 28 | 29 | want := "barbaz" 30 | if got != want { 31 | t.Errorf("got %#v, want %#v", got, want) 32 | } 33 | } 34 | 35 | func TestValueOfFunc(t *testing.T) { 36 | f := js.FuncOf(func(this js.Value, args []js.Value) interface{} { return nil }) 37 | got := js.ValueOf(f).Type() 38 | want := js.TypeFunction 39 | if got != want { 40 | t.Fail() 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /js/go111_wasm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The GopherWasm 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 wasm 6 | // +build !go1.12 7 | 8 | package js 9 | 10 | import ( 11 | "syscall/js" 12 | ) 13 | 14 | type Callback = js.Callback 15 | 16 | type EventCallbackFlag = js.EventCallbackFlag 17 | 18 | const ( 19 | PreventDefault = js.PreventDefault 20 | StopPropagation = js.StopPropagation 21 | StopImmediatePropagation = js.StopImmediatePropagation 22 | ) 23 | 24 | func NewCallback(f func([]Value)) Callback { 25 | return js.NewCallback(f) 26 | } 27 | 28 | func NewEventCallback(flags EventCallbackFlag, fn func(event Value)) Callback { 29 | return js.NewEventCallback(flags, fn) 30 | } 31 | -------------------------------------------------------------------------------- /js/go112_wasm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The GopherWasm 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 wasm 6 | // +build go1.12 7 | 8 | package js 9 | 10 | import ( 11 | "syscall/js" 12 | ) 13 | 14 | type Func = js.Func 15 | 16 | func FuncOf(fn func(this Value, args []Value) interface{}) Func { 17 | return js.FuncOf(fn) 18 | } 19 | -------------------------------------------------------------------------------- /js/js_notwasm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The GopherWasm 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 !wasm 6 | 7 | package js 8 | 9 | import ( 10 | "reflect" 11 | "unsafe" 12 | 13 | "github.com/gopherjs/gopherjs/js" 14 | ) 15 | 16 | type Type int 17 | 18 | const ( 19 | TypeUndefined Type = iota 20 | TypeNull 21 | TypeBoolean 22 | TypeNumber 23 | TypeString 24 | TypeSymbol 25 | TypeObject 26 | TypeFunction 27 | ) 28 | 29 | func (t Type) String() string { 30 | switch t { 31 | case TypeUndefined: 32 | return "undefined" 33 | case TypeNull: 34 | return "null" 35 | case TypeBoolean: 36 | return "boolean" 37 | case TypeNumber: 38 | return "number" 39 | case TypeString: 40 | return "string" 41 | case TypeSymbol: 42 | return "symbol" 43 | case TypeObject: 44 | return "object" 45 | case TypeFunction: 46 | return "function" 47 | default: 48 | panic("bad type") 49 | } 50 | } 51 | 52 | func Global() Value { 53 | return Value{v: js.Global} 54 | } 55 | 56 | func Null() Value { 57 | return Value{v: nil} 58 | } 59 | 60 | func Undefined() Value { 61 | return Value{v: js.Undefined} 62 | } 63 | 64 | type Func struct { 65 | Value 66 | } 67 | 68 | func (f Func) Release() { 69 | f.Value = Null() 70 | } 71 | 72 | func FuncOf(fn func(this Value, args []Value) interface{}) Func { 73 | return Func{ 74 | Value: Value{ 75 | v: js.MakeFunc(func(this *js.Object, args []*js.Object) interface{} { 76 | vargs := make([]Value, len(args)) 77 | for i, a := range args { 78 | vargs[i] = Value{a} 79 | } 80 | return fn(Value{this}, vargs) 81 | }), 82 | }, 83 | } 84 | } 85 | 86 | type Error struct { 87 | Value 88 | } 89 | 90 | func (e Error) Error() string { 91 | return "JavaScript error: " + e.Get("message").String() 92 | } 93 | 94 | type Value struct { 95 | v *js.Object 96 | } 97 | 98 | var ( 99 | id *js.Object 100 | instanceOf *js.Object 101 | getValueType *js.Object 102 | ) 103 | 104 | func init() { 105 | if js.Global != nil { 106 | id = js.Global.Call("eval", "(function(x) { return x; })") 107 | instanceOf = js.Global.Call("eval", "(function(x, y) { return x instanceof y; })") 108 | getValueType = js.Global.Call("eval", `(function(x) { 109 | if (typeof(x) === "undefined") { 110 | return 0; // TypeUndefined 111 | } 112 | if (x === null) { 113 | return 1; // TypeNull 114 | } 115 | if (typeof(x) === "boolean") { 116 | return 2; // TypeBoolean 117 | } 118 | if (typeof(x) === "number") { 119 | return 3; // TypeNumber 120 | } 121 | if (typeof(x) === "string") { 122 | return 4; // TypeString 123 | } 124 | if (typeof(x) === "symbol") { 125 | return 5; // TypeSymbol 126 | } 127 | if (typeof(x) === "function") { 128 | return 7; // TypeFunction 129 | } 130 | return 6; // TypeObject 131 | })`) 132 | } 133 | } 134 | 135 | func ValueOf(x interface{}) Value { 136 | switch x := x.(type) { 137 | case Value: 138 | return x 139 | case Func: 140 | return x.Value 141 | case TypedArray: 142 | return x.Value 143 | case nil: 144 | return Null() 145 | case bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, unsafe.Pointer, string, map[string]interface{}, []interface{}: 146 | return Value{v: id.Invoke(x)} 147 | default: 148 | panic(`invalid arg: ` + reflect.TypeOf(x).String()) 149 | } 150 | } 151 | 152 | func (v Value) Bool() bool { 153 | if vType := v.Type(); vType != TypeBoolean { 154 | panic(&ValueError{"Value.Bool", vType}) 155 | } 156 | return v.v.Bool() 157 | } 158 | 159 | func convertArgs(args []interface{}) []interface{} { 160 | newArgs := []interface{}{} 161 | for _, arg := range args { 162 | v := ValueOf(arg) 163 | newArgs = append(newArgs, v.v) 164 | } 165 | return newArgs 166 | } 167 | 168 | func (v Value) Call(m string, args ...interface{}) Value { 169 | if vType := v.Type(); vType != TypeObject && vType != TypeFunction { 170 | panic(&ValueError{"Value.Call", vType}) 171 | } 172 | if propType := v.Get(m).Type(); propType != TypeFunction { 173 | panic("js: Value.Call: property " + m + " is not a function, got " + propType.String()) 174 | } 175 | return Value{v: v.v.Call(m, convertArgs(args)...)} 176 | } 177 | 178 | func (v Value) Float() float64 { 179 | if vType := v.Type(); vType != TypeNumber { 180 | panic(&ValueError{"Value.Float", vType}) 181 | } 182 | return v.v.Float() 183 | } 184 | 185 | func (v Value) Get(p string) Value { 186 | return Value{v: v.v.Get(p)} 187 | } 188 | 189 | func (v Value) Index(i int) Value { 190 | return Value{v: v.v.Index(i)} 191 | } 192 | 193 | func (v Value) Int() int { 194 | if vType := v.Type(); vType != TypeNumber { 195 | panic(&ValueError{"Value.Int", vType}) 196 | } 197 | return v.v.Int() 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) Length() int { 208 | return v.v.Length() 209 | } 210 | 211 | func (v Value) New(args ...interface{}) Value { 212 | return Value{v: v.v.New(convertArgs(args)...)} 213 | } 214 | 215 | func (v Value) Set(p string, x interface{}) { 216 | v.v.Set(p, x) 217 | } 218 | 219 | func (v Value) SetIndex(i int, x interface{}) { 220 | v.v.SetIndex(i, x) 221 | } 222 | 223 | func (v Value) String() string { 224 | return v.v.String() 225 | } 226 | 227 | func (v Value) InstanceOf(t Value) bool { 228 | return instanceOf.Invoke(v, t).Bool() 229 | } 230 | 231 | func (v Value) Type() Type { 232 | return Type(getValueType.Invoke(v).Int()) 233 | } 234 | 235 | type TypedArray struct { 236 | Value 237 | } 238 | 239 | func TypedArrayOf(slice interface{}) TypedArray { 240 | switch slice := slice.(type) { 241 | case []int8, []int16, []int32, []uint8, []uint16, []uint32, []float32, []float64: 242 | return TypedArray{Value{v: id.Invoke(slice)}} 243 | default: 244 | panic("TypedArrayOf: not a supported slice") 245 | } 246 | } 247 | 248 | func (t *TypedArray) Release() { 249 | t.Value = Null() 250 | } 251 | 252 | func GetInternalObject(v Value) interface{} { 253 | return v.v 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 | -------------------------------------------------------------------------------- /js/js_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The GopherWasm 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 | package js_test 6 | 7 | import ( 8 | "fmt" 9 | "math" 10 | "testing" 11 | 12 | "github.com/gopherjs/gopherwasm/js" 13 | ) 14 | 15 | func TestNull(t *testing.T) { 16 | want := "null" 17 | if got := js.Null().String(); got != want { 18 | t.Errorf("got %#v, want %#v", got, want) 19 | } 20 | } 21 | 22 | func TestCallback(t *testing.T) { 23 | ch := make(chan int) 24 | c := js.NewCallback(func(args []js.Value) { 25 | ch <- args[0].Int() + args[1].Int() 26 | }) 27 | defer c.Release() 28 | 29 | js.ValueOf(c).Invoke(1, 2) 30 | got := <-ch 31 | want := 3 32 | if got != want { 33 | t.Errorf("got %#v, want %#v", got, want) 34 | } 35 | } 36 | 37 | func TestCallbackObject(t *testing.T) { 38 | ch := make(chan string) 39 | c := js.NewCallback(func(args []js.Value) { 40 | ch <- args[0].Get("foo").String() 41 | }) 42 | defer c.Release() 43 | 44 | js.ValueOf(c).Invoke(js.Global().Call("eval", `({"foo": "bar"})`)) 45 | got := <-ch 46 | want := "bar" 47 | if got != want { 48 | t.Errorf("got %#v, want %#v", got, want) 49 | } 50 | } 51 | 52 | func TestString(t *testing.T) { 53 | obj := js.Global().Call("eval", "'Hello'") 54 | got := obj.String() 55 | if want := "Hello"; got != want { 56 | t.Errorf("got %#v, want %#v", got, want) 57 | } 58 | 59 | obj = js.Global().Call("eval", "123") 60 | got = obj.String() 61 | if want := "123"; got != want { 62 | t.Errorf("got %#v, want %#v", got, want) 63 | } 64 | } 65 | 66 | func TestInt64(t *testing.T) { 67 | var i int64 = math.MaxInt64 68 | got := js.ValueOf(i).String() 69 | // js.Value keeps the value only in 53-bit precision. 70 | if want := "9223372036854776000"; got != want { 71 | t.Errorf("got %#v, want %#v", got, want) 72 | } 73 | } 74 | 75 | func TestInstanceOf(t *testing.T) { 76 | arr := js.Global().Call("eval", "[]") 77 | got := arr.InstanceOf(js.Global().Call("eval", "Array")) 78 | want := true 79 | if got != want { 80 | t.Errorf("got %#v, want %#v", got, want) 81 | } 82 | 83 | got = arr.InstanceOf(js.Global().Call("eval", "Object")) 84 | want = true 85 | if got != want { 86 | t.Errorf("got %#v, want %#v", got, want) 87 | } 88 | 89 | got = arr.InstanceOf(js.Global().Call("eval", "String")) 90 | want = false 91 | if got != want { 92 | t.Errorf("got %#v, want %#v", got, want) 93 | } 94 | 95 | str := js.Global().Call("eval", "String").New() 96 | got = str.InstanceOf(js.Global().Call("eval", "Array")) 97 | want = false 98 | if got != want { 99 | t.Errorf("got %#v, want %#v", got, want) 100 | } 101 | 102 | got = str.InstanceOf(js.Global().Call("eval", "Object")) 103 | want = true 104 | if got != want { 105 | t.Errorf("got %#v, want %#v", got, want) 106 | } 107 | 108 | got = str.InstanceOf(js.Global().Call("eval", "String")) 109 | want = true 110 | if got != want { 111 | t.Errorf("got %#v, want %#v", got, want) 112 | } 113 | } 114 | 115 | func TestTypedArrayOf(t *testing.T) { 116 | testTypedArrayOf(t, "[]int8", []int8{0, -42, 0}, -42) 117 | testTypedArrayOf(t, "[]int16", []int16{0, -42, 0}, -42) 118 | testTypedArrayOf(t, "[]int32", []int32{0, -42, 0}, -42) 119 | testTypedArrayOf(t, "[]uint8", []uint8{0, 42, 0}, 42) 120 | testTypedArrayOf(t, "[]uint16", []uint16{0, 42, 0}, 42) 121 | testTypedArrayOf(t, "[]uint32", []uint32{0, 42, 0}, 42) 122 | testTypedArrayOf(t, "[]float32", []float32{0, -42.5, 0}, -42.5) 123 | testTypedArrayOf(t, "[]float64", []float64{0, -42.5, 0}, -42.5) 124 | } 125 | 126 | func testTypedArrayOf(t *testing.T, name string, slice interface{}, want float64) { 127 | t.Run(name, func(t *testing.T) { 128 | a := js.TypedArrayOf(slice) 129 | got := a.Index(1).Float() 130 | a.Release() 131 | if got != want { 132 | t.Errorf("got %#v, want %#v", got, want) 133 | } 134 | 135 | a2 := js.TypedArrayOf(slice) 136 | v := js.ValueOf(a2) 137 | got = v.Index(1).Float() 138 | a2.Release() 139 | if got != want { 140 | t.Errorf("got %#v, want %#v", got, want) 141 | } 142 | }) 143 | } 144 | 145 | func TestType(t *testing.T) { 146 | if got, want := js.Undefined().Type(), js.TypeUndefined; got != want { 147 | t.Errorf("got %s, want %s", got, want) 148 | } 149 | if got, want := js.Null().Type(), js.TypeNull; got != want { 150 | t.Errorf("got %s, want %s", got, want) 151 | } 152 | if got, want := js.ValueOf(true).Type(), js.TypeBoolean; got != want { 153 | t.Errorf("got %s, want %s", got, want) 154 | } 155 | if got, want := js.ValueOf(42).Type(), js.TypeNumber; got != want { 156 | t.Errorf("got %s, want %s", got, want) 157 | } 158 | if got, want := js.ValueOf("test").Type(), js.TypeString; got != want { 159 | t.Errorf("got %s, want %s", got, want) 160 | } 161 | if got, want := js.Global().Get("Symbol").Invoke("test").Type(), js.TypeSymbol; got != want { 162 | t.Errorf("got %s, want %s", got, want) 163 | } 164 | if got, want := js.Global().Get("Array").New().Type(), js.TypeObject; got != want { 165 | t.Errorf("got %s, want %s", got, want) 166 | } 167 | if got, want := js.Global().Get("Array").Type(), js.TypeFunction; got != want { 168 | t.Errorf("got %s, want %s", got, want) 169 | } 170 | } 171 | 172 | func TestValueOf(t *testing.T) { 173 | JSON := js.Global().Get("JSON") 174 | for _, test := range []struct { 175 | in interface{} 176 | wantType js.Type 177 | wantString string 178 | }{ 179 | {js.Value(js.ValueOf(42)), js.TypeNumber, "42"}, 180 | {js.NewCallback(func(args []js.Value) {}), js.TypeFunction, ""}, 181 | {js.TypedArrayOf([]int8{1, 2, 3}), js.TypeObject, `{"0":1,"1":2,"2":3}`}, 182 | {nil, js.TypeNull, "null"}, 183 | {bool(true), js.TypeBoolean, "true"}, 184 | {int(1), js.TypeNumber, "1"}, 185 | {int8(2), js.TypeNumber, "2"}, 186 | {int16(3), js.TypeNumber, "3"}, 187 | {int32(4), js.TypeNumber, "4"}, 188 | {int64(5), js.TypeNumber, "5"}, 189 | {uint(6), js.TypeNumber, "6"}, 190 | {uint8(7), js.TypeNumber, "7"}, 191 | {uint16(8), js.TypeNumber, "8"}, 192 | {uint32(9), js.TypeNumber, "9"}, 193 | {uint64(10), js.TypeNumber, "10"}, 194 | {float32(11), js.TypeNumber, "11"}, 195 | {float64(12), js.TypeNumber, "12"}, 196 | // FIXME this doesn't work {unsafe.Pointer(&x19), js.TypeNumber, ""}, 197 | {string("hello"), js.TypeString, `"hello"`}, 198 | {map[string]interface{}{"a": 1}, js.TypeObject, `{"a":1}`}, 199 | {[]interface{}{1, 2, 3}, js.TypeObject, "[1,2,3]"}, 200 | } { 201 | t.Run(fmt.Sprintf("%T", test.in), func(t *testing.T) { 202 | got := js.ValueOf(test.in) 203 | if got.Type() != test.wantType { 204 | t.Errorf("type: got %v want %v", got.Type(), test.wantType) 205 | } 206 | gotString := JSON.Call("stringify", got).String() 207 | if test.wantString != "" && gotString != test.wantString { 208 | t.Errorf("string: got %v want %v", gotString, test.wantString) 209 | } 210 | }) 211 | } 212 | 213 | // Check unknown types panic 214 | didPanic := false 215 | func() { 216 | defer func() { 217 | if r := recover(); r != nil { 218 | didPanic = true 219 | } 220 | }() 221 | _ = js.ValueOf([]struct{}{}) 222 | }() 223 | if !didPanic { 224 | t.Errorf("Unknown type didn't panic") 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /js/js_wasm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The GopherWasm 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 wasm 6 | 7 | package js 8 | 9 | import ( 10 | "syscall/js" 11 | ) 12 | 13 | type Type = js.Type 14 | 15 | const ( 16 | TypeUndefined = js.TypeUndefined 17 | TypeNull = js.TypeNull 18 | TypeBoolean = js.TypeBoolean 19 | TypeNumber = js.TypeNumber 20 | TypeString = js.TypeString 21 | TypeSymbol = js.TypeSymbol 22 | TypeObject = js.TypeObject 23 | TypeFunction = js.TypeFunction 24 | ) 25 | 26 | func Global() Value { 27 | return js.Global() 28 | } 29 | 30 | func Null() Value { 31 | return js.Null() 32 | } 33 | 34 | func Undefined() Value { 35 | return js.Undefined() 36 | } 37 | 38 | type Error = js.Error 39 | 40 | type Value = js.Value 41 | 42 | func ValueOf(x interface{}) Value { 43 | return js.ValueOf(x) 44 | } 45 | 46 | type TypedArray = js.TypedArray 47 | 48 | func TypedArrayOf(slice interface{}) TypedArray { 49 | return js.TypedArrayOf(slice) 50 | } 51 | 52 | func GetInternalObject(v Value) interface{} { 53 | return v 54 | } 55 | -------------------------------------------------------------------------------- /js/testmain_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The GopherWasm 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 !wasm 6 | 7 | package js_test 8 | 9 | import ( 10 | "testing" 11 | ) 12 | 13 | func TestMain(m *testing.M) { 14 | // Suppress the 'deadlock' error on GopherJS by goroutine 15 | // (https://github.com/gopherjs/gopherjs/issues/826). 16 | go func() { 17 | m.Run() 18 | }() 19 | } 20 | --------------------------------------------------------------------------------