Documentation
¶
Overview ¶
Package js the JavaScript implementation.
Run ESM/CJS modules:
func main() {
module, err := js.CompileModule("", "module.exports = () => 'some value'")
if err != nil {
panic(err)
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
value, err := js.RunModule(ctx, module)
if err != nil {
panic(err)
}
fmt.Println(value.Export())
}
Index ¶
- Constants
- Variables
- func AccountFromCtx(ctx context.Context) any
- func CallModuleExport(ctx context.Context, module sobek.CyclicModuleRecord, exportName string, ...) (ret sobek.Value, err error)
- func Cleanup(rt *sobek.Runtime, job ...func())
- func CompileModule(name, source string) (sobek.CyclicModuleRecord, error)
- func Context(rt *sobek.Runtime) context.Context
- func EnableConsole(rt *sobek.Runtime, attr ...slog.Attr)
- func Format(rt *sobek.Runtime, args ...sobek.Value) string
- func Loader() modules.Loader
- func Logger(ctx context.Context) *slog.Logger
- func ModuleCallable(rt *sobek.Runtime, module sobek.CyclicModuleRecord) (sobek.Callable, error)
- func ModuleInstance(rt *sobek.Runtime, module sobek.CyclicModuleRecord) (sobek.ModuleInstance, error)
- func Register(name string, mod modules.Module)
- func Run(ctx context.Context, fn func(*sobek.Runtime) error) error
- func RunModule(ctx context.Context, module sobek.CyclicModuleRecord, args ...any) (sobek.Value, error)
- func RunProgram(ctx context.Context, program *sobek.Program) (sobek.Value, error)
- func RunString(ctx context.Context, str string) (sobek.Value, error)
- func SetLoader(ml modules.Loader)
- func SetScheduler(s Scheduler)
- func Throw(rt *sobek.Runtime, err error)
- func ToBytes(data any) ([]byte, error)
- func Unwrap(value sobek.Value) (any, error)
- func WithAccount(ctx context.Context, account any) context.Context
- func WithLogger(ctx context.Context, logger *slog.Logger) context.Context
- type Enqueue
- type EventLoop
- type Global
- type Metrics
- type Module
- type Option
- type Scheduler
- type SchedulerOptions
- type VM
Constants ¶
const ( // DefaultTimeoutGetVM default get js.VM timeout DefaultTimeoutGetVM = 500 * time.Millisecond // DefaultMaxRetriesGetVM default retries times DefaultMaxRetriesGetVM = 3 )
Variables ¶
var ( // ErrSchedulerClosed the scheduler was closed error ErrSchedulerClosed = errors.New("scheduler was closed") )
Functions ¶
func AccountFromCtx ¶
AccountFromCtx returns the value set by WithAccount, or nil if unset.
func CallModuleExport ¶
func CallModuleExport(ctx context.Context, module sobek.CyclicModuleRecord, exportName string, args ...any) (ret sobek.Value, err error)
CallModuleExport calls the named export function from a module.
func Cleanup ¶
Cleanup add a function to execute when the VM has finished running. eg: close resources...
func CompileModule ¶
func CompileModule(name, source string) (sobek.CyclicModuleRecord, error)
CompileModule compile module from source string (cjs/esm).
func ModuleCallable ¶
ModuleCallable return the sobek.CyclicModuleRecord default export as sobek.Callable.
func ModuleInstance ¶
func ModuleInstance(rt *sobek.Runtime, module sobek.CyclicModuleRecord) (sobek.ModuleInstance, error)
ModuleInstance return the sobek.ModuleInstance.
func Register ¶
func Register(name string, mod modules.Module)
Register registers a native module importable as "superuser/<name>" (legacy superuser-api convention).
func Run ¶
Run executes the given function
example:
err := js.Run(context.Background(), func(rt *sobek.Runtime) error {
_, err := rt.RunString(`console.log('hello world')`)
return err
})
if err != nil {
panic(err)
}
func RunModule ¶
func RunModule(ctx context.Context, module sobek.CyclicModuleRecord, args ...any) (sobek.Value, error)
RunModule the sobek.CyclicModuleRecord
example:
module, err := js.CompileModule("add", "export default (a, b) => a + b")
if err != nil {
panic(err)
}
value, err := js.RunModule(context.Background(), module, 1, 2)
if err != nil {
panic(err)
}
fmt.Println(value.Export()) // 3
func RunProgram ¶
RunProgram executes the given sobek.Program
example:
program, err := sobek.Compile("", `1 + 1`, false)
if err != nil {
panic(err)
}
value, err := js.RunProgram(context.Background(), program)
if err != nil {
panic(err)
}
fmt.Println(value.Export()) // 2
func RunString ¶
RunString executes the given string
example:
value, err := js.RunString(context.Background(), `1 + 1`)
if err != nil {
panic(err)
}
fmt.Println(value.Export()) // 2
func WithAccount ¶
WithAccount attaches the current JS/storage caller identity to ctx (e.g. *request.Account from search package).
Types ¶
type Enqueue ¶
type Enqueue func(func() error)
Enqueue add a job to the job queue.
func EnqueueJob ¶
EnqueueJob return a function Enqueue to add a job to the job queue.
type EventLoop ¶
type EventLoop struct {
// contains filtered or unexported fields
}
EventLoop implements an eventloop.
func (*EventLoop) Cleanup ¶
func (e *EventLoop) Cleanup(job ...func())
Cleanup add a function to execute when run finish.
func (*EventLoop) EnqueueJob ¶
EnqueueJob return a function Enqueue to add a job to the job queue. Usage:
func main() {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(`{"foo":"bar"}`))
}))
defer server.Close()
loop := js.NewEventLoop()
runtime := sobek.New()
_ = runtime.Set("fetch", func(call sobek.FunctionCall) sobek.Value {
promise, resolve, reject := runtime.NewPromise()
enqueue := loop.EnqueueJob()
go func() {
res, err := http.Get(call.Argument(0).String())
if err != nil {
enqueue(func() error { return reject(err) })
return
}
loop.Cleanup(func() { res.Body.Close() })
data, err := io.ReadAll(res.Body)
if err != nil {
enqueue(func() error { return reject(err) })
return
}
enqueue(func() error { return resolve(string(data)) })
}()
return runtime.ToValue(promise)
})
var (
ret sobek.Value
err error
)
err = loop.Start(func() error {
ret, err = runtime.RunString(fmt.Sprintf(`fetch("%s")`, server.URL))
return err
})
if err != nil {
panic(err)
}
promise, ok := ret.Export().(*sobek.Promise)
if !ok {
panic("expect promise")
return
}
switch promise.State() {
case sobek.PromiseStatePending:
panic("unexpect pending state")
case sobek.PromiseStateRejected:
panic(promise.Result().(error))
case sobek.PromiseStateFulfilled:
fmt.Println(promise.Result().Export())
}
}
type Metrics ¶
type Metrics struct {
Max int `json:"max"` // max vm size
Idle int `json:"idle"` // idle vm size
Remaining int `json:"remaining"` // remaining creatable vm size
}
Metrics contains Scheduler metrics
type Module ¶
type Module = modules.Module
Module is the native module interface (alias for modules.Module).
type Scheduler ¶
type Scheduler interface {
// Get a VM from the pool (or create under cap).
Get() (VM, error)
// Shrink the idle VM to initial VM size
Shrink()
// Metrics Scheduler metrics
Metrics() Metrics
// Close the scheduler
Close() error
}
Scheduler the js.VM scheduler
func NewScheduler ¶
func NewScheduler(opt SchedulerOptions) Scheduler
NewScheduler create a new Scheduler
type SchedulerOptions ¶
type SchedulerOptions struct {
InitialVMs uint `yaml:"initial-vms" json:"initialVMs"`
MaxVMs uint `yaml:"max-vms" json:"maxVMs"`
GetMaxRetries uint `yaml:"get-max-retries" json:"maxRetries"`
GetTimeout time.Duration `yaml:"get-timeout" json:"timeout"`
VMOptions []Option `yaml:"-"` // options for NewVM
}
SchedulerOptions options
type VM ¶
type VM interface {
// RunModule run the sobek.CyclicModuleRecord.
// To compile the module, sobek.ParseModule or CompileModule.
// Any additional arguments are passed to the default export function arguments.
RunModule(ctx context.Context, module sobek.CyclicModuleRecord, args ...any) (sobek.Value, error)
// RunString executes the given string
RunString(ctx context.Context, str string) (sobek.Value, error)
// RunProgram executes the given sobek.Program
RunProgram(ctx context.Context, program *sobek.Program) (sobek.Value, error)
// Run execute the given function in the EventLoop.
// when context done interrupt VM execution and release the VM.
// This is usually used when needs to be called repeatedly many times.
// like this:
//
// func main() {
// ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
// defer cancel()
//
// vm := js.NewVM()
// rt := vm.Runtime()
//
// module, err := js.CompileModule("add", "export default (a, b) => a + b")
// if err != nil {
// panic(module)
// }
//
// add, err := js.ModuleCallable(rt, module)
// if err != nil {
// panic(err)
// }
//
// var total int64
// vm.Run(ctx, func() error {
// for i := 0; i < 8; i++ {
// v, err := add(sobek.Undefined(), rt.ToValue(i), rt.ToValue(total))
// if err != nil {
// panic(err)
// }
// total = v.ToInteger()
// }
// return nil
// })
//
// fmt.Println(total)
// }
Run(context.Context, func() error) error
// Runtime return the js runtime
Runtime() *sobek.Runtime
}
VM the js runtime. An instance of VM can only be used by a single goroutine at a time.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package modulestest the module test vm
|
Package modulestest the module test vm |