blob: a5210faf7fd26cbd8497269334fbe78d6a4bcf34 [file] [log] [blame]
Dan Willemsenc7413322018-08-27 23:21:26 -07001// 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
Dan Willemsenbc60c3c2021-12-15 01:09:00 -08005//go:build js && wasm
Dan Willemsenc7413322018-08-27 23:21:26 -07006
7// Package js gives access to the WebAssembly host environment when using the js/wasm architecture.
8// Its API is based on JavaScript semantics.
9//
10// This package is EXPERIMENTAL. Its current scope is only to allow tests to run, but not yet to provide a
11// comprehensive API for users. It is exempt from the Go compatibility promise.
12package js
13
14import (
Patrice Arruda748609c2020-06-25 12:12:21 -070015 "runtime"
Dan Willemsenc7413322018-08-27 23:21:26 -070016 "unsafe"
17)
18
19// ref is used to identify a JavaScript value, since the value itself can not be passed to WebAssembly.
Colin Crossd9c6b802019-03-19 21:10:31 -070020//
21// The JavaScript value "undefined" is represented by the value 0.
22// A JavaScript number (64-bit float, except 0 and NaN) is represented by its IEEE 754 binary representation.
Dan Willemsenc7413322018-08-27 23:21:26 -070023// All other values are represented as an IEEE 754 binary representation of NaN with bits 0-31 used as
Patrice Arruda748609c2020-06-25 12:12:21 -070024// an ID and bits 32-34 used to differentiate between string, symbol, function and object.
Dan Willemsenc7413322018-08-27 23:21:26 -070025type ref uint64
26
Colin Crossd9c6b802019-03-19 21:10:31 -070027// 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).
Dan Willemsenc7413322018-08-27 23:21:26 -070028const nanHead = 0x7FF80000
29
Colin Crossd9c6b802019-03-19 21:10:31 -070030// Value represents a JavaScript value. The zero value is the JavaScript value "undefined".
Patrice Arruda748609c2020-06-25 12:12:21 -070031// Values can be checked for equality with the Equal method.
Dan Willemsenc7413322018-08-27 23:21:26 -070032type Value struct {
Patrice Arruda748609c2020-06-25 12:12:21 -070033 _ [0]func() // uncomparable; to make == not compile
34 ref ref // identifies a JavaScript value, see ref type
35 gcPtr *ref // used to trigger the finalizer when the Value is not referenced any more
Dan Willemsenc7413322018-08-27 23:21:26 -070036}
37
Patrice Arruda748609c2020-06-25 12:12:21 -070038const (
39 // the type flags need to be in sync with wasm_exec.js
40 typeFlagNone = iota
41 typeFlagObject
42 typeFlagString
43 typeFlagSymbol
44 typeFlagFunction
45)
46
Patrice Arruda748609c2020-06-25 12:12:21 -070047func makeValue(r ref) Value {
48 var gcPtr *ref
49 typeFlag := (r >> 32) & 7
50 if (r>>32)&nanHead == nanHead && typeFlag != typeFlagNone {
51 gcPtr = new(ref)
52 *gcPtr = r
53 runtime.SetFinalizer(gcPtr, func(p *ref) {
54 finalizeRef(*p)
55 })
56 }
57
58 return Value{ref: r, gcPtr: gcPtr}
Dan Willemsenc7413322018-08-27 23:21:26 -070059}
60
Patrice Arruda748609c2020-06-25 12:12:21 -070061func finalizeRef(r ref)
62
63func predefValue(id uint32, typeFlag byte) Value {
64 return Value{ref: (nanHead|ref(typeFlag))<<32 | ref(id)}
Dan Willemsenc7413322018-08-27 23:21:26 -070065}
66
67func floatValue(f float64) Value {
Colin Crossd9c6b802019-03-19 21:10:31 -070068 if f == 0 {
69 return valueZero
70 }
Dan Willemsenc7413322018-08-27 23:21:26 -070071 if f != f {
72 return valueNaN
73 }
74 return Value{ref: *(*ref)(unsafe.Pointer(&f))}
75}
76
77// Error wraps a JavaScript error.
78type Error struct {
79 // Value is the underlying JavaScript error value.
80 Value
81}
82
83// Error implements the error interface.
84func (e Error) Error() string {
85 return "JavaScript error: " + e.Get("message").String()
86}
87
88var (
Colin Crossd9c6b802019-03-19 21:10:31 -070089 valueUndefined = Value{ref: 0}
Patrice Arruda748609c2020-06-25 12:12:21 -070090 valueNaN = predefValue(0, typeFlagNone)
91 valueZero = predefValue(1, typeFlagNone)
92 valueNull = predefValue(2, typeFlagNone)
93 valueTrue = predefValue(3, typeFlagNone)
94 valueFalse = predefValue(4, typeFlagNone)
95 valueGlobal = predefValue(5, typeFlagObject)
96 jsGo = predefValue(6, typeFlagObject) // instance of the Go class in JavaScript
Dan Willemsenc7413322018-08-27 23:21:26 -070097
98 objectConstructor = valueGlobal.Get("Object")
99 arrayConstructor = valueGlobal.Get("Array")
100)
101
Patrice Arruda748609c2020-06-25 12:12:21 -0700102// Equal reports whether v and w are equal according to JavaScript's === operator.
103func (v Value) Equal(w Value) bool {
104 return v.ref == w.ref && v.ref != valueNaN.ref
105}
106
Dan Willemsenc7413322018-08-27 23:21:26 -0700107// Undefined returns the JavaScript value "undefined".
108func Undefined() Value {
109 return valueUndefined
110}
111
Patrice Arruda748609c2020-06-25 12:12:21 -0700112// IsUndefined reports whether v is the JavaScript value "undefined".
113func (v Value) IsUndefined() bool {
114 return v.ref == valueUndefined.ref
115}
116
Dan Willemsenc7413322018-08-27 23:21:26 -0700117// Null returns the JavaScript value "null".
118func Null() Value {
119 return valueNull
120}
121
Patrice Arruda748609c2020-06-25 12:12:21 -0700122// IsNull reports whether v is the JavaScript value "null".
123func (v Value) IsNull() bool {
124 return v.ref == valueNull.ref
125}
126
127// IsNaN reports whether v is the JavaScript value "NaN".
128func (v Value) IsNaN() bool {
129 return v.ref == valueNaN.ref
130}
131
Dan Willemsenc7413322018-08-27 23:21:26 -0700132// Global returns the JavaScript global object, usually "window" or "global".
133func Global() Value {
134 return valueGlobal
135}
136
137// ValueOf returns x as a JavaScript value:
138//
139// | Go | JavaScript |
140// | ---------------------- | ---------------------- |
141// | js.Value | [its value] |
Colin Crossd9c6b802019-03-19 21:10:31 -0700142// | js.Func | function |
Dan Willemsenc7413322018-08-27 23:21:26 -0700143// | nil | null |
144// | bool | boolean |
145// | integers and floats | number |
146// | string | string |
147// | []interface{} | new array |
148// | map[string]interface{} | new object |
Colin Crossd9c6b802019-03-19 21:10:31 -0700149//
150// Panics if x is not one of the expected types.
Dan Willemsenbc60c3c2021-12-15 01:09:00 -0800151func ValueOf(x any) Value {
Dan Willemsenc7413322018-08-27 23:21:26 -0700152 switch x := x.(type) {
Dan Willemsenbc60c3c2021-12-15 01:09:00 -0800153 case Value:
Dan Willemsenc7413322018-08-27 23:21:26 -0700154 return x
Dan Willemsenbc60c3c2021-12-15 01:09:00 -0800155 case Func:
156 return x.Value
Dan Willemsenc7413322018-08-27 23:21:26 -0700157 case nil:
158 return valueNull
159 case bool:
160 if x {
161 return valueTrue
162 } else {
163 return valueFalse
164 }
165 case int:
166 return floatValue(float64(x))
167 case int8:
168 return floatValue(float64(x))
169 case int16:
170 return floatValue(float64(x))
171 case int32:
172 return floatValue(float64(x))
173 case int64:
174 return floatValue(float64(x))
175 case uint:
176 return floatValue(float64(x))
177 case uint8:
178 return floatValue(float64(x))
179 case uint16:
180 return floatValue(float64(x))
181 case uint32:
182 return floatValue(float64(x))
183 case uint64:
184 return floatValue(float64(x))
185 case uintptr:
186 return floatValue(float64(x))
187 case unsafe.Pointer:
188 return floatValue(float64(uintptr(x)))
189 case float32:
190 return floatValue(float64(x))
191 case float64:
192 return floatValue(x)
193 case string:
194 return makeValue(stringVal(x))
Dan Willemsenbc60c3c2021-12-15 01:09:00 -0800195 case []any:
Dan Willemsenc7413322018-08-27 23:21:26 -0700196 a := arrayConstructor.New(len(x))
197 for i, s := range x {
198 a.SetIndex(i, s)
199 }
200 return a
Dan Willemsenbc60c3c2021-12-15 01:09:00 -0800201 case map[string]any:
Dan Willemsenc7413322018-08-27 23:21:26 -0700202 o := objectConstructor.New()
203 for k, v := range x {
204 o.Set(k, v)
205 }
206 return o
207 default:
208 panic("ValueOf: invalid value")
209 }
210}
211
212func stringVal(x string) ref
213
214// Type represents the JavaScript type of a Value.
215type Type int
216
217const (
218 TypeUndefined Type = iota
219 TypeNull
220 TypeBoolean
221 TypeNumber
222 TypeString
223 TypeSymbol
224 TypeObject
225 TypeFunction
226)
227
228func (t Type) String() string {
229 switch t {
230 case TypeUndefined:
231 return "undefined"
232 case TypeNull:
233 return "null"
234 case TypeBoolean:
235 return "boolean"
236 case TypeNumber:
237 return "number"
238 case TypeString:
239 return "string"
240 case TypeSymbol:
241 return "symbol"
242 case TypeObject:
243 return "object"
244 case TypeFunction:
245 return "function"
246 default:
247 panic("bad type")
248 }
249}
250
Colin Cross430342c2019-09-07 08:36:04 -0700251func (t Type) isObject() bool {
252 return t == TypeObject || t == TypeFunction
253}
254
Dan Willemsenc7413322018-08-27 23:21:26 -0700255// Type returns the JavaScript type of the value v. It is similar to JavaScript's typeof operator,
256// except that it returns TypeNull instead of TypeObject for null.
257func (v Value) Type() Type {
258 switch v.ref {
259 case valueUndefined.ref:
260 return TypeUndefined
261 case valueNull.ref:
262 return TypeNull
263 case valueTrue.ref, valueFalse.ref:
264 return TypeBoolean
265 }
266 if v.isNumber() {
267 return TypeNumber
268 }
Patrice Arruda748609c2020-06-25 12:12:21 -0700269 typeFlag := (v.ref >> 32) & 7
Dan Willemsenc7413322018-08-27 23:21:26 -0700270 switch typeFlag {
Patrice Arruda748609c2020-06-25 12:12:21 -0700271 case typeFlagObject:
272 return TypeObject
273 case typeFlagString:
Dan Willemsenc7413322018-08-27 23:21:26 -0700274 return TypeString
Patrice Arruda748609c2020-06-25 12:12:21 -0700275 case typeFlagSymbol:
Dan Willemsenc7413322018-08-27 23:21:26 -0700276 return TypeSymbol
Patrice Arruda748609c2020-06-25 12:12:21 -0700277 case typeFlagFunction:
Dan Willemsenc7413322018-08-27 23:21:26 -0700278 return TypeFunction
279 default:
Patrice Arruda748609c2020-06-25 12:12:21 -0700280 panic("bad type flag")
Dan Willemsenc7413322018-08-27 23:21:26 -0700281 }
282}
283
284// Get returns the JavaScript property p of value v.
Colin Cross430342c2019-09-07 08:36:04 -0700285// It panics if v is not a JavaScript object.
Dan Willemsenc7413322018-08-27 23:21:26 -0700286func (v Value) Get(p string) Value {
Colin Cross430342c2019-09-07 08:36:04 -0700287 if vType := v.Type(); !vType.isObject() {
288 panic(&ValueError{"Value.Get", vType})
289 }
Patrice Arruda748609c2020-06-25 12:12:21 -0700290 r := makeValue(valueGet(v.ref, p))
291 runtime.KeepAlive(v)
292 return r
Dan Willemsenc7413322018-08-27 23:21:26 -0700293}
294
295func valueGet(v ref, p string) ref
296
297// Set sets the JavaScript property p of value v to ValueOf(x).
Colin Cross430342c2019-09-07 08:36:04 -0700298// It panics if v is not a JavaScript object.
Dan Willemsenbc60c3c2021-12-15 01:09:00 -0800299func (v Value) Set(p string, x any) {
Colin Cross430342c2019-09-07 08:36:04 -0700300 if vType := v.Type(); !vType.isObject() {
301 panic(&ValueError{"Value.Set", vType})
302 }
Patrice Arruda748609c2020-06-25 12:12:21 -0700303 xv := ValueOf(x)
304 valueSet(v.ref, p, xv.ref)
305 runtime.KeepAlive(v)
306 runtime.KeepAlive(xv)
Dan Willemsenc7413322018-08-27 23:21:26 -0700307}
308
309func valueSet(v ref, p string, x ref)
310
Patrice Arruda748609c2020-06-25 12:12:21 -0700311// Delete deletes the JavaScript property p of value v.
312// It panics if v is not a JavaScript object.
313func (v Value) Delete(p string) {
314 if vType := v.Type(); !vType.isObject() {
315 panic(&ValueError{"Value.Delete", vType})
316 }
317 valueDelete(v.ref, p)
318 runtime.KeepAlive(v)
319}
320
321func valueDelete(v ref, p string)
322
Dan Willemsenc7413322018-08-27 23:21:26 -0700323// Index returns JavaScript index i of value v.
Colin Cross430342c2019-09-07 08:36:04 -0700324// It panics if v is not a JavaScript object.
Dan Willemsenc7413322018-08-27 23:21:26 -0700325func (v Value) Index(i int) Value {
Colin Cross430342c2019-09-07 08:36:04 -0700326 if vType := v.Type(); !vType.isObject() {
327 panic(&ValueError{"Value.Index", vType})
328 }
Patrice Arruda748609c2020-06-25 12:12:21 -0700329 r := makeValue(valueIndex(v.ref, i))
330 runtime.KeepAlive(v)
331 return r
Dan Willemsenc7413322018-08-27 23:21:26 -0700332}
333
334func valueIndex(v ref, i int) ref
335
336// SetIndex sets the JavaScript index i of value v to ValueOf(x).
Colin Cross430342c2019-09-07 08:36:04 -0700337// It panics if v is not a JavaScript object.
Dan Willemsenbc60c3c2021-12-15 01:09:00 -0800338func (v Value) SetIndex(i int, x any) {
Colin Cross430342c2019-09-07 08:36:04 -0700339 if vType := v.Type(); !vType.isObject() {
340 panic(&ValueError{"Value.SetIndex", vType})
341 }
Patrice Arruda748609c2020-06-25 12:12:21 -0700342 xv := ValueOf(x)
343 valueSetIndex(v.ref, i, xv.ref)
344 runtime.KeepAlive(v)
345 runtime.KeepAlive(xv)
Dan Willemsenc7413322018-08-27 23:21:26 -0700346}
347
348func valueSetIndex(v ref, i int, x ref)
349
Dan Willemsenbc60c3c2021-12-15 01:09:00 -0800350func makeArgs(args []any) ([]Value, []ref) {
Patrice Arruda748609c2020-06-25 12:12:21 -0700351 argVals := make([]Value, len(args))
352 argRefs := make([]ref, len(args))
Dan Willemsenc7413322018-08-27 23:21:26 -0700353 for i, arg := range args {
Patrice Arruda748609c2020-06-25 12:12:21 -0700354 v := ValueOf(arg)
355 argVals[i] = v
356 argRefs[i] = v.ref
Dan Willemsenc7413322018-08-27 23:21:26 -0700357 }
Patrice Arruda748609c2020-06-25 12:12:21 -0700358 return argVals, argRefs
Dan Willemsenc7413322018-08-27 23:21:26 -0700359}
360
361// Length returns the JavaScript property "length" of v.
Colin Cross430342c2019-09-07 08:36:04 -0700362// It panics if v is not a JavaScript object.
Dan Willemsenc7413322018-08-27 23:21:26 -0700363func (v Value) Length() int {
Colin Cross430342c2019-09-07 08:36:04 -0700364 if vType := v.Type(); !vType.isObject() {
365 panic(&ValueError{"Value.SetIndex", vType})
366 }
Patrice Arruda748609c2020-06-25 12:12:21 -0700367 r := valueLength(v.ref)
368 runtime.KeepAlive(v)
369 return r
Dan Willemsenc7413322018-08-27 23:21:26 -0700370}
371
372func valueLength(v ref) int
373
374// Call does a JavaScript call to the method m of value v with the given arguments.
375// It panics if v has no method m.
376// The arguments get mapped to JavaScript values according to the ValueOf function.
Dan Willemsenbc60c3c2021-12-15 01:09:00 -0800377func (v Value) Call(m string, args ...any) Value {
Patrice Arruda748609c2020-06-25 12:12:21 -0700378 argVals, argRefs := makeArgs(args)
379 res, ok := valueCall(v.ref, m, argRefs)
380 runtime.KeepAlive(v)
381 runtime.KeepAlive(argVals)
Dan Willemsenc7413322018-08-27 23:21:26 -0700382 if !ok {
Colin Cross430342c2019-09-07 08:36:04 -0700383 if vType := v.Type(); !vType.isObject() { // check here to avoid overhead in success case
Dan Willemsenc7413322018-08-27 23:21:26 -0700384 panic(&ValueError{"Value.Call", vType})
385 }
386 if propType := v.Get(m).Type(); propType != TypeFunction {
387 panic("syscall/js: Value.Call: property " + m + " is not a function, got " + propType.String())
388 }
389 panic(Error{makeValue(res)})
390 }
391 return makeValue(res)
392}
393
394func valueCall(v ref, m string, args []ref) (ref, bool)
395
396// Invoke does a JavaScript call of the value v with the given arguments.
Colin Cross430342c2019-09-07 08:36:04 -0700397// It panics if v is not a JavaScript function.
Dan Willemsenc7413322018-08-27 23:21:26 -0700398// The arguments get mapped to JavaScript values according to the ValueOf function.
Dan Willemsenbc60c3c2021-12-15 01:09:00 -0800399func (v Value) Invoke(args ...any) Value {
Patrice Arruda748609c2020-06-25 12:12:21 -0700400 argVals, argRefs := makeArgs(args)
401 res, ok := valueInvoke(v.ref, argRefs)
402 runtime.KeepAlive(v)
403 runtime.KeepAlive(argVals)
Dan Willemsenc7413322018-08-27 23:21:26 -0700404 if !ok {
405 if vType := v.Type(); vType != TypeFunction { // check here to avoid overhead in success case
406 panic(&ValueError{"Value.Invoke", vType})
407 }
408 panic(Error{makeValue(res)})
409 }
410 return makeValue(res)
411}
412
413func valueInvoke(v ref, args []ref) (ref, bool)
414
415// New uses JavaScript's "new" operator with value v as constructor and the given arguments.
Colin Cross430342c2019-09-07 08:36:04 -0700416// It panics if v is not a JavaScript function.
Dan Willemsenc7413322018-08-27 23:21:26 -0700417// The arguments get mapped to JavaScript values according to the ValueOf function.
Dan Willemsenbc60c3c2021-12-15 01:09:00 -0800418func (v Value) New(args ...any) Value {
Patrice Arruda748609c2020-06-25 12:12:21 -0700419 argVals, argRefs := makeArgs(args)
420 res, ok := valueNew(v.ref, argRefs)
421 runtime.KeepAlive(v)
422 runtime.KeepAlive(argVals)
Dan Willemsenc7413322018-08-27 23:21:26 -0700423 if !ok {
Colin Cross430342c2019-09-07 08:36:04 -0700424 if vType := v.Type(); vType != TypeFunction { // check here to avoid overhead in success case
425 panic(&ValueError{"Value.Invoke", vType})
426 }
Dan Willemsenc7413322018-08-27 23:21:26 -0700427 panic(Error{makeValue(res)})
428 }
429 return makeValue(res)
430}
431
432func valueNew(v ref, args []ref) (ref, bool)
433
434func (v Value) isNumber() bool {
Colin Crossd9c6b802019-03-19 21:10:31 -0700435 return v.ref == valueZero.ref ||
436 v.ref == valueNaN.ref ||
Patrice Arruda748609c2020-06-25 12:12:21 -0700437 (v.ref != valueUndefined.ref && (v.ref>>32)&nanHead != nanHead)
Dan Willemsenc7413322018-08-27 23:21:26 -0700438}
439
440func (v Value) float(method string) float64 {
441 if !v.isNumber() {
442 panic(&ValueError{method, v.Type()})
443 }
Colin Crossd9c6b802019-03-19 21:10:31 -0700444 if v.ref == valueZero.ref {
445 return 0
446 }
Dan Willemsenc7413322018-08-27 23:21:26 -0700447 return *(*float64)(unsafe.Pointer(&v.ref))
448}
449
Colin Cross430342c2019-09-07 08:36:04 -0700450// Float returns the value v as a float64.
451// It panics if v is not a JavaScript number.
Dan Willemsenc7413322018-08-27 23:21:26 -0700452func (v Value) Float() float64 {
453 return v.float("Value.Float")
454}
455
Colin Cross430342c2019-09-07 08:36:04 -0700456// Int returns the value v truncated to an int.
457// It panics if v is not a JavaScript number.
Dan Willemsenc7413322018-08-27 23:21:26 -0700458func (v Value) Int() int {
459 return int(v.float("Value.Int"))
460}
461
Colin Cross430342c2019-09-07 08:36:04 -0700462// Bool returns the value v as a bool.
463// It panics if v is not a JavaScript boolean.
Dan Willemsenc7413322018-08-27 23:21:26 -0700464func (v Value) Bool() bool {
465 switch v.ref {
466 case valueTrue.ref:
467 return true
468 case valueFalse.ref:
469 return false
470 default:
471 panic(&ValueError{"Value.Bool", v.Type()})
472 }
473}
474
Colin Crossd9c6b802019-03-19 21:10:31 -0700475// Truthy returns the JavaScript "truthiness" of the value v. In JavaScript,
476// false, 0, "", null, undefined, and NaN are "falsy", and everything else is
477// "truthy". See https://developer.mozilla.org/en-US/docs/Glossary/Truthy.
478func (v Value) Truthy() bool {
479 switch v.Type() {
480 case TypeUndefined, TypeNull:
481 return false
482 case TypeBoolean:
483 return v.Bool()
484 case TypeNumber:
485 return v.ref != valueNaN.ref && v.ref != valueZero.ref
486 case TypeString:
487 return v.String() != ""
488 case TypeSymbol, TypeFunction, TypeObject:
489 return true
490 default:
491 panic("bad type")
492 }
493}
494
Colin Cross430342c2019-09-07 08:36:04 -0700495// String returns the value v as a string.
496// String is a special case because of Go's String method convention. Unlike the other getters,
497// it does not panic if v's Type is not TypeString. Instead, it returns a string of the form "<T>"
498// or "<T: V>" where T is v's type and V is a string representation of v's value.
Dan Willemsenc7413322018-08-27 23:21:26 -0700499func (v Value) String() string {
Colin Cross430342c2019-09-07 08:36:04 -0700500 switch v.Type() {
501 case TypeString:
Patrice Arruda748609c2020-06-25 12:12:21 -0700502 return jsString(v)
Colin Cross430342c2019-09-07 08:36:04 -0700503 case TypeUndefined:
504 return "<undefined>"
505 case TypeNull:
506 return "<null>"
507 case TypeBoolean:
Patrice Arruda748609c2020-06-25 12:12:21 -0700508 return "<boolean: " + jsString(v) + ">"
Colin Cross430342c2019-09-07 08:36:04 -0700509 case TypeNumber:
Patrice Arruda748609c2020-06-25 12:12:21 -0700510 return "<number: " + jsString(v) + ">"
Colin Cross430342c2019-09-07 08:36:04 -0700511 case TypeSymbol:
512 return "<symbol>"
513 case TypeObject:
514 return "<object>"
515 case TypeFunction:
516 return "<function>"
517 default:
518 panic("bad type")
519 }
520}
521
Patrice Arruda748609c2020-06-25 12:12:21 -0700522func jsString(v Value) string {
523 str, length := valuePrepareString(v.ref)
524 runtime.KeepAlive(v)
Dan Willemsenc7413322018-08-27 23:21:26 -0700525 b := make([]byte, length)
526 valueLoadString(str, b)
Patrice Arruda748609c2020-06-25 12:12:21 -0700527 finalizeRef(str)
Dan Willemsenc7413322018-08-27 23:21:26 -0700528 return string(b)
529}
530
531func valuePrepareString(v ref) (ref, int)
532
533func valueLoadString(v ref, b []byte)
534
535// InstanceOf reports whether v is an instance of type t according to JavaScript's instanceof operator.
536func (v Value) InstanceOf(t Value) bool {
Patrice Arruda748609c2020-06-25 12:12:21 -0700537 r := valueInstanceOf(v.ref, t.ref)
538 runtime.KeepAlive(v)
539 runtime.KeepAlive(t)
540 return r
Dan Willemsenc7413322018-08-27 23:21:26 -0700541}
542
543func valueInstanceOf(v ref, t ref) bool
544
545// A ValueError occurs when a Value method is invoked on
546// a Value that does not support it. Such cases are documented
547// in the description of each method.
548type ValueError struct {
549 Method string
550 Type Type
551}
552
553func (e *ValueError) Error() string {
554 return "syscall/js: call of " + e.Method + " on " + e.Type.String()
555}
Colin Cross430342c2019-09-07 08:36:04 -0700556
Patrice Arruda748609c2020-06-25 12:12:21 -0700557// CopyBytesToGo copies bytes from src to dst.
558// It panics if src is not an Uint8Array or Uint8ClampedArray.
Colin Cross430342c2019-09-07 08:36:04 -0700559// It returns the number of bytes copied, which will be the minimum of the lengths of src and dst.
Colin Cross430342c2019-09-07 08:36:04 -0700560func CopyBytesToGo(dst []byte, src Value) int {
561 n, ok := copyBytesToGo(dst, src.ref)
Patrice Arruda748609c2020-06-25 12:12:21 -0700562 runtime.KeepAlive(src)
Colin Cross430342c2019-09-07 08:36:04 -0700563 if !ok {
Patrice Arruda748609c2020-06-25 12:12:21 -0700564 panic("syscall/js: CopyBytesToGo: expected src to be an Uint8Array or Uint8ClampedArray")
Colin Cross430342c2019-09-07 08:36:04 -0700565 }
566 return n
567}
568
569func copyBytesToGo(dst []byte, src ref) (int, bool)
570
Patrice Arruda748609c2020-06-25 12:12:21 -0700571// CopyBytesToJS copies bytes from src to dst.
572// It panics if dst is not an Uint8Array or Uint8ClampedArray.
Colin Cross430342c2019-09-07 08:36:04 -0700573// It returns the number of bytes copied, which will be the minimum of the lengths of src and dst.
Colin Cross430342c2019-09-07 08:36:04 -0700574func CopyBytesToJS(dst Value, src []byte) int {
575 n, ok := copyBytesToJS(dst.ref, src)
Patrice Arruda748609c2020-06-25 12:12:21 -0700576 runtime.KeepAlive(dst)
Colin Cross430342c2019-09-07 08:36:04 -0700577 if !ok {
Patrice Arruda748609c2020-06-25 12:12:21 -0700578 panic("syscall/js: CopyBytesToJS: expected dst to be an Uint8Array or Uint8ClampedArray")
Colin Cross430342c2019-09-07 08:36:04 -0700579 }
580 return n
581}
582
583func copyBytesToJS(dst ref, src []byte) (int, bool)