Source file src/syscall/js/js.go

     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  //go:build js && wasm
     6  
     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.
    12  package js
    13  
    14  import (
    15  	"runtime"
    16  	"unsafe"
    17  )
    18  
    19  // ref is used to identify a JavaScript value, since the value itself can not be passed to WebAssembly.
    20  //
    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.
    23  // All other values are represented as an IEEE 754 binary representation of NaN with bits 0-31 used as
    24  // an ID and bits 32-34 used to differentiate between string, symbol, function and object.
    25  type ref uint64
    26  
    27  // 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).
    28  const nanHead = 0x7FF80000
    29  
    30  // Value represents a JavaScript value. The zero value is the JavaScript value "undefined".
    31  // Values can be checked for equality with the Equal method.
    32  type Value struct {
    33  	_     [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
    36  }
    37  
    38  const (
    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  
    47  func 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}
    59  }
    60  
    61  //go:wasmimport gojs syscall/js.finalizeRef
    62  func finalizeRef(r ref)
    63  
    64  func predefValue(id uint32, typeFlag byte) Value {
    65  	return Value{ref: (nanHead|ref(typeFlag))<<32 | ref(id)}
    66  }
    67  
    68  func floatValue(f float64) Value {
    69  	if f == 0 {
    70  		return valueZero
    71  	}
    72  	if f != f {
    73  		return valueNaN
    74  	}
    75  	return Value{ref: *(*ref)(unsafe.Pointer(&f))}
    76  }
    77  
    78  // Error wraps a JavaScript error.
    79  type Error struct {
    80  	// Value is the underlying JavaScript error value.
    81  	Value
    82  }
    83  
    84  // Error implements the error interface.
    85  func (e Error) Error() string {
    86  	return "JavaScript error: " + e.Get("message").String()
    87  }
    88  
    89  var (
    90  	valueUndefined = Value{ref: 0}
    91  	valueNaN       = predefValue(0, typeFlagNone)
    92  	valueZero      = predefValue(1, typeFlagNone)
    93  	valueNull      = predefValue(2, typeFlagNone)
    94  	valueTrue      = predefValue(3, typeFlagNone)
    95  	valueFalse     = predefValue(4, typeFlagNone)
    96  	valueGlobal    = predefValue(5, typeFlagObject)
    97  	jsGo           = predefValue(6, typeFlagObject) // instance of the Go class in JavaScript
    98  
    99  	objectConstructor = valueGlobal.Get("Object")
   100  	arrayConstructor  = valueGlobal.Get("Array")
   101  )
   102  
   103  // Equal reports whether v and w are equal according to JavaScript's === operator.
   104  func (v Value) Equal(w Value) bool {
   105  	return v.ref == w.ref && v.ref != valueNaN.ref
   106  }
   107  
   108  // Undefined returns the JavaScript value "undefined".
   109  func Undefined() Value {
   110  	return valueUndefined
   111  }
   112  
   113  // IsUndefined reports whether v is the JavaScript value "undefined".
   114  func (v Value) IsUndefined() bool {
   115  	return v.ref == valueUndefined.ref
   116  }
   117  
   118  // Null returns the JavaScript value "null".
   119  func Null() Value {
   120  	return valueNull
   121  }
   122  
   123  // IsNull reports whether v is the JavaScript value "null".
   124  func (v Value) IsNull() bool {
   125  	return v.ref == valueNull.ref
   126  }
   127  
   128  // IsNaN reports whether v is the JavaScript value "NaN".
   129  func (v Value) IsNaN() bool {
   130  	return v.ref == valueNaN.ref
   131  }
   132  
   133  // Global returns the JavaScript global object, usually "window" or "global".
   134  func Global() Value {
   135  	return valueGlobal
   136  }
   137  
   138  // ValueOf returns x as a JavaScript value:
   139  //
   140  //	| Go                     | JavaScript             |
   141  //	| ---------------------- | ---------------------- |
   142  //	| js.Value               | [its value]            |
   143  //	| js.Func                | function               |
   144  //	| nil                    | null                   |
   145  //	| bool                   | boolean                |
   146  //	| integers and floats    | number                 |
   147  //	| string                 | string                 |
   148  //	| []interface{}          | new array              |
   149  //	| map[string]interface{} | new object             |
   150  //
   151  // Panics if x is not one of the expected types.
   152  func ValueOf(x any) Value {
   153  	switch x := x.(type) {
   154  	case Value:
   155  		return x
   156  	case Func:
   157  		return x.Value
   158  	case nil:
   159  		return valueNull
   160  	case bool:
   161  		if x {
   162  			return valueTrue
   163  		} else {
   164  			return valueFalse
   165  		}
   166  	case int:
   167  		return floatValue(float64(x))
   168  	case int8:
   169  		return floatValue(float64(x))
   170  	case int16:
   171  		return floatValue(float64(x))
   172  	case int32:
   173  		return floatValue(float64(x))
   174  	case int64:
   175  		return floatValue(float64(x))
   176  	case uint:
   177  		return floatValue(float64(x))
   178  	case uint8:
   179  		return floatValue(float64(x))
   180  	case uint16:
   181  		return floatValue(float64(x))
   182  	case uint32:
   183  		return floatValue(float64(x))
   184  	case uint64:
   185  		return floatValue(float64(x))
   186  	case uintptr:
   187  		return floatValue(float64(x))
   188  	case unsafe.Pointer:
   189  		return floatValue(float64(uintptr(x)))
   190  	case float32:
   191  		return floatValue(float64(x))
   192  	case float64:
   193  		return floatValue(x)
   194  	case string:
   195  		return makeValue(stringVal(x))
   196  	case []any:
   197  		a := arrayConstructor.New(len(x))
   198  		for i, s := range x {
   199  			a.SetIndex(i, s)
   200  		}
   201  		return a
   202  	case map[string]any:
   203  		o := objectConstructor.New()
   204  		for k, v := range x {
   205  			o.Set(k, v)
   206  		}
   207  		return o
   208  	default:
   209  		panic("ValueOf: invalid value")
   210  	}
   211  }
   212  
   213  // stringVal copies string x to Javascript and returns a ref.
   214  //
   215  // (noescape): This is safe because no references are maintained to the
   216  //             Go string x after the syscall returns.
   217  //
   218  //go:wasmimport gojs syscall/js.stringVal
   219  //go:noescape
   220  func stringVal(x string) ref
   221  
   222  // Type represents the JavaScript type of a Value.
   223  type Type int
   224  
   225  const (
   226  	TypeUndefined Type = iota
   227  	TypeNull
   228  	TypeBoolean
   229  	TypeNumber
   230  	TypeString
   231  	TypeSymbol
   232  	TypeObject
   233  	TypeFunction
   234  )
   235  
   236  func (t Type) String() string {
   237  	switch t {
   238  	case TypeUndefined:
   239  		return "undefined"
   240  	case TypeNull:
   241  		return "null"
   242  	case TypeBoolean:
   243  		return "boolean"
   244  	case TypeNumber:
   245  		return "number"
   246  	case TypeString:
   247  		return "string"
   248  	case TypeSymbol:
   249  		return "symbol"
   250  	case TypeObject:
   251  		return "object"
   252  	case TypeFunction:
   253  		return "function"
   254  	default:
   255  		panic("bad type")
   256  	}
   257  }
   258  
   259  func (t Type) isObject() bool {
   260  	return t == TypeObject || t == TypeFunction
   261  }
   262  
   263  // Type returns the JavaScript type of the value v. It is similar to JavaScript's typeof operator,
   264  // except that it returns TypeNull instead of TypeObject for null.
   265  func (v Value) Type() Type {
   266  	switch v.ref {
   267  	case valueUndefined.ref:
   268  		return TypeUndefined
   269  	case valueNull.ref:
   270  		return TypeNull
   271  	case valueTrue.ref, valueFalse.ref:
   272  		return TypeBoolean
   273  	}
   274  	if v.isNumber() {
   275  		return TypeNumber
   276  	}
   277  	typeFlag := (v.ref >> 32) & 7
   278  	switch typeFlag {
   279  	case typeFlagObject:
   280  		return TypeObject
   281  	case typeFlagString:
   282  		return TypeString
   283  	case typeFlagSymbol:
   284  		return TypeSymbol
   285  	case typeFlagFunction:
   286  		return TypeFunction
   287  	default:
   288  		panic("bad type flag")
   289  	}
   290  }
   291  
   292  // Get returns the JavaScript property p of value v.
   293  // It panics if v is not a JavaScript object.
   294  func (v Value) Get(p string) Value {
   295  	if vType := v.Type(); !vType.isObject() {
   296  		panic(&ValueError{"Value.Get", vType})
   297  	}
   298  	r := makeValue(valueGet(v.ref, p))
   299  	runtime.KeepAlive(v)
   300  	return r
   301  }
   302  
   303  // valueGet returns a ref to JavaScript property p of ref v.
   304  //
   305  // (noescape): This is safe because no references are maintained to the
   306  //             Go string p after the syscall returns.
   307  //
   308  //go:wasmimport gojs syscall/js.valueGet
   309  //go:noescape
   310  func valueGet(v ref, p string) ref
   311  
   312  // Set sets the JavaScript property p of value v to ValueOf(x).
   313  // It panics if v is not a JavaScript object.
   314  func (v Value) Set(p string, x any) {
   315  	if vType := v.Type(); !vType.isObject() {
   316  		panic(&ValueError{"Value.Set", vType})
   317  	}
   318  	xv := ValueOf(x)
   319  	valueSet(v.ref, p, xv.ref)
   320  	runtime.KeepAlive(v)
   321  	runtime.KeepAlive(xv)
   322  }
   323  
   324  // valueSet sets property p of ref v to ref x.
   325  //
   326  // (noescape): This is safe because no references are maintained to the
   327  //             Go string p after the syscall returns.
   328  //
   329  //go:wasmimport gojs syscall/js.valueSet
   330  //go:noescape
   331  func valueSet(v ref, p string, x ref)
   332  
   333  // Delete deletes the JavaScript property p of value v.
   334  // It panics if v is not a JavaScript object.
   335  func (v Value) Delete(p string) {
   336  	if vType := v.Type(); !vType.isObject() {
   337  		panic(&ValueError{"Value.Delete", vType})
   338  	}
   339  	valueDelete(v.ref, p)
   340  	runtime.KeepAlive(v)
   341  }
   342  
   343  // valueDelete deletes the JavaScript property p of ref v.
   344  //
   345  // (noescape): This is safe because no references are maintained to the
   346  //             Go string p after the syscall returns.
   347  //
   348  //go:wasmimport gojs syscall/js.valueDelete
   349  //go:noescape
   350  func valueDelete(v ref, p string)
   351  
   352  // Index returns JavaScript index i of value v.
   353  // It panics if v is not a JavaScript object.
   354  func (v Value) Index(i int) Value {
   355  	if vType := v.Type(); !vType.isObject() {
   356  		panic(&ValueError{"Value.Index", vType})
   357  	}
   358  	r := makeValue(valueIndex(v.ref, i))
   359  	runtime.KeepAlive(v)
   360  	return r
   361  }
   362  
   363  //go:wasmimport gojs syscall/js.valueIndex
   364  func valueIndex(v ref, i int) ref
   365  
   366  // SetIndex sets the JavaScript index i of value v to ValueOf(x).
   367  // It panics if v is not a JavaScript object.
   368  func (v Value) SetIndex(i int, x any) {
   369  	if vType := v.Type(); !vType.isObject() {
   370  		panic(&ValueError{"Value.SetIndex", vType})
   371  	}
   372  	xv := ValueOf(x)
   373  	valueSetIndex(v.ref, i, xv.ref)
   374  	runtime.KeepAlive(v)
   375  	runtime.KeepAlive(xv)
   376  }
   377  
   378  //go:wasmimport gojs syscall/js.valueSetIndex
   379  func valueSetIndex(v ref, i int, x ref)
   380  
   381  // makeArgSlices makes two slices to hold JavaScript arg data.
   382  // It can be paired with storeArgs to make-and-store JavaScript arg slices.
   383  // However, the two functions are separated to ensure makeArgSlices is inlined
   384  // which will prevent the slices from being heap allocated for small (<=16)
   385  // numbers of args.
   386  func makeArgSlices(size int) (argVals []Value, argRefs []ref) {
   387  	// value chosen for being power of two, and enough to handle all web APIs
   388  	// in particular, note that WebGL2's texImage2D takes up to 10 arguments
   389  	const maxStackArgs = 16
   390  	if size <= maxStackArgs {
   391  		// as long as makeArgs is inlined, these will be stack-allocated
   392  		argVals = make([]Value, size, maxStackArgs)
   393  		argRefs = make([]ref, size, maxStackArgs)
   394  	} else {
   395  		// allocates on the heap, but exceeding maxStackArgs should be rare
   396  		argVals = make([]Value, size)
   397  		argRefs = make([]ref, size)
   398  	}
   399  	return
   400  }
   401  
   402  // storeArgs maps input args onto respective Value and ref slices.
   403  // It can be paired with makeArgSlices to make-and-store JavaScript arg slices.
   404  func storeArgs(args []any, argValsDst []Value, argRefsDst []ref) {
   405  	// would go in makeArgs if the combined func was simple enough to inline
   406  	for i, arg := range args {
   407  		v := ValueOf(arg)
   408  		argValsDst[i] = v
   409  		argRefsDst[i] = v.ref
   410  	}
   411  }
   412  
   413  // Length returns the JavaScript property "length" of v.
   414  // It panics if v is not a JavaScript object.
   415  func (v Value) Length() int {
   416  	if vType := v.Type(); !vType.isObject() {
   417  		panic(&ValueError{"Value.SetIndex", vType})
   418  	}
   419  	r := valueLength(v.ref)
   420  	runtime.KeepAlive(v)
   421  	return r
   422  }
   423  
   424  //go:wasmimport gojs syscall/js.valueLength
   425  func valueLength(v ref) int
   426  
   427  // Call does a JavaScript call to the method m of value v with the given arguments.
   428  // It panics if v has no method m.
   429  // The arguments get mapped to JavaScript values according to the ValueOf function.
   430  func (v Value) Call(m string, args ...any) Value {
   431  	argVals, argRefs := makeArgSlices(len(args))
   432  	storeArgs(args, argVals, argRefs)
   433  	res, ok := valueCall(v.ref, m, argRefs)
   434  	runtime.KeepAlive(v)
   435  	runtime.KeepAlive(argVals)
   436  	if !ok {
   437  		if vType := v.Type(); !vType.isObject() { // check here to avoid overhead in success case
   438  			panic(&ValueError{"Value.Call", vType})
   439  		}
   440  		if propType := v.Get(m).Type(); propType != TypeFunction {
   441  			panic("syscall/js: Value.Call: property " + m + " is not a function, got " + propType.String())
   442  		}
   443  		panic(Error{makeValue(res)})
   444  	}
   445  	return makeValue(res)
   446  }
   447  
   448  // valueCall does a JavaScript call to the method name m of ref v with the given arguments.
   449  //
   450  // (noescape): This is safe because no references are maintained to the
   451  //             Go string m after the syscall returns. Additionally, the args slice
   452  //             is only used temporarily to collect the JavaScript objects for
   453  //             the JavaScript method invocation.
   454  //
   455  //go:wasmimport gojs syscall/js.valueCall
   456  //go:nosplit
   457  //go:noescape
   458  func valueCall(v ref, m string, args []ref) (ref, bool)
   459  
   460  // Invoke does a JavaScript call of the value v with the given arguments.
   461  // It panics if v is not a JavaScript function.
   462  // The arguments get mapped to JavaScript values according to the ValueOf function.
   463  func (v Value) Invoke(args ...any) Value {
   464  	argVals, argRefs := makeArgSlices(len(args))
   465  	storeArgs(args, argVals, argRefs)
   466  	res, ok := valueInvoke(v.ref, argRefs)
   467  	runtime.KeepAlive(v)
   468  	runtime.KeepAlive(argVals)
   469  	if !ok {
   470  		if vType := v.Type(); vType != TypeFunction { // check here to avoid overhead in success case
   471  			panic(&ValueError{"Value.Invoke", vType})
   472  		}
   473  		panic(Error{makeValue(res)})
   474  	}
   475  	return makeValue(res)
   476  }
   477  
   478  // valueInvoke does a JavaScript call to value v with the given arguments.
   479  //
   480  // (noescape): This is safe because the args slice is only used temporarily
   481  //             to collect the JavaScript objects for the JavaScript method
   482  //             invocation.
   483  //
   484  //go:wasmimport gojs syscall/js.valueInvoke
   485  //go:noescape
   486  func valueInvoke(v ref, args []ref) (ref, bool)
   487  
   488  // New uses JavaScript's "new" operator with value v as constructor and the given arguments.
   489  // It panics if v is not a JavaScript function.
   490  // The arguments get mapped to JavaScript values according to the ValueOf function.
   491  func (v Value) New(args ...any) Value {
   492  	argVals, argRefs := makeArgSlices(len(args))
   493  	storeArgs(args, argVals, argRefs)
   494  	res, ok := valueNew(v.ref, argRefs)
   495  	runtime.KeepAlive(v)
   496  	runtime.KeepAlive(argVals)
   497  	if !ok {
   498  		if vType := v.Type(); vType != TypeFunction { // check here to avoid overhead in success case
   499  			panic(&ValueError{"Value.Invoke", vType})
   500  		}
   501  		panic(Error{makeValue(res)})
   502  	}
   503  	return makeValue(res)
   504  }
   505  
   506  // valueNew uses JavaScript's "new" operator with value v as a constructor and the given arguments.
   507  //
   508  // (noescape): This is safe because the args slice is only used temporarily
   509  //             to collect the JavaScript objects for the constructor execution.
   510  //
   511  //go:wasmimport gojs syscall/js.valueNew
   512  //go:noescape
   513  func valueNew(v ref, args []ref) (ref, bool)
   514  
   515  func (v Value) isNumber() bool {
   516  	return v.ref == valueZero.ref ||
   517  		v.ref == valueNaN.ref ||
   518  		(v.ref != valueUndefined.ref && (v.ref>>32)&nanHead != nanHead)
   519  }
   520  
   521  func (v Value) float(method string) float64 {
   522  	if !v.isNumber() {
   523  		panic(&ValueError{method, v.Type()})
   524  	}
   525  	if v.ref == valueZero.ref {
   526  		return 0
   527  	}
   528  	return *(*float64)(unsafe.Pointer(&v.ref))
   529  }
   530  
   531  // Float returns the value v as a float64.
   532  // It panics if v is not a JavaScript number.
   533  func (v Value) Float() float64 {
   534  	return v.float("Value.Float")
   535  }
   536  
   537  // Int returns the value v truncated to an int.
   538  // It panics if v is not a JavaScript number.
   539  func (v Value) Int() int {
   540  	return int(v.float("Value.Int"))
   541  }
   542  
   543  // Bool returns the value v as a bool.
   544  // It panics if v is not a JavaScript boolean.
   545  func (v Value) Bool() bool {
   546  	switch v.ref {
   547  	case valueTrue.ref:
   548  		return true
   549  	case valueFalse.ref:
   550  		return false
   551  	default:
   552  		panic(&ValueError{"Value.Bool", v.Type()})
   553  	}
   554  }
   555  
   556  // Truthy returns the JavaScript "truthiness" of the value v. In JavaScript,
   557  // false, 0, "", null, undefined, and NaN are "falsy", and everything else is
   558  // "truthy". See https://developer.mozilla.org/en-US/docs/Glossary/Truthy.
   559  func (v Value) Truthy() bool {
   560  	switch v.Type() {
   561  	case TypeUndefined, TypeNull:
   562  		return false
   563  	case TypeBoolean:
   564  		return v.Bool()
   565  	case TypeNumber:
   566  		return v.ref != valueNaN.ref && v.ref != valueZero.ref
   567  	case TypeString:
   568  		return v.String() != ""
   569  	case TypeSymbol, TypeFunction, TypeObject:
   570  		return true
   571  	default:
   572  		panic("bad type")
   573  	}
   574  }
   575  
   576  // String returns the value v as a string.
   577  // String is a special case because of Go's String method convention. Unlike the other getters,
   578  // it does not panic if v's Type is not TypeString. Instead, it returns a string of the form "<T>"
   579  // or "<T: V>" where T is v's type and V is a string representation of v's value.
   580  func (v Value) String() string {
   581  	switch v.Type() {
   582  	case TypeString:
   583  		return jsString(v)
   584  	case TypeUndefined:
   585  		return "<undefined>"
   586  	case TypeNull:
   587  		return "<null>"
   588  	case TypeBoolean:
   589  		return "<boolean: " + jsString(v) + ">"
   590  	case TypeNumber:
   591  		return "<number: " + jsString(v) + ">"
   592  	case TypeSymbol:
   593  		return "<symbol>"
   594  	case TypeObject:
   595  		return "<object>"
   596  	case TypeFunction:
   597  		return "<function>"
   598  	default:
   599  		panic("bad type")
   600  	}
   601  }
   602  
   603  func jsString(v Value) string {
   604  	str, length := valuePrepareString(v.ref)
   605  	runtime.KeepAlive(v)
   606  	b := make([]byte, length)
   607  	valueLoadString(str, b)
   608  	finalizeRef(str)
   609  	return string(b)
   610  }
   611  
   612  //go:wasmimport gojs syscall/js.valuePrepareString
   613  func valuePrepareString(v ref) (ref, int)
   614  
   615  // valueLoadString loads string data located at ref v into byte slice b.
   616  //
   617  // (noescape): This is safe because the byte slice is only used as a destination
   618  //             for storing the string data and references to it are not maintained.
   619  //
   620  //go:wasmimport gojs syscall/js.valueLoadString
   621  //go:noescape
   622  func valueLoadString(v ref, b []byte)
   623  
   624  // InstanceOf reports whether v is an instance of type t according to JavaScript's instanceof operator.
   625  func (v Value) InstanceOf(t Value) bool {
   626  	r := valueInstanceOf(v.ref, t.ref)
   627  	runtime.KeepAlive(v)
   628  	runtime.KeepAlive(t)
   629  	return r
   630  }
   631  
   632  //go:wasmimport gojs syscall/js.valueInstanceOf
   633  func valueInstanceOf(v ref, t ref) bool
   634  
   635  // A ValueError occurs when a Value method is invoked on
   636  // a Value that does not support it. Such cases are documented
   637  // in the description of each method.
   638  type ValueError struct {
   639  	Method string
   640  	Type   Type
   641  }
   642  
   643  func (e *ValueError) Error() string {
   644  	return "syscall/js: call of " + e.Method + " on " + e.Type.String()
   645  }
   646  
   647  // CopyBytesToGo copies bytes from src to dst.
   648  // It panics if src is not a Uint8Array or Uint8ClampedArray.
   649  // It returns the number of bytes copied, which will be the minimum of the lengths of src and dst.
   650  func CopyBytesToGo(dst []byte, src Value) int {
   651  	n, ok := copyBytesToGo(dst, src.ref)
   652  	runtime.KeepAlive(src)
   653  	if !ok {
   654  		panic("syscall/js: CopyBytesToGo: expected src to be a Uint8Array or Uint8ClampedArray")
   655  	}
   656  	return n
   657  }
   658  
   659  // copyBytesToGo copies bytes from src to dst.
   660  //
   661  // (noescape): This is safe because the dst byte slice is only used as a dst
   662  //             copy buffer and no references to it are maintained.
   663  //
   664  //go:wasmimport gojs syscall/js.copyBytesToGo
   665  //go:noescape
   666  func copyBytesToGo(dst []byte, src ref) (int, bool)
   667  
   668  // CopyBytesToJS copies bytes from src to dst.
   669  // It panics if dst is not a Uint8Array or Uint8ClampedArray.
   670  // It returns the number of bytes copied, which will be the minimum of the lengths of src and dst.
   671  func CopyBytesToJS(dst Value, src []byte) int {
   672  	n, ok := copyBytesToJS(dst.ref, src)
   673  	runtime.KeepAlive(dst)
   674  	if !ok {
   675  		panic("syscall/js: CopyBytesToJS: expected dst to be a Uint8Array or Uint8ClampedArray")
   676  	}
   677  	return n
   678  }
   679  
   680  // copyBytesToJs copies bytes from src to dst.
   681  //
   682  // (noescape): This is safe because the src byte slice is only used as a src
   683  //             copy buffer and no references to it are maintained.
   684  //
   685  //go:wasmimport gojs syscall/js.copyBytesToJS
   686  //go:noescape
   687  func copyBytesToJS(dst ref, src []byte) (int, bool)
   688  

View as plain text