@@ -209,6 +209,7 @@ func ValueOf(x interface{}) Value {
209
209
}
210
210
}
211
211
212
+ //go:noescape
212
213
func stringVal (x string ) ref
213
214
214
215
// Type represents the JavaScript type of a Value.
@@ -292,6 +293,7 @@ func (v Value) Get(p string) Value {
292
293
return r
293
294
}
294
295
296
+ //go:noescape
295
297
func valueGet (v ref , p string ) ref
296
298
297
299
// Set sets the JavaScript property p of value v to ValueOf(x).
@@ -306,6 +308,7 @@ func (v Value) Set(p string, x interface{}) {
306
308
runtime .KeepAlive (xv )
307
309
}
308
310
311
+ //go:noescape
309
312
func valueSet (v ref , p string , x ref )
310
313
311
314
// Delete deletes the JavaScript property p of value v.
@@ -318,6 +321,7 @@ func (v Value) Delete(p string) {
318
321
runtime .KeepAlive (v )
319
322
}
320
323
324
+ //go:noescape
321
325
func valueDelete (v ref , p string )
322
326
323
327
// Index returns JavaScript index i of value v.
@@ -347,15 +351,29 @@ func (v Value) SetIndex(i int, x interface{}) {
347
351
348
352
func valueSetIndex (v ref , i int , x ref )
349
353
350
- func makeArgs (args []interface {}) ([]Value , []ref ) {
351
- argVals := make ([]Value , len (args ))
352
- argRefs := make ([]ref , len (args ))
354
+ func makeArgs (args []interface {}) (argVals []Value , argRefs []ref ) {
355
+ // value chosen for being power of two, and enough to handle all web APIs
356
+ // in particular, note that WebGL2's texImage2D takes up to 10 arguments
357
+ const maxStackArgs = 16
358
+ if len (args ) <= maxStackArgs {
359
+ // as long as makeArgs is inlined, these will be stack-allocated
360
+ argVals = make ([]Value , len (args ), maxStackArgs )
361
+ argRefs = make ([]ref , len (args ), maxStackArgs )
362
+ } else {
363
+ // allocates on the heap, but exceeding maxStackArgs should be rare
364
+ argVals = make ([]Value , len (args ))
365
+ argRefs = make ([]ref , len (args ))
366
+ }
367
+ return
368
+ }
369
+
370
+ func storeArgs (args []interface {}, argValsDst []Value , argRefsDst []ref ) {
371
+ // would go in makeArgs if the combined func was simple enough to inline
353
372
for i , arg := range args {
354
373
v := ValueOf (arg )
355
- argVals [i ] = v
356
- argRefs [i ] = v .ref
374
+ argValsDst [i ] = v
375
+ argRefsDst [i ] = v .ref
357
376
}
358
- return argVals , argRefs
359
377
}
360
378
361
379
// Length returns the JavaScript property "length" of v.
@@ -376,6 +394,7 @@ func valueLength(v ref) int
376
394
// The arguments get mapped to JavaScript values according to the ValueOf function.
377
395
func (v Value ) Call (m string , args ... interface {}) Value {
378
396
argVals , argRefs := makeArgs (args )
397
+ storeArgs (args , argVals , argRefs )
379
398
res , ok := valueCall (v .ref , m , argRefs )
380
399
runtime .KeepAlive (v )
381
400
runtime .KeepAlive (argVals )
@@ -391,13 +410,15 @@ func (v Value) Call(m string, args ...interface{}) Value {
391
410
return makeValue (res )
392
411
}
393
412
413
+ //go:noescape
394
414
func valueCall (v ref , m string , args []ref ) (ref , bool )
395
415
396
416
// Invoke does a JavaScript call of the value v with the given arguments.
397
417
// It panics if v is not a JavaScript function.
398
418
// The arguments get mapped to JavaScript values according to the ValueOf function.
399
419
func (v Value ) Invoke (args ... interface {}) Value {
400
420
argVals , argRefs := makeArgs (args )
421
+ storeArgs (args , argVals , argRefs )
401
422
res , ok := valueInvoke (v .ref , argRefs )
402
423
runtime .KeepAlive (v )
403
424
runtime .KeepAlive (argVals )
@@ -410,13 +431,15 @@ func (v Value) Invoke(args ...interface{}) Value {
410
431
return makeValue (res )
411
432
}
412
433
434
+ //go:noescape
413
435
func valueInvoke (v ref , args []ref ) (ref , bool )
414
436
415
437
// New uses JavaScript's "new" operator with value v as constructor and the given arguments.
416
438
// It panics if v is not a JavaScript function.
417
439
// The arguments get mapped to JavaScript values according to the ValueOf function.
418
440
func (v Value ) New (args ... interface {}) Value {
419
441
argVals , argRefs := makeArgs (args )
442
+ storeArgs (args , argVals , argRefs )
420
443
res , ok := valueNew (v .ref , argRefs )
421
444
runtime .KeepAlive (v )
422
445
runtime .KeepAlive (argVals )
@@ -429,6 +452,7 @@ func (v Value) New(args ...interface{}) Value {
429
452
return makeValue (res )
430
453
}
431
454
455
+ //go:noescape
432
456
func valueNew (v ref , args []ref ) (ref , bool )
433
457
434
458
func (v Value ) isNumber () bool {
@@ -580,4 +604,5 @@ func CopyBytesToJS(dst Value, src []byte) int {
580
604
return n
581
605
}
582
606
607
+ //go:noescape
583
608
func copyBytesToJS (dst ref , src []byte ) (int , bool )
0 commit comments