(vm *VM, fn func(vm *VM, args Values) any)
| 319 | } |
| 320 | |
| 321 | func WrapVmCall(vm *VM, fn func(vm *VM, args Values) any) any { |
| 322 | return func(c otto.FunctionCall) otto.Value { |
| 323 | // Resolve into a local variable instead of reassigning the captured |
| 324 | // vm: the closure is shared across all forked VMs (otto copies the |
| 325 | // runtime but not the Go closure), so writing the captured variable |
| 326 | // would race between concurrent VM runs. |
| 327 | actualVM := vm.resolveVM(c.Otto) |
| 328 | if actualVM == nil { |
| 329 | panic("detached vm") |
| 330 | } |
| 331 | |
| 332 | defer func() { |
| 333 | if e := recover(); e != nil { |
| 334 | actualVM.ThrowError(e) |
| 335 | } |
| 336 | }() |
| 337 | |
| 338 | ret := fn(actualVM, newValues(actualVM, c.ArgumentList)) |
| 339 | ov, e := actualVM.o.ToValue(ret) |
| 340 | if e != nil { |
| 341 | actualVM.ThrowTypeError(e.Error()) |
| 342 | } |
| 343 | return ov |
| 344 | } |
| 345 | } |
| 346 | |
| 347 | func wrapVmRun(ctx context.Context, vm *VM, fn func() (otto.Value, error)) (value *Value, e error) { |
| 348 | defer func() { |
no test coverage detected