Documentation
¶
Overview ¶
Package plugins runs third-party TypeScript plugins (spec 5.3–5.5): manifest validation, the sandbox and the ctx API. It does not import core; the host side is injected.
Index ¶
- Constants
- Variables
- func Build(dir, main string) ([]byte, error)
- func BuildWith(c Compiler, dir, main string) ([]byte, error)
- func CompareVersions(a, b string) int
- func EgressFor(kind InvocationKind, m Manifest, granted, holdsMail, scopeReadMail bool) (hosts []string, needsApproval bool)
- func FailReason(err error) string
- func FileSHA256(path string) (string, error)
- func HashDir(dir string, lim Limits) (string, error)
- func HostPort(u *url.URL) string
- func IsNativeFailure(err error) bool
- func LibraryName() string
- func PlatformKey() string
- func QuestionBytes(qs []Question) int
- func ScrubPaths(s string) string
- func ServeNative(args []string, stdin io.Reader, stdout, stderr io.Writer) int
- func ServeNativeWith(args []string, stdin io.Reader, stdout, stderr io.Writer, open NativeOpener) int
- func Snapshot(src, dst string, lim Limits) (sourceHash string, err error)
- type ActionInfo
- type Answer
- type Artifact
- type AttachmentMeta
- type CallScope
- type Client
- type Clock
- type Compiler
- type ConfigField
- type ConfigSnapshot
- type DraftInput
- type DraftUpdate
- type FetchRequest
- type FetchResponse
- type Hop
- type Host
- type Invocation
- type InvocationKind
- type Limits
- type MailMessage
- type MailSummary
- type Manifest
- type NativeCall
- type NativeError
- type NativeOpener
- type NativeOptions
- type NativeProcess
- type NativeSpec
- type NetError
- type NetOptions
- type Option
- type PermissionError
- type Permissions
- type Plugin
- func (p *Plugin) Actions() []ActionInfo
- func (p *Plugin) Card(ctx context.Context, inv Invocation, m MailMessage) (res any, matched bool, err error)
- func (p *Plugin) Emit(ctx context.Context, inv Invocation, event string, args ...any) error
- func (p *Plugin) EmitResult(ctx context.Context, inv Invocation, event string, args ...any) (any, error)
- func (p *Plugin) Events() []string
- func (p *Plugin) Handles(event string) bool
- func (p *Plugin) HasCard() bool
- func (p *Plugin) RunAction(ctx context.Context, inv Invocation, id string, target any) (any, error)
- func (p *Plugin) RunTool(ctx context.Context, inv Invocation, name string, args any) (any, error)
- func (p *Plugin) Tools() []ToolInfo
- func (p *Plugin) Translate(ctx context.Context, inv Invocation, req any) (any, error)
- func (p *Plugin) VM() *VM
- type Question
- type Registry
- type RegistryPlugin
- type RegistryRelease
- type Text
- type ToolInfo
- type VM
- func (v *VM) Call(ctx context.Context, inv Invocation, fn func(c *CallScope) (any, error)) (any, error)
- func (v *VM) Close()
- func (v *VM) HostFunc(name string, fn func(c *CallScope, call goja.FunctionCall) goja.Value) goja.Value
- func (v *VM) Init(ctx context.Context, inv Invocation, jsCtx func(c *CallScope) goja.Value) error
- type VMOptions
- type Watchdog
- type When
Constants ¶
const ( MaxBodyBytes = 256 << 10 // each of a message's text and html, as a plugin gets it MaxStorageValue = 64 << 10 MaxStorageTotal = 1 << 20 // keys and values of one plugin MaxLLMBytes = 64 << 10 // llm.complete prompt and answer; llm.decide input and question text MaxQuestions = 128 // per llm.decide call: rejected beyond, never split MaxFetchBody = 1 << 20 EventReceived = "message.received" EventBeforeSend = "message.beforeSend" )
Host-side data limits (spec 5.5).
const ( MaxFetchResponse = 5 << 20 FetchTimeout = 30 * time.Second )
Network limits of ctx.net.fetch (spec 5.5).
const AnyPlatform = "any"
const BuildDir = ".build"
BuildDir is where a snapshot keeps its compiled code; it is not part of the snapshot.
const MaxResultBytes = 1 << 20
MaxResultBytes caps the JSON a plugin call hands back to the host.
const NativeABI uint32 = 1
NativeABI is the C ABI version this build of Godwit loads.
Variables ¶
var ( ScriptLimits = Limits{File: 5 << 20, Total: 20 << 20} NativeLimits = Limits{File: 64 << 20, Total: 80 << 20} )
Snapshot limits by kind: a native plugin carries a shared library.
var ( // ErrNativeExited: the plugin's process ended (a crash, or it never loaded). ErrNativeExited = errors.New("plugin: native plugin exited") // ErrNativeABI: the call failed below the envelope. ErrNativeABI = errors.New("plugin: native call failed") )
var ( ErrPermission = errors.New("plugin: permission denied") ErrTimeout = errors.New("plugin: call timed out") ErrMemoryLimit = errors.New("plugin: memory limit exceeded") ErrClosed = errors.New("plugin: closed") ErrTooLarge = errors.New("plugin: data too large") )
var Platforms = []string{"darwin-arm64", "darwin-amd64", "windows-amd64", "windows-arm64", "linux-amd64", "linux-arm64"}
Platforms are the artifact keys of native releases; a script release has only AnyPlatform.
Functions ¶
func BuildWith ¶
BuildWith compiles the snapshot in dir with c. The result is cached in dir/.build under the snapshot's hash, main and c.Key(); other builds there are removed.
func CompareVersions ¶ added in v1.3.0
CompareVersions orders versions like 1.2.10 and v1.2.0-beta: numeric dot parts (missing ones are 0), then a release after its prereleases, which compare as strings.
func EgressFor ¶
func EgressFor(kind InvocationKind, m Manifest, granted, holdsMail, scopeReadMail bool) (hosts []string, needsApproval bool)
EgressFor is the egress rule for one call of kind into plugin m (plan 4 规格解释): the hosts its Invocation may fetch from, and whether the call needs an egress approval listing them first. granted: the plugin's current permissions are granted; holdsMail: the plugin was ever handed mail content (its storage may keep it, across calls, updates and restarts); scopeReadMail: the call's input may carry mail content (a Wit run that has read mail calling a tool, an action on a selection). Init, card and beforeSend never fetch; a hook gets every declared host; an action or a tool needs approval when the plugin holds net and any of mail:read, holdsMail or scopeReadMail. Since ctx.storage outlives a call, "this call read no mail" is never trusted for a plugin that has or ever had mail.
func FailReason ¶
FailReason is the audit reason of a request the policy allowed that failed: dns_error, tls_error or network_error.
func FileSHA256 ¶ added in v1.3.0
FileSHA256 is the hex SHA-256 of a file's contents.
func HostPort ¶
HostPort is u's lowercased host with its port, the scheme's default (https 443, http 80) when it has none: the destination an audit row names.
func IsNativeFailure ¶ added in v1.3.0
IsNativeFailure reports whether err means the plugin misbehaved (exited, broke the ABI or timed out), as opposed to answering with an error.
func LibraryName ¶ added in v1.3.0
func LibraryName() string
LibraryName is the file a native plugin's shared library has in its directory on this platform.
func PlatformKey ¶ added in v1.3.0
func PlatformKey() string
PlatformKey is this build's artifact key.
func QuestionBytes ¶
QuestionBytes is the size of the questions' text: instructions, values and descriptions.
func ScrubPaths ¶
ScrubPaths replaces absolute paths in s with "<path>".
func ServeNative ¶ added in v1.3.0
ServeNative is `godwit plugin-host`. Exit codes: 3 the file is not the one granted (nothing was loaded), 4 it did not load or init, 0 stdin closed.
func ServeNativeWith ¶ added in v1.3.0
func ServeNativeWith(args []string, stdin io.Reader, stdout, stderr io.Writer, open NativeOpener) int
ServeNativeWith is ServeNative with another loader (tests).
Types ¶
type ActionInfo ¶
type Answer ¶
Question and Answer are typed judge questions and answers, as llm.decide and Wit's classify_mail take and give them: the OpenAI Decisions API's shape (predicate, choice, score; a refusal answer), whatever the judge.
type Artifact ¶ added in v1.3.0
type Artifact struct {
URL string `json:"url"`
SHA256 string `json:"sha256"`
Size int64 `json:"size"`
}
Artifact is one released file: exactly Size bytes with this SHA-256.
type AttachmentMeta ¶
type CallScope ¶
type CallScope struct {
// contains filtered or unexported fields
}
CallScope is one top-level call. It is only valid on the owner goroutine, inside the Call that made it (including host functions JS invokes then).
func (*CallScope) Async ¶
Async returns a promise settled by fn, which runs on its own goroutine with the call's context. The result goes through rt.ToValue (json tags name struct fields); an error rejects with a plain Error whose message is redacted and path-scrubbed. The settlement is posted back to the owner goroutine tagged with this call; if the call has ended by then it is dropped and never runs.
func (*CallScope) Context ¶
Context ends with the call; synchronous host work should honour it, since Interrupt cannot stop a running Go function.
func (*CallScope) Invocation ¶
func (c *CallScope) Invocation() Invocation
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is ctx.net.fetch's HTTP client. It resolves names itself and dials only addresses it has checked (no DNS rebinding between check and connect), never uses a proxy, and re-checks every redirect.
func NewClient ¶
func NewClient(opts NetOptions) *Client
func (*Client) Do ¶
func (c *Client) Do(ctx context.Context, allowed []string, req FetchRequest) (FetchResponse, []Hop, error)
Do fetches req if its URL is allowed (host[:port], 443 by default) and returns the response, every hop for the audit (none only for an unparseable URL), and an error; a policy refusal or the timeout is a *NetError. No partial body is ever returned.
type Compiler ¶
type Compiler interface {
// Key identifies the compiler version and options: builds cached under
// another key are not reused.
Key() string
Compile(dir, main string) ([]byte, error)
}
Compiler turns a snapshot into the script the plugin VM runs.
var ESBuild Compiler = esbuildCompiler{}
ESBuild bundles TypeScript or JavaScript with esbuild.
type ConfigField ¶
type ConfigField struct {
Key string `json:"key"`
Type string `json:"type"`
Label Text `json:"label"`
Options []Option `json:"options,omitempty"`
AllowCustom bool `json:"allowCustom,omitempty"`
Required bool `json:"required,omitempty"`
Default json.RawMessage `json:"default,omitempty"`
When *When `json:"when,omitempty"`
}
ConfigField is one setting the user fills in. Type is text, secret, number, boolean or select. A secret has no default and is stored in the keychain.
func (ConfigField) Accepts ¶
func (f ConfigField) Accepts(v json.RawMessage) bool
Accepts reports whether v is a value f can hold (not for a secret).
type ConfigSnapshot ¶
ConfigSnapshot is a plugin's configuration at one config version; Err is why it could not be read (ctx.config then throws). Never changed once made.
type DraftInput ¶
type DraftUpdate ¶
type DraftUpdate struct {
DraftID int64 `json:"draftId"`
Revision int64 `json:"revision"`
HTML string `json:"html"`
}
DraftUpdate replaces a draft's body if the draft is still at Revision.
type FetchRequest ¶
type FetchResponse ¶
type Hop ¶
type Hop struct{ Dest, Decision, Reason string }
Hop is one request of a fetch, the first or a redirect: its host:port and its outcome. Decision is "allow" (answered, or redirected onward), "deny" (refused by the policy; Reason is the NetError code) or "error" (the policy allowed it and it failed; Reason is dns_error, network_error, tls_error, timeout or cancelled).
type Host ¶
type Host interface {
StorageGet(ctx context.Context, key string) (string, bool, error)
StorageSet(ctx context.Context, key, value string) error
StorageDelete(ctx context.Context, key string) error
MailGet(ctx context.Context, id int64) (MailMessage, error)
MailSearch(ctx context.Context, q string, limit int) ([]MailSummary, error)
MailSetFlags(ctx context.Context, ids []int64, add, remove []string) error
MailMove(ctx context.Context, ids []int64, folderID int64) error
MailCreateDraft(ctx context.Context, d DraftInput) (int64, error)
MailUpdateDraft(ctx context.Context, u DraftUpdate) (int64, error)
LLMComplete(ctx context.Context, prompt string) (string, error)
LLMDecide(ctx context.Context, input string, qs []Question) ([]Answer, error)
Fetch(ctx context.Context, inv Invocation, req FetchRequest) (FetchResponse, error)
AuditEgress(ctx context.Context, inv Invocation, dest, decision, reason string) error
}
Host is what the core gives a plugin's ctx. Permissions are checked before any of it is called. It has no way to send mail, and must never get one.
type Invocation ¶
type Invocation struct {
ID string
Kind InvocationKind
Write bool
EgressHosts []string
// Unapproved: the call needed an egress approval it did not get, so it
// has no hosts; a fetch to a declared host is denied as approval_required.
Unapproved bool
// Approved: the user approved this call's egress (its hosts were listed).
// An action or tool call without it is checked again as it fetches.
Approved bool
// Config is the call's ctx.config, taken when the host admitted the call
// (before it waits for the VM); nil makes ctx.config throw.
Config *ConfigSnapshot
}
Invocation is what the host allows one top-level call into a plugin: whether it may write mail, and the hosts it may fetch from (none: no egress). What the plugin declared when registering does not widen it.
type InvocationKind ¶
type InvocationKind string
const ( KindInit InvocationKind = "init" KindHook InvocationKind = "hook" KindBeforeSend InvocationKind = "beforeSend" KindAction InvocationKind = "action" KindCard InvocationKind = "card" KindTool InvocationKind = "tool" // KindTranslate translates mail the user chose to translate with this // plugin: like a hook it gets every declared host without asking each // time (docs/superpowers/specs/2026-10-14-native-plugins-design.md 2.7). KindTranslate InvocationKind = "translate" )
type Limits ¶ added in v1.3.0
type Limits struct{ File, Total int64 }
Limits caps a snapshot: each file, and all of them together, in bytes.
type MailMessage ¶
type MailMessage struct {
ID int64 `json:"id"`
Subject string `json:"subject"`
From string `json:"from"`
To []string `json:"to"`
Cc []string `json:"cc"`
Date time.Time `json:"date"`
Text string `json:"text"`
HTML string `json:"html"`
Truncated bool `json:"truncated"`
Attachments []AttachmentMeta `json:"attachments"`
}
MailMessage is a message as a plugin sees it. Text and HTML are cut to the host's limit, with Truncated set.
type MailSummary ¶
type Manifest ¶
type Manifest struct {
Name string `json:"name"`
Version string `json:"version"`
Description Text `json:"description"` // one line, shown under the name in settings
Main string `json:"main,omitempty"`
Native *NativeSpec `json:"native,omitempty"`
Capabilities []string `json:"capabilities,omitempty"` // what it provides to Godwit's own features
Permissions Permissions `json:"permissions"`
Config []ConfigField `json:"config"`
}
Manifest is a plugin's plugin.json (spec 5.3–5.4). A script plugin has Main and Permissions; a native one (docs/superpowers/specs/2026-10-14-native-plugins-design.md) has Native instead, and its shared library is LibraryName() beside plugin.json.
func ParseManifest ¶
ParseManifest parses and strictly validates plugin.json of the plugin installed in the directory dirName. A manifest that fails is not loaded.
func (Manifest) IsNative ¶ added in v1.3.0
IsNative reports whether m is a native (shared library) plugin.
func (Manifest) PermissionHash ¶
PermissionHash identifies what the user granted: it changes when the mail, net or llm permissions change, and not with their order, case, a ":443" or the config.
type NativeCall ¶ added in v1.3.0
NativeCall calls a loaded library: it returns the plugin's response envelope as is; an error is a failure below the envelope.
type NativeError ¶ added in v1.3.0
type NativeError struct {
Code string `json:"code"`
Message string `json:"message"`
Retryable bool `json:"retryable,omitempty"`
}
NativeError is a native plugin's own error envelope: its answer, not a failure.
func (*NativeError) Error ¶ added in v1.3.0
func (e *NativeError) Error() string
type NativeOpener ¶ added in v1.3.0
type NativeOpener func(path string, hostABI uint32) (NativeCall, error)
NativeOpener loads the library at path, speaking hostABI.
func FakeNativeOpener ¶ added in v1.3.0
func FakeNativeOpener(stderr io.Writer) NativeOpener
FakeNativeOpener is a NativeOpener for tests that loads nothing: the "library" file is JSON {"describe": {...}, "initFail": bool, "echoStderr": "...", "record": "<path>", "describeSleepMs": n, "recordEnv": bool, "source": "en", "translateWrongCount": bool, "translateError": "<code>"}. initFail writes echoStderr and fails init; describe answers after describeSleepMs. translate answers "[<target>] <text>" per text from source (default "en"), one text short with translateWrongCount, or the error envelope translateError; with record each request is appended to record + ".translate", and recordEnv adds the environment to configure's record. Methods: describe, configure (writes its request to record, if set), translate (echoes the texts, source "en"), fail (a rate_limited envelope), probe.sleep {"ms"} and probe.crash (writes echoStderr, exits 2).
type NativeOptions ¶ added in v1.3.0
type NativeOptions struct {
Command []string
Env []string
Library, SHA256 string
Timeout time.Duration
Redact func(string) string
OnStart func(ctx context.Context, call func(ctx context.Context, method string, params any) (json.RawMessage, error)) error
Idle time.Duration
}
NativeOptions start a plugin's process: Command then --library Library --sha256 SHA256, in the environment Env alone. Timeout 0 is 60 s; Redact nil leaves error text as it is. OnStart, if set, runs once per new process before any call reaches it (calls made meanwhile wait); its error fails the call that started the process, which is then ended. Idle, if set, ends a process no call has used for that long; the next call starts a new one.
type NativeProcess ¶ added in v1.3.0
type NativeProcess struct {
// contains filtered or unexported fields
}
func NewNativeProcess ¶ added in v1.3.0
func NewNativeProcess(o NativeOptions) *NativeProcess
NewNativeProcess returns the plugin's process handle; nothing starts until the first Call.
func (*NativeProcess) Call ¶ added in v1.3.0
func (n *NativeProcess) Call(ctx context.Context, method string, params any) (json.RawMessage, error)
Call runs method with params (marshalled to JSON) and returns the result. A plugin's error envelope is a *NativeError; see IsNativeFailure for the rest.
func (*NativeProcess) Close ¶ added in v1.3.0
func (n *NativeProcess) Close()
Close ends the process: stdin first, then after nativeGrace the process group. Calls after it return ErrClosed.
type NativeSpec ¶ added in v1.3.0
type NativeSpec struct {
ABI uint32 `json:"abi"`
}
NativeSpec marks a native plugin: the C ABI version its library exports.
type NetError ¶
type NetError struct{ Reason, Host string }
NetError is a fetch the policy refused. Reason is a stable code: host_not_allowed, scheme, ip_literal, userinfo, private_address, too_many_redirects, too_large or timeout.
type NetOptions ¶
type NetOptions struct {
Resolver interface {
LookupIPAddr(ctx context.Context, host string) ([]net.IPAddr, error)
}
Dial func(ctx context.Context, network, addr string) (net.Conn, error)
AllowHTTP, AllowLoopback bool
MaxBody int64 // response body; 0 = MaxFetchResponse
Timeout time.Duration // whole call, redirects and body included; 0 = FetchTimeout
UserAgent string // "Godwit-Plugin/<version>"
// contains filtered or unexported fields
}
NetOptions configures a Client. Zero values are the real network and the spec's limits; AllowHTTP and AllowLoopback exist for tests only.
type PermissionError ¶
type PermissionError struct{ Perm string }
PermissionError is a ctx API call the manifest or the invocation does not allow. Its message names only the permission.
func (*PermissionError) Error ¶
func (e *PermissionError) Error() string
func (*PermissionError) Is ¶
func (e *PermissionError) Is(target error) bool
type Permissions ¶
type Permissions struct {
Mail []string `json:"mail"`
Net []string `json:"net"`
LLM bool `json:"llm"`
}
Permissions: Mail holds "read" and/or "write" (there is no send); Net the hosts, each "host" or "host:port", lowercased and without ":443" after ParseManifest.
type Plugin ¶
type Plugin struct {
Name string
// contains filtered or unexported fields
}
Plugin is a loaded plugin: its VM and what it registered during initialization. Registrations never change after Load.
func Load ¶
Load builds the ctx object and runs the plugin's initialization in an init invocation (no writes, no egress, cfg as ctx.config), recording what it registers.
func (*Plugin) Actions ¶
func (p *Plugin) Actions() []ActionInfo
func (*Plugin) Card ¶
func (p *Plugin) Card(ctx context.Context, inv Invocation, m MailMessage) (res any, matched bool, err error)
Card runs the card's match(m) and, if its result is truthy, render(m), both under inv, and returns render's result; matched is false when match was not truthy. ctx bounds both calls together.
func (*Plugin) Emit ¶
Emit runs the plugin's handler for event with args (plain JSON-like Go data) as one top-level call under inv, awaiting it if it is async.
func (*Plugin) EmitResult ¶
func (p *Plugin) EmitResult(ctx context.Context, inv Invocation, event string, args ...any) (any, error)
EmitResult is Emit that returns the handler's (awaited) result as plain JSON data.
func (*Plugin) RunAction ¶
RunAction runs the registered action id on target under inv and returns its (awaited) result as plain JSON data.
func (*Plugin) RunTool ¶
RunTool runs the registered tool name with args under inv and returns its (awaited) result as plain JSON data.
type Question ¶
Question and Answer are typed judge questions and answers, as llm.decide and Wit's classify_mail take and give them: the OpenAI Decisions API's shape (predicate, choice, score; a refusal answer), whatever the judge.
type Registry ¶ added in v1.3.0
type Registry struct {
Schema int `json:"schema"`
Updated time.Time `json:"updated"`
Plugins []RegistryPlugin `json:"plugins"`
}
func CheckRegistry ¶ added in v1.3.0
CheckRegistry is ParseRegistry for publishing: an unknown field anywhere or a release this build cannot read is an error.
func ParseRegistry ¶ added in v1.3.0
ParseRegistry parses and validates a registry.json as this build reads it. The format grows without a new schema: fields this build does not know are ignored outside releases, and a release it cannot read whole (new fields, a new capability, or invalid) goes to Unsupported instead of failing the registry, so older clients keep the rest of it, revocations included.
type RegistryPlugin ¶ added in v1.3.0
type RegistryPlugin struct {
Name string `json:"name"`
Title Text `json:"title"`
Summary Text `json:"summary"`
Homepage string `json:"homepage,omitempty"`
Releases []RegistryRelease `json:"releases"`
// Unsupported are the releases this build cannot read, with only their
// Version and MinGodwit: Pick's reason when none of Releases fits.
Unsupported []RegistryRelease `json:"-"`
}
func (RegistryPlugin) Pick ¶ added in v1.3.0
func (p RegistryPlugin) Pick(platform, appVersion string) (RegistryRelease, Artifact, string)
Pick returns the newest release this build can install on platform, and its file; reason, when there is none, is why the newest release does not fit: "abi", "platform", "godwit:<minGodwit>", or "unsupported" for one this build cannot read. appVersion "" or "dev" (a development build) takes any minGodwit.
type RegistryRelease ¶ added in v1.3.0
type Text ¶
Text is a label: a plain string, or {"default": ..., "<lang>": ...}.
func (Text) For ¶
For returns the text for lang, then for its base language ("de" for "de-AT"), then a matching script/region, then the default.
func (Text) MarshalJSON ¶
func (*Text) UnmarshalJSON ¶
type VM ¶
type VM struct {
// contains filtered or unexported fields
}
VM is one plugin's goja runtime. Every touch of the runtime happens on its owner goroutine: top-level calls are queued and run one at a time there, and async host work posts its completion back to it. Nothing returned by Call is a goja.Value.
func (*VM) Call ¶
func (v *VM) Call(ctx context.Context, inv Invocation, fn func(c *CallScope) (any, error)) (any, error)
Call runs fn on the owner goroutine as one top-level call, after any call already running or queued. If fn returns a goja.Value it is awaited when it is a promise (pumping only this call's async completions) and exported as plain JSON data (map[string]any, []any, float64, string, bool, nil; at most MaxResultBytes, else ErrTooLarge). Go results are normalized the same way through encoding/json; one holding a goja.Value, func or channel is an error. The call ends at settlement, ctx's end, Close (ErrClosed), the kind's time limit (ErrTimeout) or the watchdog (ErrMemoryLimit); JS still running is interrupted.
func (*VM) Close ¶
func (v *VM) Close()
Close refuses new calls (ErrClosed), cancels the running one and waits for it, drops pending completions and stops the owner goroutine.
func (*VM) HostFunc ¶
func (v *VM) HostFunc(name string, fn func(c *CallScope, call goja.FunctionCall) goja.Value) goja.Value
HostFunc wraps a host function for JS. Call it on the owner goroutine (from inside a Call or Init). fn gets the scope of the call JS invoked it in. To throw, fn panics; JS always gets a plain Error (no Go value behind it, so e.value is undefined) whose message went through Redact and path scrubbing:
- an error: "<name>: " + its message
- a goja error value (rt.NewTypeError(...), ...): its message, keeping TypeError as TypeError
- anything else, Go runtime errors included: "<name>: internal error"
Interrupts and stack overflows pass through untouched.
type VMOptions ¶
VMOptions: a nil Clock is the real clock, a nil Watchdog the default one, a nil Redact the identity.
type Watchdog ¶
Watchdog is the soft heap limit: goja has no per-runtime memory cap, so while a call runs it samples a process-wide meter and interrupts that call with ErrMemoryLimit when the meter has grown by more than Threshold since the call began. ponytail: process-wide, so it cannot tell the plugin's allocations from the app's; a child process with GOMEMLIMIT is the hard cap if one is ever needed.
Zero fields take defaults: Meter reads runtime.MemStats.HeapAlloc, Clock is the VM's, Interval 10 ms, Threshold 256 MB.
type When ¶
type When struct {
Key string `json:"key"`
Equals json.RawMessage `json:"equals,omitempty"`
NotEquals json.RawMessage `json:"notEquals,omitempty"`
}
When shows a field only if the earlier field Key equals (or does not equal) a value of that field's type.