@@ -210,7 +210,13 @@ func ValueOf(x any) Value {
210
210
}
211
211
}
212
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
+ //
213
218
//go:wasmimport gojs syscall/js.stringVal
219
+ //go:noescape
214
220
func stringVal (x string ) ref
215
221
216
222
// Type represents the JavaScript type of a Value.
@@ -294,7 +300,13 @@ func (v Value) Get(p string) Value {
294
300
return r
295
301
}
296
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
+ //
297
308
//go:wasmimport gojs syscall/js.valueGet
309
+ //go:noescape
298
310
func valueGet (v ref , p string ) ref
299
311
300
312
// Set sets the JavaScript property p of value v to ValueOf(x).
@@ -309,7 +321,13 @@ func (v Value) Set(p string, x any) {
309
321
runtime .KeepAlive (xv )
310
322
}
311
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
+ //
312
329
//go:wasmimport gojs syscall/js.valueSet
330
+ //go:noescape
313
331
func valueSet (v ref , p string , x ref )
314
332
315
333
// Delete deletes the JavaScript property p of value v.
@@ -322,7 +340,13 @@ func (v Value) Delete(p string) {
322
340
runtime .KeepAlive (v )
323
341
}
324
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
+ //
325
348
//go:wasmimport gojs syscall/js.valueDelete
349
+ //go:noescape
326
350
func valueDelete (v ref , p string )
327
351
328
352
// Index returns JavaScript index i of value v.
@@ -354,15 +378,36 @@ func (v Value) SetIndex(i int, x any) {
354
378
//go:wasmimport gojs syscall/js.valueSetIndex
355
379
func valueSetIndex (v ref , i int , x ref )
356
380
357
- func makeArgs (args []any ) ([]Value , []ref ) {
358
- argVals := make ([]Value , len (args ))
359
- argRefs := make ([]ref , len (args ))
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
360
406
for i , arg := range args {
361
407
v := ValueOf (arg )
362
- argVals [i ] = v
363
- argRefs [i ] = v .ref
408
+ argValsDst [i ] = v
409
+ argRefsDst [i ] = v .ref
364
410
}
365
- return argVals , argRefs
366
411
}
367
412
368
413
// Length returns the JavaScript property "length" of v.
@@ -383,7 +428,8 @@ func valueLength(v ref) int
383
428
// It panics if v has no method m.
384
429
// The arguments get mapped to JavaScript values according to the ValueOf function.
385
430
func (v Value ) Call (m string , args ... any ) Value {
386
- argVals , argRefs := makeArgs (args )
431
+ argVals , argRefs := makeArgSlices (len (args ))
432
+ storeArgs (args , argVals , argRefs )
387
433
res , ok := valueCall (v .ref , m , argRefs )
388
434
runtime .KeepAlive (v )
389
435
runtime .KeepAlive (argVals )
@@ -399,15 +445,24 @@ func (v Value) Call(m string, args ...any) Value {
399
445
return makeValue (res )
400
446
}
401
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
+ //
402
455
//go:wasmimport gojs syscall/js.valueCall
403
456
//go:nosplit
457
+ //go:noescape
404
458
func valueCall (v ref , m string , args []ref ) (ref , bool )
405
459
406
460
// Invoke does a JavaScript call of the value v with the given arguments.
407
461
// It panics if v is not a JavaScript function.
408
462
// The arguments get mapped to JavaScript values according to the ValueOf function.
409
463
func (v Value ) Invoke (args ... any ) Value {
410
- argVals , argRefs := makeArgs (args )
464
+ argVals , argRefs := makeArgSlices (len (args ))
465
+ storeArgs (args , argVals , argRefs )
411
466
res , ok := valueInvoke (v .ref , argRefs )
412
467
runtime .KeepAlive (v )
413
468
runtime .KeepAlive (argVals )
@@ -420,14 +475,22 @@ func (v Value) Invoke(args ...any) Value {
420
475
return makeValue (res )
421
476
}
422
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
+ //
423
484
//go:wasmimport gojs syscall/js.valueInvoke
485
+ //go:noescape
424
486
func valueInvoke (v ref , args []ref ) (ref , bool )
425
487
426
488
// New uses JavaScript's "new" operator with value v as constructor and the given arguments.
427
489
// It panics if v is not a JavaScript function.
428
490
// The arguments get mapped to JavaScript values according to the ValueOf function.
429
491
func (v Value ) New (args ... any ) Value {
430
- argVals , argRefs := makeArgs (args )
492
+ argVals , argRefs := makeArgSlices (len (args ))
493
+ storeArgs (args , argVals , argRefs )
431
494
res , ok := valueNew (v .ref , argRefs )
432
495
runtime .KeepAlive (v )
433
496
runtime .KeepAlive (argVals )
@@ -440,7 +503,13 @@ func (v Value) New(args ...any) Value {
440
503
return makeValue (res )
441
504
}
442
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
+ //
443
511
//go:wasmimport gojs syscall/js.valueNew
512
+ //go:noescape
444
513
func valueNew (v ref , args []ref ) (ref , bool )
445
514
446
515
func (v Value ) isNumber () bool {
@@ -543,7 +612,13 @@ func jsString(v Value) string {
543
612
//go:wasmimport gojs syscall/js.valuePrepareString
544
613
func valuePrepareString (v ref ) (ref , int )
545
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
+ //
546
620
//go:wasmimport gojs syscall/js.valueLoadString
621
+ //go:noescape
547
622
func valueLoadString (v ref , b []byte )
548
623
549
624
// InstanceOf reports whether v is an instance of type t according to JavaScript's instanceof operator.
@@ -581,7 +656,13 @@ func CopyBytesToGo(dst []byte, src Value) int {
581
656
return n
582
657
}
583
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
+ //
584
664
//go:wasmimport gojs syscall/js.copyBytesToGo
665
+ //go:noescape
585
666
func copyBytesToGo (dst []byte , src ref ) (int , bool )
586
667
587
668
// CopyBytesToJS copies bytes from src to dst.
@@ -596,5 +677,11 @@ func CopyBytesToJS(dst Value, src []byte) int {
596
677
return n
597
678
}
598
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
+ //
599
685
//go:wasmimport gojs syscall/js.copyBytesToJS
686
+ //go:noescape
600
687
func copyBytesToJS (dst ref , src []byte ) (int , bool )
0 commit comments