engine

package
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 20, 2026 License: MIT Imports: 30 Imported by: 0

Documentation

Overview

Package engine is the pure-Go port of ant's "Silver" JavaScript engine.

This file ports ant's NaN-boxed value representation (include/internal.h, src/ant.c). A Value is a 64-bit IEEE-754 double whose "not a number" bit patterns are reused to smuggle tagged, non-numeric values.

Layout (identical to ant):

1111 1111 1111 TTTTT DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
[-- prefix ---][type][--------------- 47-bit data --------------------]

Any 64-bit pattern strictly greater than NANBOX_PREFIX (which is the bit pattern of -Infinity) is a tagged value; anything <= it is an ordinary double, so numeric math is free.

DIVERGENCE FROM ant: in ant the 47-bit data field of a heap-resident type (T_OBJ/T_STR/…) holds a raw C pointer. In goant it instead holds a 32-bit handle into a chunked, non-moving pool (see pools.go), keeping Values pointer-free from the Go GC's perspective — a hard requirement for the JIT (native code may hold/copy Values freely) and for our own ported GC.

Index

Constants

View Source
const (
	PromisePending   = iota // 0
	PromiseFulfilled        // 1
	PromiseRejected         // 2
)

Promise settlement states, matching the internal encoding.

View Source
const (
	OpfJitEligible uint32 = 1 << iota
	OpfJitInlineable
	OpfJitNeedsArgsBuf
	OpfJitNeedsCloseUpval
	OpfJitLocalNumericBailout
	OpfJitNeedsBailout
	OpfJitNeedsIcEpoch
	OpfJitNeedsIncLocal
	OpfJitBranch32
	OpfJitOsrBackedge
	OpfJitBranch8
	OpfJitNeedsTcoArgs
	OpfJitNeedsIterRoots
)

Per-opcode JIT metadata flags (ant OP_FLAG / SV_OPF_*).

Variables

View Source
var ErrHostClosed = errors.New("goant: runtime is closed")

ErrHostClosed is what Post reports once the Runtime has been closed: a goroutine finishing after shutdown learns its answer went nowhere, rather than queueing onto a loop that will never run again.

View Source
var ErrNotImplemented = errors.New("goant: not implemented yet")

ErrNotImplemented marks engine surface that is scaffolded but not yet ported.

View Source
var ErrTerminated = errors.New("goant: execution terminated")

ErrTerminated reports that execution was stopped by Interrupt rather than finishing or throwing. Hosts distinguish it with errors.Is.

Functions

func DisasmOnly

func DisasmOnly(filename, src string) error

DisasmOnly compiles src and writes a bytecode listing to stdout (goant --disasm).

func ICMissReasons

func ICMissReasons() (hit, empty, room, full uint64)

ICMissReasons reports the breakdown: hit, empty, room-left, full.

func JITBailStats

func JITBailStats() uint64

JITBailStats reports frames compiled code handed back to the interpreter partway through. See jitbail.go.

func JITCallStats

func JITCallStats() (fast, slow uint64)

JITCallStats reports calls made from compiled code, by whether the call site made them itself or went through the runtime.

func JITCodeMemory

func JITCodeMemory() (blocks, bytes, peak int64)

JITStats reports frame entries served by compiled code, by compiled code that declined its arguments, and by the interpreter for want of any compiled form.

Entries the runtime made. A compiled call site entering a compiled function does not pass through here at all, which is the point of it — JITCallStats is where those are counted, and on a call-heavy program they are most of them. JITCodeMemory reports the executable memory the tier holds: how many blocks are mapped, how many bytes they total, and the high-water mark.

This is the number a long-running host has to watch, and the reason it is public rather than diagnostic. Compiled code is NEVER RELEASED — a block has to outlive every entry into it, and nothing here can prove an entry has ended, so a suspended generator or an outer frame of a recursive function would be left holding freed executable memory. A process running one script exits before that matters; one running thousands of different flows over days accumulates a block per hot function, plus one more each time a function is recompiled.

"Never freed" is justified. "Unbounded and unmeasured" is not, which is what this closes: a host can sample it, alarm on it, and recycle a Runtime before it becomes a problem.

func JITElementStats

func JITElementStats() (hit, miss uint64)

JITElementStats is the same for `a[i]`, which has no cache site and a guard chain of its own.

func JITElementStoreStats

func JITElementStoreStats() (hit, miss uint64)

JITElementStoreStats is JITElementStats for `a[i] = v`.

func JITGlobalStats

func JITGlobalStats() (hit, miss uint64)

JITGlobalStats is the same for a global read, which is the same cache over a receiver compiled code fetches rather than one it was handed.

func JITIsEnabled

func JITIsEnabled() bool

JITIsEnabled reports the process-wide DEFAULT for new Runtimes.

Exported so a harness can say which tier it measured rather than assume it — GOANT_JIT=0 used to read as ON, and weeks of "the tier changes nothing" were measured that way. A run that cannot state what it ran is not a measurement. What a particular Runtime is doing is Runtime.JITEnabled.

func JITNarrowStats

func JITNarrowStats() uint64

JITNarrowStats reports reads the emitted probe declined that the cache could answer anyway — the gap between what icWay.hit accepts and what the guard chain in machine code accepts. Every one is a helper round trip that a wider guard would remove.

func JITOperatorStats

func JITOperatorStats() (fast, slow uint64)

JITOperatorStats reports operators compiled without a known operand type, by whether the guard let them take the machine instruction or sent them to the runtime.

func JITPropertyStats

func JITPropertyStats() (hit, miss uint64)

JITPropertyStats reports compiled property reads served by the emitted inline-cache probe, and those that fell through to the runtime.

func JITSetEnabled

func JITSetEnabled(on bool) bool

JITSetEnabled changes the default for Runtimes created AFTER it returns, and returns what the default was.

For a harness that needs both tiers in one process — computing an answer key with the interpreter before measuring the compiler against it, which is the only way to have an oracle that is not the thing under test. A host wanting to control one Runtime should use Runtime.SetJITEnabled, which is per-Runtime and takes effect immediately.

func JITStats

func JITStats() (compiled, declined, interpreted uint64)

func JITStoreStats

func JITStoreStats() (hit, miss uint64)

JITStoreStats is JITPropertyStats for the other direction. Counted apart because the two probes decline for different reasons and a combined figure would hide whichever of them is doing worse.

func ParseFunctionParameters

func ParseFunctionParameters(prefix, params string) error

ParseFunctionParameters checks the parameter text handed to the dynamic Function constructor. CreateDynamicFunction parses P on its own goal symbol (FormalParameters) BEFORE assembling the function's source text, so a `-->` there is a SyntaxError even though the assembled source would put it right after `anonymous(`, where Annex B would take it for a comment.

func ParseOnly

func ParseOnly(filename, src string) error

ParseOnly parses src and reports any syntax error (goant --parse).

Types

type BlobResolver

type BlobResolver func(ref string) ([]byte, error)

BlobResolver returns the bytes behind a content-addressed reference. An error stops the script the way a heap-limit breach does — the read cannot produce a value, and carrying on would hand the script an envelope where it expected data, which surfaces as a type error somewhere unrelated.

type CompileError

type CompileError struct{ Msg string }

CompileError is a compile-time (semantic) error.

func (*CompileError) Error

func (e *CompileError) Error() string

type ExitError

type ExitError struct{ Code int }

ExitError signals a process.exit(code) request bubbling to the CLI/harness.

func (*ExitError) Error

func (e *ExitError) Error() string

type GlobalDeclError

type GlobalDeclError struct{ Msg string }

GlobalDeclError is a TypeError raised by GlobalDeclarationInstantiation before a Script runs: one of its top-level declarations names a binding the global environment cannot create (a non-configurable property, or any new name on a non-extensible global). It is returned from Compile because it is decided there, but it is a runtime TypeError, not an early SyntaxError.

func (*GlobalDeclError) Error

func (e *GlobalDeclError) Error() string

type Handle

type Handle uint32

Handle is a 32-bit index into a pool. Handle 0 is reserved as "null handle"; real cells start at 1 so a zeroed Value payload never aliases a live cell.

type HostFunc

type HostFunc = func(rt *Runtime, this Value, args []Value) (Value, *ThrowError)

HostFunc is the signature of a Go function callable from JavaScript. It is the same signature the built-ins use, so a host function is not a second class of callable — it takes the same fast path.

type Invocation

type Invocation struct {
	// contains filtered or unexported fields
}

Invocation is one script run with its own global state. Begin one, run whatever the host needs, then End it; the globals the run installed are discarded and the next Invocation starts clean.

Invocations do not nest usefully and are not safe to interleave: a Runtime runs one script at a time, which is the same constraint every other engine places on an isolate.

func (*Invocation) Dirty

func (inv *Invocation) Dirty() bool

Dirty reports whether this invocation modified state that predates it, which means the next run on this Runtime would inherit the change.

A host pooling Runtimes must not reuse one whose last invocation reported true. Discarding it costs a fresh Runtime (~700 µs) on the rare run that monkey-patches a builtin, and nothing at all on every run that does not.

func (*Invocation) End

func (inv *Invocation) End()

End discards the invocation's globals and restores the shared ones. Calling it twice is harmless.

func (*Invocation) Global

func (inv *Invocation) Global() Value

Global returns this invocation's global object, for a host installing per-run values on it.

func (*Invocation) Release

func (inv *Invocation) Release() bool

Release ends the invocation and frees everything it allocated, in one step and without tracing anything.

This is region reclamation, and it fits this workload exactly: a run allocates a message graph, produces a result, and every object it made dies together. There is nothing to mark, no roots to enumerate, no write barriers — the allocator simply rewinds.

It is sound only because of the dirty check. If the run never wrote to an object that predates it, then nothing outside the region can point into it, so the whole region is unreachable by construction. A run that did write to shared state cannot be released, and Release reports false without freeing — the caller should discard the Runtime instead.

EVERY Value created during the invocation becomes invalid, including the script's result. A caller must extract what it needs — serialise the result to bytes — BEFORE calling this. Reading a Value afterwards reads a recycled cell, which is the one way to get a wrong answer out of this API.

type JITHelperCount

type JITHelperCount struct {
	Name  string
	Count uint64
}

JITHelperCount is one reason compiled code left, and how often it left for it.

func JITHelperStats

func JITHelperStats() []JITHelperCount

JITHelperStats reports calls out of compiled code by which helper was wanted, heaviest first.

This is the measurement that decides what is worth speculating on, and it is the one the tier has been improved by twice: what a compiled function cannot do itself, it leaves to say so, and the leaving is most of the cost. Emitting `x == null` rather than helping it was 18% of Octane, and nothing but this count says which of sixty helpers is the next one of those.

Deliberately not the static histogram of what functions contain. That has pointed at the wrong work every time it has been consulted, because a program's time is not spread evenly over its opcodes.

type JITRefusalWeight

type JITRefusalWeight struct {
	Reason   string
	Entries  uint64
	Unblocks uint64
	Insns    uint64
	Funcs    int
}

JITRefusalWeight is one refusal reason and what it costs.

Insns is the one to read: how many bytecode instructions the interpreter executed inside functions refused for this reason. Entries counts frame entries, which flatters a function called often over one that runs long, and Unblocks is how much of Entries this reason alone would release.

func JITRefusalWeights

func JITRefusalWeights() []JITRefusalWeight

JITRefusalWeights reports the refusal reasons by what they would unblock, heaviest first.

type ModuleResolverFunc added in v0.2.0

type ModuleResolverFunc func(specifier, referrer string) (source, path string, err error)

ModuleResolverFunc is how a host answers "where does this specifier live".

It is given the specifier exactly as written and the path of the module doing the importing (empty at an entry point), and returns the source and a path. The path is the registry key: two importers that resolve to the same path get the same module instance, which is what makes a shared dependency shared. Returning empty source means "read that path from disk", so a resolver can map bare specifiers onto real files without also taking over reading them.

type Node

type Node struct {
	Kind    NodeKind
	Op      Token
	Flags   uint32
	VarKind VarKind

	Str string // identifier name, cooked string literal, cooked template seg
	Aux string // raw template segment / regexp flags

	Num float64

	Left  *Node
	Right *Node
	Cond  *Node
	Body  *Node
	Args  []*Node

	CatchParam  *Node
	CatchBody   *Node
	FinallyBody *Node

	Init   *Node
	Update *Node

	Line   uint32
	Col    uint32
	SrcOff uint32
	SrcEnd uint32
}

Node is a single AST node (ant struct sv_ast).

func Parse

func Parse(filename, src string) (*Node, error)

Parse tokenizes and parses src into an AST (N_PROGRAM root node).

type NodeKind

type NodeKind uint8

NodeKind enumerates AST node types (ant sv_node_type_t). Order is preserved.

const (
	NNumber NodeKind = iota
	NString
	NBigInt
	NBool
	NNull
	NUndef
	NThis
	NGlobalThis
	NTemplate
	NRegexp
	NIdent
	NBinary
	NUnary
	NUpdate
	NAssign
	NTernary
	NCall
	NNew
	NMember
	NOptional
	NArray
	NObject
	NProperty
	NSpread
	NSequence
	NArrow
	NYield
	NAwait
	NTypeof
	NDelete
	NVoid
	NTaggedTemplate
	NBlock
	NVar
	NVarDecl
	NIf
	NWhile
	NDoWhile
	NFor
	NForIn
	NForOf
	NForAwaitOf
	NReturn
	NBreak
	NContinue
	NThrow
	NTry
	NSwitch
	NCase
	NLabel
	NDebugger
	NEmpty
	NWith
	NFunc
	NClass
	NMethod
	NStaticBlock
	NArrayPat
	NObjectPat
	NRest
	NAssignPat
	NNewTarget
	NImport
	NImportDecl
	NImportSpec
	NExport
	NProgram
	NImportMeta // `import.meta` (module goal only)

)

type OpFormat

type OpFormat uint8

OpFormat classifies an opcode's inline operand encoding (ant OP_FMT).

const (
	FmtNone OpFormat = iota
	FmtU8
	FmtI8
	FmtU16
	FmtI16
	FmtU32
	FmtI32
	FmtAtom
	FmtAtomU8
	FmtLabel
	FmtLabel8
	FmtLoc
	FmtLoc8
	FmtLocAtom
	FmtArg
	FmtConst
	FmtConst8
	FmtNpop
	FmtVarRef
)

func (OpFormat) String

func (f OpFormat) String() string

type Opcode

type Opcode uint8

Opcode is a Silver bytecode operation (ant OP_DEF).

const (
	OpInvalid Opcode = iota
	OpConst
	OpConstI8
	OpConst8
	OpUndef
	OpNull
	OpTrue
	OpFalse
	OpThis
	OpGlobal
	OpObject
	OpPrivateToken
	OpArray
	OpSetBrand
	OpRegexp
	OpClosure
	OpPop
	OpDup
	OpDup2
	OpSwap
	OpRot3l
	OpRot3r
	OpNip
	OpNip2
	OpInsert2
	OpInsert3
	OpSwapUnder
	OpRot4Under
	OpGetLocal
	OpPutLocal
	OpSetLocal
	OpGetLocal8
	OpPutLocal8
	OpSetLocal8
	OpSetLocalUndef
	OpGetLocalChk
	OpPutLocalChk
	OpGetSlotRaw
	OpGetArg
	OpPutArg
	OpSetArg
	OpRest
	OpGetUpval
	OpPutUpval
	OpSetUpval
	OpCloseUpval
	OpGetGlobal
	OpGetGlobalUndef
	OpPutGlobal
	OpGetField
	OpGetField2
	OpPutField
	OpGetElem
	OpGetElem2
	OpPutElem
	OpDefineField
	OpGetLength
	OpGetFieldOpt
	OpGetElemOpt
	OpGetPrivate
	OpGetPrivateOpt
	OpPutPrivate
	OpDefPrivate
	OpHasPrivate
	OpGetSuper
	OpGetSuperVal
	OpPutSuperVal
	OpAdd
	OpSub
	OpMul
	OpDiv
	OpAddNum
	OpSubNum
	OpMulNum
	OpDivNum
	OpMod
	OpExp
	OpNeg
	OpUplus
	OpInc
	OpDec
	OpPostInc
	OpPostDec
	OpIncLocal
	OpDecLocal
	OpAddLocal
	OpStrAppendLocal
	OpStrAlcSnapshot
	OpStrFlushLocal
	OpEq
	OpNe
	OpSeq
	OpSne
	OpLt
	OpLe
	OpGt
	OpGe
	OpInstanceof
	OpIn
	OpIsNullish
	OpIsUndefOrNull
	OpBand
	OpBor
	OpBxor
	OpBnot
	OpShl
	OpShr
	OpUshr
	OpNot
	OpTypeof
	OpVoid
	OpDelete
	OpDeleteVar
	OpJmp
	OpJmpFalse
	OpJmpTrue
	OpJmpFalsePeek
	OpJmpTruePeek
	OpJmpNotNullish
	OpJmp8
	OpJmpFalse8
	OpJmpTrue8
	OpCall
	OpCallMethod
	OpCallIsProto
	OpCallArrayIncludes
	OpReLiteralExec
	OpStrReLiteralReplace
	OpReExecTruthy
	OpTailCall
	OpTailCallMethod
	OpNew
	OpApply
	OpSuperApply
	OpNewApply
	OpEval
	OpReturn
	OpReturnUndef
	OpReturnAsync
	OpCheckCtor
	OpCheckCtorRet
	OpHalt
	OpThrow
	OpThrowError
	OpTryPush
	OpTryPushFinally
	OpTryPop
	OpCatch
	OpFinally
	OpFinallyRet
	OpFinallyDiscard
	OpUnwindJmp
	OpNipCatch
	OpUsingPush
	OpUsingPushAsync
	OpDisposeResource
	OpDisposeResourceAsync
	OpUsingDispose
	OpUsingDisposeAsync
	OpUsingDisposeSuppressed
	OpUsingDisposeAsyncSuppressed
	OpForIn
	OpForOf
	OpForAwaitOf
	OpIterNext
	OpIterGetValue
	OpIterClose
	OpIterCall
	OpAwaitIterNext
	OpDestructureInit
	OpDestructureNext
	OpDestructureRest
	OpDestructureClose
	OpAwait
	OpYield
	OpYieldStarInit
	OpYieldStarNext
	OpYieldStarThrow
	OpYieldStarReturn
	OpSpread
	OpDefineMethod
	OpDefineMethodComp
	OpSetName
	OpSetNameComp
	OpSetProto
	OpSetHomeObj
	OpAppend
	OpCopyDataProps
	OpDefineClass
	OpDefineClassComp
	OpToObject
	OpToPropkey
	OpIsUndef
	OpIsNull
	OpImport
	OpImportSource
	OpImportSync
	OpImportDefault
	OpImportNamed
	OpExport
	OpExportAll
	OpEnterWith
	OpExitWith
	OpWithGetVar
	OpWithPutVar
	OpWithDelVar
	OpSpecialObj
	OpEmpty
	OpDebugger
	OpNop
	OpPutConst
	OpLabel
	OpLineNum
	OpColNum
	// OpChkCtor pops a class-heritage value and throws a TypeError unless it is
	// null or a constructor (ClassDefinitionEvaluation's IsConstructor check).
	OpChkCtor
	// OpChkProto pops a superclass's .prototype and throws a TypeError unless it
	// is an Object or null (the protoParent check).
	OpChkProto
	// OpImportDefer is `import defer * as ns`: the module is already linked, so
	// this only asks for its namespace WITHOUT evaluating it. What comes back is
	// the deferred namespace, which runs the module the first time it is asked
	// about a string key.
	OpImportDefer
	// OpImportDeferDyn is `import.defer(spec, options)`: like a dynamic import,
	// except that what the promise settles with is the deferred namespace and
	// only the module's asynchronous dependencies are evaluated.
	OpImportDeferDyn

	NumOpcodes = 218
)

func (Opcode) Flags

func (op Opcode) Flags() uint32

Flags returns the opcode's JIT metadata bitset.

func (Opcode) Format

func (op Opcode) Format() OpFormat

Format returns the operand encoding.

func (Opcode) Name

func (op Opcode) Name() string

Name returns the opcode mnemonic.

func (Opcode) Size

func (op Opcode) Size() int

Size returns the total instruction length in bytes (opcode + operands).

func (Opcode) StackEffect

func (op Opcode) StackEffect() (pop, push int)

StackEffect returns (popped, pushed) stack slot counts.

func (Opcode) String

func (op Opcode) String() string

type Runtime

type Runtime struct {
	// contains filtered or unexported fields
}

Runtime is a single JavaScript isolate — the Go analogue of ant's ant_t (include/internal.h struct ant_isolate_t). It owns the non-moving pools that back heap Values plus the interning tables and global state.

This struct grows phase by phase; Phase 0 establishes the pools and the public entry points. Phases 1–3 wire in the lexer/parser, object model, and interpreter.

func New

func New() *Runtime

New creates a fresh Runtime with empty pools and an initialized global object.

func (*Runtime) BeginInvocation

func (rt *Runtime) BeginInvocation() *Invocation

BeginInvocation starts a run with a fresh global object.

func (*Runtime) BigInt

func (rt *Runtime) BigInt(v Value) (*big.Int, bool)

BigInt returns a BigInt's value. The returned big.Int is a copy, so the caller may keep or modify it.

func (*Runtime) BlobResolveError

func (rt *Runtime) BlobResolveError() error

BlobResolveError returns the failure that stopped the last script, if it was stopped by a blob that could not be fetched.

func (*Runtime) BlobResolveFailed

func (rt *Runtime) BlobResolveFailed() bool

BlobResolveFailed reports that this Runtime was terminated because a lazily parsed envelope named a blob the resolver could not produce. The error itself is BlobResolveError.

It is reported rather than swallowed because the alternative is worse than a stopped script: the value would arrive as the raw envelope, and the failure would surface as a type error in the middle of someone's JavaScript with nothing pointing at the missing blob.

func (*Runtime) Bytes

func (rt *Runtime) Bytes(v Value) ([]byte, bool)

Bytes returns the bytes behind an ArrayBuffer or any typed-array view of one, without copying. ok is false for anything else, and for a detached buffer.

For a view the slice covers only that view's window. The bytes are live: a write through the returned slice is visible to the script.

func (*Runtime) Call

func (rt *Runtime) Call(fn, this Value, args []Value) (Value, error)

Call invokes fn with the given this-binding and arguments.

func (*Runtime) ClearInterrupt

func (rt *Runtime) ClearInterrupt()

ClearInterrupt cancels a pending or delivered interrupt, making the Runtime usable again. Call it only once the interrupted script has actually returned.

func (*Runtime) CloseHost added in v0.2.0

func (rt *Runtime) CloseHost()

CloseHost stops the queue accepting work and drops what it is holding. A later Post reports ErrHostClosed rather than queueing into a Runtime that will never run again.

func (*Runtime) Collect

func (rt *Runtime) Collect()

Collect runs a full mark-and-sweep immediately, whether or not automatic collection is enabled. Exposed for hosts that know they have just finished with a large working set, and used by the tests.

It is only safe at a point where the engine is not inside a native call; the interpreter's safepoints are such points, and so is a return to the host.

func (*Runtime) Compile

func (rt *Runtime) Compile(prog *Node, filename, source string) (*svFunc, error)

Compile compiles a parsed program to a bytecode function (script mode).

func (*Runtime) CompileEval

func (rt *Runtime) CompileEval(prog *Node, filename, source string) (*svFunc, error)

CompileEval compiles an eval body: `var` bindings stay frame-local.

func (*Runtime) CompileModule

func (rt *Runtime) CompileModule(prog *Node, filename, source string) (*svFunc, error)

CompileModule compiles a Module: it is strict, its top-level `this` is undefined, and its import/export declarations are handled (imports are not yet linked, so a module with static imports is out of scope here).

func (*Runtime) CompileScript

func (rt *Runtime) CompileScript(filename, src string) (*Script, error)

CompileScript parses and compiles src without running it.

func (*Runtime) Construct

func (rt *Runtime) Construct(fn Value, args []Value) (Value, error)

Construct invokes fn as a constructor — `new fn(args...)`.

func (*Runtime) DateMillis

func (rt *Runtime) DateMillis(v Value) (ms float64, ok bool)

DateMillis returns a Date's time value in milliseconds since the epoch. ok is false if v is not a Date; the value is NaN for an invalid one.

func (*Runtime) DeleteProp

func (rt *Runtime) DeleteProp(obj Value, name string) (bool, error)

DeleteProp removes obj.name, returning whether it is gone afterwards — the `delete` operator, which reports false for a non-configurable property rather than throwing (outside strict mode).

func (*Runtime) Disassemble

func (rt *Runtime) Disassemble(fn *svFunc) string

Disassemble renders fn's bytecode as a listing.

func (*Runtime) DrainJobs

func (rt *Runtime) DrainJobs()

DrainJobs runs the microtask queue to completion.

func (*Runtime) EnableAgents

func (rt *Runtime) EnableAgents()

EnableAgents installs $262.agent on this Runtime, letting a script start other agents and share memory with them.

It is off by default and a host must ask, because starting an agent is a capability, not a language feature: each one is a goroutine with a realm of its own, and a script that could start them at will could exhaust the process. The conformance runner turns it on; an embedder running untrusted scripts should not.

func (*Runtime) EnableHostAPI

func (rt *Runtime) EnableHostAPI()

EnableHostAPI installs the Test262 host object $262 on this Runtime's global, along with the two global capabilities it exposes — evalScript and createRealm.

It is off by default. A conformance runner turns it on; an embedder running untrusted scripts must not, because $262 is a set of capabilities rather than a set of language features:

  • detachArrayBuffer invalidates an ArrayBuffer's bytes, which JavaScript itself can only do by transferring them away;
  • createRealm allocates a whole realm per call, with nothing bounding how many;
  • evalScript compiles a Script into this realm, whose top-level var and function declarations become NON-configurable global properties;
  • reading IsHTMLDDA disables the compiled tier for the realm, for as long as that realm lives.

Calling it twice is harmless: the second call replaces the same properties with equivalent ones. See EnableAgents for $262.agent, which is a separate grant.

func (*Runtime) GCCycles

func (rt *Runtime) GCCycles() int

GCCycles reports how many collections have completed. For tests.

func (*Runtime) GetIndex

func (rt *Runtime) GetIndex(obj Value, i int) (Value, error)

GetIndex reads obj[i], honouring getters, the prototype chain and exotic index behaviour (arrays, strings, typed arrays).

func (*Runtime) GetProp

func (rt *Runtime) GetProp(obj Value, name string) (Value, error)

GetProp reads obj.name, running any getter and honouring the prototype chain. A thrown JS exception is returned as an error carrying the value.

func (*Runtime) Global

func (rt *Runtime) Global() Value

Global returns the global object (globalThis).

func (*Runtime) HasProp

func (rt *Runtime) HasProp(obj Value, name string) (bool, error)

HasProp reports whether obj.name resolves, own or inherited — the `in` operator. A Proxy's has trap can throw, so this can fail.

func (*Runtime) HeapLimit

func (rt *Runtime) HeapLimit() uint64

HeapLimit reports the current budget, 0 if none.

func (*Runtime) HeapLimitExceeded

func (rt *Runtime) HeapLimitExceeded() bool

HeapLimitExceeded reports that this Runtime was terminated for exceeding its heap budget rather than by a host Interrupt. The distinction is what lets a caller report "this script needed more memory than it is allowed" instead of "this script was cancelled", which are different problems with different fixes.

func (*Runtime) HeapReserved

func (rt *Runtime) HeapReserved() (cells int, bytes uint64)

HeapReserved reports the high-water mark instead of the current occupancy: the cell storage the pools hold, whether or not anything is in it.

It is a different question from HeapUsage and for this engine the more important one, because THE CELL POOLS NEVER SHRINK. A chunk allocated at the peak is held for the life of the Runtime — free and truncate both keep it — so what a host pays resident is set by the worst moment the program ever had and not by what it is holding now. Two runs with identical live sets can differ by a factor if one let more garbage pile up before collecting, and only this number says so.

Counted from the chunk vectors, which is why it survives region reclamation while a watermark handle does not: Invocation.Release rewinds the allocator but keeps the chunks, deliberately, so the next invocation allocates into memory that is already there. Chunk granularity is 4096 cells.

func (*Runtime) HeapUsage

func (rt *Runtime) HeapUsage() (cells int, bytes uint64)

HeapUsage reports this runtime's own allocation, by live cell count and an estimate of the bytes those cells occupy.

This is the runtime's occupancy, not the process's: an embedder running many runtimes needs to know which one is growing, and Go's process-wide MemStats cannot tell it. The byte figure is cells times their element size and so excludes payloads hanging off them (string bytes, array backing stores), which makes it a floor rather than a total.

It is a meaningful number to retire a pooled runtime on, because there is currently no collector: cells are reclaimed only when the whole Runtime is dropped and Go collects the pools (PLAN.md Phase 7). Until that lands, this count only goes up over a runtime's life, so an embedder that reuses runtimes must watch it.

func (*Runtime) HoldValue added in v0.2.0

func (rt *Runtime) HoldValue(v Value) (release func())

HoldValue roots v until the returned function is called.

A promise handed to JavaScript and then dropped by it — `void fetch(url)` — has no reference the collector can find, and the answer still has to arrive somewhere. This is how the host says "I am holding this", and it is a reference count rather than a flag because the same value may be held twice.

Call it on the Runtime's goroutine, like everything else that touches the heap. The release function has the same rule; post it if you are elsewhere.

func (*Runtime) HostPending added in v0.2.0

func (rt *Runtime) HostPending() bool

HostPending reports whether anything outside JavaScript is still expected: a posted job not yet run, or an operation that has taken a ref.

func (*Runtime) HostRef added in v0.2.0

func (rt *Runtime) HostRef()

HostRef records that a host operation is in flight, so the loop stays alive waiting for it. Every HostRef must be matched by exactly one HostUnref, including on the failure path — an unbalanced ref hangs the loop until its context is cancelled, which is a deadlock wearing a timeout.

func (*Runtime) HostUnref added in v0.2.0

func (rt *Runtime) HostUnref()

HostUnref records that an in-flight host operation is done.

func (*Runtime) InternedCount

func (rt *Runtime) InternedCount() int

InternedCount returns how many strings are in this runtime's intern table.

The table is permanent and shared by every realm, so this number only rises. It is exposed so a host can tell the difference between memory that is merely uncollected and memory that is pinned forever — and so a test can prove that passing data in does not pin it.

func (*Runtime) Interrupt

func (rt *Runtime) Interrupt()

Interrupt requests that any script currently running on this Runtime stop as soon as it reaches the next check point. Safe to call from any goroutine, and safe to call when nothing is running.

func (*Runtime) Interrupted

func (rt *Runtime) Interrupted() bool

Interrupted reports whether an interrupt is pending or has been delivered. A pending turn hand-over is not one: the script is not stopping.

func (*Runtime) IsArray

func (rt *Runtime) IsArray(v Value) bool

IsArray reports whether v is an Array exotic object (Array.isArray, which also sees through a Proxy to its target).

func (*Runtime) IsBigInt

func (rt *Runtime) IsBigInt(v Value) bool

func (*Runtime) IsBool

func (rt *Runtime) IsBool(v Value) bool

func (*Runtime) IsByteArray

func (rt *Runtime) IsByteArray(v Value) bool

IsByteArray reports whether v is a value whose contents are unambiguously bytes: an ArrayBuffer, or a one-byte-per-element view of one. A Float64Array has bytes too, but they are not what it holds, so it is excluded — a host deciding how to represent a value should not turn its numbers into a blob.

func (*Runtime) IsDate

func (rt *Runtime) IsDate(v Value) bool

IsDate reports whether v is a Date object, by its internal slot rather than by its prototype, so an object merely inheriting from Date.prototype is not mistaken for one.

func (*Runtime) IsError

func (rt *Runtime) IsError(v Value) bool

IsError reports whether v inherits from Error.prototype.

func (*Runtime) IsFunction

func (rt *Runtime) IsFunction(v Value) bool

IsFunction reports whether v is callable.

func (*Runtime) IsNull

func (rt *Runtime) IsNull(v Value) bool

func (*Runtime) IsNumber

func (rt *Runtime) IsNumber(v Value) bool

func (*Runtime) IsObject

func (rt *Runtime) IsObject(v Value) bool

IsObject reports whether v is an object (including functions and arrays), matching the embedder-facing sense of "object" rather than typeof.

func (*Runtime) IsPromise

func (rt *Runtime) IsPromise(v Value) bool

IsPromise reports whether v carries promise settlement state.

func (*Runtime) IsString

func (rt *Runtime) IsString(v Value) bool

func (*Runtime) IsSymbol

func (rt *Runtime) IsSymbol(v Value) bool

IsSymbol and IsBigInt cover the two primitives the basic predicates omit.

func (*Runtime) IsTypedArray

func (rt *Runtime) IsTypedArray(v Value) bool

IsTypedArray reports whether v is an integer-indexed exotic object. Such a value is not IsObject — it has its own tag — so a host walking a graph must test for it separately.

func (*Runtime) IsUndefined

func (rt *Runtime) IsUndefined(v Value) bool

Type predicates. These answer questions about the value as it is, with no coercion — IsNumber is false for a String that happens to look numeric.

func (*Runtime) JITEnabled

func (rt *Runtime) JITEnabled() bool

JITEnabled reports whether this Runtime will compile and will enter compiled code.

func (*Runtime) JSONParse

func (rt *Runtime) JSONParse(s string) (Value, error)

JSONParse applies JSON.parse(s).

func (*Runtime) JSONParseBytes

func (rt *Runtime) JSONParseBytes(b []byte) (Value, error)

JSONParseBytes parses JSON directly from b, with no intermediate JS string.

b must not be modified while the returned value is reachable: the parser takes a string view over it rather than copying. Strings *inside* the result are freshly allocated, so only the top-level buffer is aliased.

This is JSON.parse without a reviver. A host that needs one should go through the builtin, since the reviver has to observe source text.

func (*Runtime) JSONParseBytesLazy

func (rt *Runtime) JSONParseBytesLazy(b []byte) (Value, error)

JSONParseBytesLazy parses JSON directly from b without building the value graph. Objects and arrays come back knowing their own layout and nothing deeper; each property or element is parsed the first time it is read.

This is JSON.parse without a reviver, with the same result for any script that can observe it, and with cost proportional to what the script reads rather than to the size of the document.

b must not be modified or reused for as long as the returned value is reachable. That window is longer than JSONParseBytes's: the result aliases b for its whole life, not just for the duration of the parse.

func (*Runtime) JSONStringify

func (rt *Runtime) JSONStringify(v Value) (s string, ok bool, err error)

JSONStringify applies JSON.stringify(v). ok is false when the result is undefined — JSON.stringify(undefined) is not the string "undefined", it is no value at all, and collapsing the two would corrupt a host round-trip.

func (*Runtime) JSONStringifyEachToBytes

func (rt *Runtime) JSONStringifyEachToBytes(vals []Value, dst []byte) (out []byte, ends []int, err error)

JSONStringifyEachToBytes serializes each of vals in turn, appending every result to dst and returning the extended buffer plus the offset each value ends at, so a caller can slice them apart without a second pass.

This exists for the multi-output case, which is the one that made the old arrangement expensive: N results had to be packed into a single JS value to come back across in one piece, so each was stringified and then the array of strings was stringified again — escaping every quote in every payload a second time. Here they are simply written one after another.

A value that serializes to nothing contributes no bytes; its offset equals the previous one, so an empty span is distinguishable from a written one.

func (*Runtime) JSONStringifyToBytes

func (rt *Runtime) JSONStringifyToBytes(v Value, dst []byte) (out []byte, ok bool, err error)

JSONStringifyToBytes serializes v as JSON, appending to dst and returning the extended slice. Pass nil to allocate, or a reused buffer to avoid allocating at all.

ok is false when v serializes to nothing — undefined, a function, a symbol. That is not the string "undefined" and not an empty string; it is the absence of a value, and a caller that flattens the distinction corrupts its output. dst is returned unchanged in that case.

The value is serialized once, straight into dst. The pattern this replaces — stringify in JS, hand back a JS string, copy it to Go, and for multiple outputs stringify the whole lot a second time so it can travel as one value — costs several full passes over the payload and escapes it twice.

func (*Runtime) LengthOf

func (rt *Runtime) LengthOf(obj Value) (int, error)

LengthOf reads obj.length and coerces it the way the array built-ins do. It is the length of an array, a string or an array-like; anything without a numeric length reports 0.

func (*Runtime) LiveObjects

func (rt *Runtime) LiveObjects() int

LiveObjects reports how many object cells are currently allocated.

func (*Runtime) NewArray

func (rt *Runtime) NewArray(vals ...Value) Value

NewArray returns a fresh Array holding vals.

func (*Runtime) NewBigIntValue

func (rt *Runtime) NewBigIntValue(x *big.Int) Value

NewBigIntValue boxes a big.Int. The engine copies it, so the caller keeps ownership of x.

func (*Runtime) NewBool

func (rt *Runtime) NewBool(b bool) Value

func (*Runtime) NewDate

func (rt *Runtime) NewDate(ms float64) (Value, error)

NewDate builds a Date from milliseconds since the epoch, through the Date constructor so it gets the running realm's prototype.

func (*Runtime) NewError

func (rt *Runtime) NewError(msg string) Value

NewError builds an Error object with the given message, for a host function that wants to throw something the script can catch and inspect.

func (*Runtime) NewFunction

func (rt *Runtime) NewFunction(name string, length int, fn HostFunc) Value

NewFunction returns a callable object backed by a Go function.

func (*Runtime) NewHostPromise added in v0.2.0

func (rt *Runtime) NewHostPromise() (promise Value, resolve, reject func(Value))

NewHostPromise returns a pending promise and the two functions that settle it.

The promise is rooted and the loop is ref'd from here until one of them runs, so a host may hand the promise to JavaScript, forget it, and still settle it later. Settling releases both.

Call this on the Runtime's goroutine — typically from inside the host function that is returning the promise. The settle functions have the same rule: reach them from another goroutine through Post.

func (*Runtime) NewNumber

func (rt *Runtime) NewNumber(f float64) Value

NewNumber and NewBool wrap Go primitives.

func (*Runtime) NewObject

func (rt *Runtime) NewObject() Value

NewObject returns a fresh ordinary object with Object.prototype.

func (*Runtime) NewRealm

func (rt *Runtime) NewRealm() *Runtime

NewRealm creates a second realm on top of this one's value pools: a fresh global object with its own intrinsics, but the SAME representation for values, which is what lets an object made in one realm be used from the other. It is the relationship a V8 context has with its isolate.

The pieces the spec shares per AGENT rather than per realm — the interned string table, the Symbol.for registry, and the well-known symbols — are carried over, so `Symbol.iterator` is one symbol everywhere and an object made in one realm is still iterable from the other.

func (*Runtime) NewString

func (rt *Runtime) NewString(s string) Value

NewString interns s and returns it as a JS string.

Interning makes the string canonical, which is what property keys and identifiers need — but the intern table is permanent and shared by every realm on this runtime, so an interned string is never reclaimed. Use this only for names, never for data.

func (*Runtime) NewStringBytes

func (rt *Runtime) NewStringBytes(b []byte) Value

NewStringBytes returns b as a JS string without interning it, taking ownership of the slice rather than copying it. The caller must not modify b afterwards — JS strings are immutable and the engine will read it directly. This is the zero-copy path a cgo binding could not offer.

func (*Runtime) NewStringData

func (rt *Runtime) NewStringData(s string) Value

NewStringData returns s as a JS string without interning it.

This is the right constructor for host data — a message payload, a file's contents, anything large or unbounded in variety. Interning such a string would pin it in the runtime's intern table for the process's life: a host that passes in a distinct 50 MB message per call would retain every one of them forever, which is the difference between a working embedding and one that dies overnight.

func (*Runtime) NewUint8Array

func (rt *Runtime) NewUint8Array(b []byte) Value

NewUint8Array wraps b as a Uint8Array without copying it: the returned view reads and writes the caller's slice directly. Like NewStringBytes this trades a copy for a contract — b is now the array's backing store, and a host that keeps writing to it is writing into live JavaScript state.

Pass a copy if that is not what you want.

func (*Runtime) Null

func (rt *Runtime) Null() Value

func (*Runtime) OwnKeys

func (rt *Runtime) OwnKeys(obj Value) ([]string, error)

OwnKeys returns obj's own enumerable string keys, in property order: integer indices ascending, then the rest in insertion order. This is Object.keys, so it excludes symbols, inherited properties and non-enumerable ones.

func (*Runtime) Post added in v0.2.0

func (rt *Runtime) Post(fn func()) error

Post schedules fn to run on the Runtime's own goroutine, at the next point the loop is between jobs. It is safe from any goroutine — that is the whole point of it — and it is the ONLY safe way for another goroutine to reach a Runtime.

A closure passed here must not capture a Value: the collector cannot see inside a func, and a Value the queue is holding on behalf of a job that has not run yet is a Value nothing is keeping alive. Capture Go data, convert it inside fn, or root what you must keep with HoldValue.

Returns ErrHostClosed once the Runtime has been closed, so a goroutine finishing after shutdown learns that its answer went nowhere instead of blocking forever or panicking.

func (*Runtime) PromiseState

func (rt *Runtime) PromiseState(v Value) (state int, result Value, ok bool)

PromiseState returns the settlement state and value of a promise. ok is false if v is not a promise. For a pending promise the value is undefined.

func (*Runtime) RealTimers added in v0.2.0

func (rt *Runtime) RealTimers() bool

RealTimers reports whether the wall clock is in use.

func (*Runtime) RunLoop added in v0.2.0

func (rt *Runtime) RunLoop(ctx context.Context) error

RunLoop drives the event loop until there is nothing left that could produce more work — no microtasks, no timers, no posted jobs, no host operation in flight — or until ctx is done.

This is DrainJobs for a host that has asynchrony of its own. The difference is what "nothing left" means: with a fetch outstanding, the queues are empty and the program is very much not finished, and only the ref count knows.

func (*Runtime) RunModule

func (rt *Runtime) RunModule(filename, src string) (Value, error)

RunModule parses src in the Module goal (strict) and evaluates it. Preludes (harness scripts) should be run via RunString into the same Runtime first so their globals are visible. Static imports are not yet linked.

func (*Runtime) RunScript

func (rt *Runtime) RunScript(s *Script) (Value, error)

RunScript executes a previously compiled script and returns its completion value. It does not drain the job queue — a host that cares about promise settlement calls DrainJobs afterwards, mirroring the explicit microtask checkpoint an embedder is used to.

func (*Runtime) RunString

func (rt *Runtime) RunString(filename, src string) (Value, error)

RunString parses, compiles, and evaluates source, returning the script completion value (ant's parse → sv_compile → sv_execute pipeline).

func (*Runtime) SetBlobResolver

func (rt *Runtime) SetBlobResolver(r BlobResolver)

SetBlobResolver installs the resolver used by JSONParseBytesLazy for envelopes it encounters. Pass nil to disable, which is the default.

func (*Runtime) SetGCEnabled

func (rt *Runtime) SetGCEnabled(on bool)

SetGCEnabled turns automatic collection on or off. It is on by default; turn it off for a run short enough that nothing needs reclaiming, or one that ends with Invocation.Release.

func (*Runtime) SetHeapLimit

func (rt *Runtime) SetHeapLimit(limit uint64)

SetHeapLimit stops a script once its live heap exceeds limit bytes, instead of letting it run until the Go allocator gives up.

This is the difference between a bad script and a dead process. Go's out-of-memory is runtime.throw: no panic, no recover, no deferred anything — the process aborts and takes every other flow on it along. A host cannot defend against that after the fact, so the engine has to decline before it happens, and it is the only party that can, because it owns the allocation.

The limit is checked after a collection, never before one, so what it measures is memory that survived being collected rather than garbage on its way out. A script that churns hard but retains little is never stopped by it.

Exceeding it terminates the script the same way Interrupt does — a control throw that no catch or finally can swallow — and the host distinguishes the two with HeapLimitExceeded. Pass 0 to disable.

func (*Runtime) SetIndex

func (rt *Runtime) SetIndex(obj Value, i int, v Value) error

SetIndex writes obj[i].

func (*Runtime) SetJITEnabled

func (rt *Runtime) SetJITEnabled(on bool)

SetJITEnabled turns the compiled tier on or off for this Runtime alone.

Per-Runtime rather than per-process because a host does not have one workload. An embedder that runs long numeric flows alongside short one-shot scripts wants the tier for the former and has no use for it in the latter, and a host rolling the tier out wants it on for a fraction of its traffic — neither of which a process-wide switch or an environment variable can express.

It takes effect immediately and in both directions. Turning it OFF stops this Runtime compiling anything further AND stops it entering code it has already compiled, so it is a genuine kill switch rather than a decision that only applies to functions not yet hot: a host that sees trouble can turn the tier off on a live Runtime and have the next call interpret. What it does not do is unmap the code — that goes when the function does, see jit_reclaim.go.

Compiled code is attached to the FUNCTION, and a Program can be shared between Runtimes. That is sound here precisely because the gate is per-Runtime: a Runtime with the tier off skips the entry check regardless of what some other Runtime compiled the same function into.

func (*Runtime) SetModuleBase

func (rt *Runtime) SetModuleBase(dir string)

SetModuleBase sets the directory that import specifiers resolve against when the importer is not itself a module (a script calling import()).

func (*Runtime) SetModuleResolver added in v0.2.0

func (rt *Runtime) SetModuleResolver(fn ModuleResolverFunc)

SetModuleResolver installs the host's module resolution. Without one the engine resolves a specifier as a path relative to the importing module, which covers relative imports and nothing else — a bare `import "@scope/pkg"` has no meaning the engine can supply, because the meaning is the host's package layout, an embedded bundle, or an import map.

func (*Runtime) SetProp

func (rt *Runtime) SetProp(obj Value, name string, v Value) error

SetProp writes obj.name, running any setter.

func (*Runtime) SetRealTimers added in v0.2.0

func (rt *Runtime) SetRealTimers(on bool)

SetRealTimers switches the loop from the virtual clock to the wall clock: a timer fires when its delay has actually elapsed, and the loop sleeps in between instead of running the queue down as fast as it can.

Off by default, because determinism is worth more to a test than elapsed time is, and a script that only orders its callbacks gets the same answer either way. It is worth turning on for anything that waits on the world — a poll interval, a retry backoff, a timeout racing a request — where firing immediately means not waiting at all.

func (*Runtime) StrictEquals

func (rt *Runtime) StrictEquals(a, b Value) bool

StrictEquals applies ===.

func (*Runtime) Throw

func (rt *Runtime) Throw(v Value) *ThrowError

Throw wraps a value as a thrown JS exception, for returning from a HostFunc.

func (*Runtime) ThrowError

func (rt *Runtime) ThrowError(msg string) *ThrowError

ThrowError builds and wraps an Error in one step.

func (*Runtime) ToBool

func (rt *Runtime) ToBool(v Value) bool

ToBool applies ToBoolean.

func (*Runtime) ToNumber

func (rt *Runtime) ToNumber(v Value) (float64, error)

ToNumber applies ToNumber.

func (*Runtime) ToString

func (rt *Runtime) ToString(v Value) (string, error)

ToString applies ToString and returns the result as a Go string. It can throw, because a value's toString/@@toPrimitive is arbitrary JS.

func (*Runtime) TypeOf

func (rt *Runtime) TypeOf(v Value) string

TypeOf returns the `typeof` string for v.

func (*Runtime) Undefined

func (rt *Runtime) Undefined() Value

Undefined and Null return the corresponding primitives.

func (*Runtime) UnrefTimer added in v0.2.0

func (rt *Runtime) UnrefTimer(id float64, unref bool)

UnrefTimer marks a scheduled timer as not keeping the loop alive. It is Node's timer.unref(), and library code leans on it: an idle watchdog armed alongside a request is unref'd so that finishing the request finishes the program, rather than waiting out a timeout nobody is interested in any more.

Without it, a five-minute stream watchdog held the loop open for five minutes after the stream had finished.

type Script

type Script struct {
	// contains filtered or unexported fields
}

Script is a compiled program, separated from execution so an embedder can compile once and run many times (the "unbound script" pattern). The compiled form is bound to the Runtime that produced it.

Bound is meant literally, and running one on a DIFFERENT Runtime concurrently is a data race rather than a style violation. A Script holds the function, the function holds the tier's state — how many times it has been entered and the code it was compiled to — and none of that is synchronised, because within one Runtime nothing is concurrent. Two Runtimes sharing a Script race on it, which the race detector reports in jitTry.

This is worth stating because there is an obvious reason to want it. A host pooling Runtimes for one script would like them to share the compiled code, so that the first to go hot warms the rest — each pooled Runtime otherwise pays its own entries before it compiles. Compile per Runtime instead; the parse is what a pool saves by sharing, and the parse is not where the time goes.

func (*Script) Source

func (s *Script) Source() string

Source returns the text the script was compiled from.

type SyntaxError

type SyntaxError struct {
	Msg      string
	Offset   int
	Filename string
}

SyntaxError is a parse-time error carrying a source offset.

func (*SyntaxError) Error

func (e *SyntaxError) Error() string

type ThrowError

type ThrowError struct {
	Value Value
	// contains filtered or unexported fields
}

ThrowError wraps a thrown JS value surfaced as a Go error. When control is set it is a non-catchable control-flow signal (e.g. process.exit) that bypasses catch handlers.

func (*ThrowError) Error

func (e *ThrowError) Error() string

type Token

type Token uint8

Token kinds — ported 1:1 from ant include/tokens.h. The exact numeric values matter: the parser does range checks (identifier-like tokens live in [TokIdentifier, TokIdentLikeEnd); operators start at TokDot=100) and indexes precTable by token.

const (
	TokErr Token = iota
	TokEOF
	TokNumber
	TokString
	TokSemicolon
	TokBigInt
	TokLParen
	TokRParen
	TokLBrace
	TokRBrace
	TokLBracket
	TokRBracket
)
const (
	TokIdentifier Token = 50 + iota
	TokAsync
	TokAwait
	TokBreak
	TokCase
	TokCatch
	TokClass
	TokConst
	TokContinue
	TokDefault
	TokDelete
	TokDo
	TokDebugger
	TokElse
	TokExport
	TokFinally
	TokFor
	TokFrom
	TokFunc
	TokIf
	TokImport
	TokIn
	TokInstanceof
	TokLet
	TokNew
	TokOf
	TokReturn
	TokSuper
	TokSwitch
	TokThis
	TokThrow
	TokTry
	TokVar
	TokVoid
	TokWhile
	TokWith
	TokYield
	TokUndef
	TokNull
	TokTrue
	TokFalse
	TokAs
	TokStatic
	TokTypeof
	TokUsing
	TokWindow
	TokGlobalThis
	TokIdentLikeEnd
)

Identifier-like tokens (keywords + identifiers), based at 50.

const (
	TokDot Token = 100 + iota
	TokCall
	TokBracket
	TokPostInc
	TokPostDec
	TokNot
	TokTilda
	TokUPlus
	TokUMinus
	TokExp
	TokMul
	TokDiv
	TokRem
	TokOptionalChain
	TokRest
	TokPlus
	TokMinus
	TokShl
	TokShr
	TokZShr
	TokLt
	TokLe
	TokGt
	TokGe
	TokEq
	TokNe
	TokSeq
	TokSne
	TokAnd
	TokXor
	TokOr
	TokLand
	TokLor
	TokNullish
	TokColon
	TokQ
	TokAssign
	TokPlusAssign
	TokMinusAssign
	TokMulAssign
	TokDivAssign
	TokRemAssign
	TokShlAssign
	TokShrAssign
	TokZShrAssign
	TokAndAssign
	TokXorAssign
	TokOrAssign
	TokExpAssign
	TokLorAssign
	TokLandAssign
	TokNullishAssign
	TokComma
	TokTemplate
	TokArrow
	TokHash
	TokMax
)

Operators, based at 100.

type Type

type Type uint8

Type is a 5-bit NaN-box type tag.

const (
	// heap-resident
	TObj Type = iota // 0
	TStr             // 1
	TArr             // 2

	// objects
	TFunc      // 3
	TCFunc     // 4
	TPromise   // 5
	TGenerator // 6

	// primitives
	TUndef  // 7
	TNull   // 8
	TBool   // 9
	TNum    // 10
	TBigInt // 11
	TSymbol // 12

	// internal
	TErr        // 13
	TTypedArray // 14
	TNTArg      // 15

	// collections
	TMap     // 16
	TSet     // 17
	TWeakMap // 18
	TWeakSet // 19

	TSentinel Type = nanboxTypeMask // 31
)

Type tags — the 5-bit tag stored in bits 51..47. Order and values are identical to the anonymous enum in include/internal.h; the JIT and the T_*_MASK bit-tests below depend on the exact numbering.

type Value

type Value uint64

Value is a NaN-boxed JavaScript value.

func ExceptionValue

func ExceptionValue(err error) (Value, bool)

ExceptionValue extracts the thrown JS value from an error returned by this package, so a host can inspect it rather than only read its message. ok is false for errors that are not JS exceptions (parse errors, for instance).

func (Value) Bool

func (v Value) Bool() bool

Bool extracts the boolean payload (undefined behavior if not a TBool).

func (Value) Data

func (v Value) Data() uint64

Data returns v's 47-bit payload (a pool handle, immediate, or tagged pointer, depending on the type).

func (Value) IsBool

func (v Value) IsBool() bool

func (Value) IsEmpty

func (v Value) IsEmpty() bool

func (Value) IsErr

func (v Value) IsErr() bool

func (Value) IsNonNumeric

func (v Value) IsNonNumeric() bool

IsNonNumeric mirrors ant's is_non_numeric bit-test.

func (Value) IsNull

func (v Value) IsNull() bool

func (Value) IsNullish

func (v Value) IsNullish() bool

func (Value) IsNumber

func (v Value) IsNumber() bool

func (Value) IsObjectLike

func (v Value) IsObjectLike() bool

IsObjectLike reports whether v is a heap object that participates in the ordinary property protocol: an object-family value (IsObjectType) or a TypedArray, which is an exotic object carried under its own value tag.

func (Value) IsObjectType

func (v Value) IsObjectType() bool

IsObjectType reports whether v is one of the object-family tags (obj/arr/func/promise/generator).

func (Value) IsSpecialObject

func (v Value) IsSpecialObject() bool

IsSpecialObject reports whether v is a plain object or array.

func (Value) IsString

func (v Value) IsString() bool

func (Value) IsSymbol

func (v Value) IsSymbol() bool

func (Value) IsUndefined

func (v Value) IsUndefined() bool

func (Value) Number

func (v Value) Number() float64

Number extracts the float64 (undefined behavior if tagged).

func (Value) Type

func (v Value) Type() Type

Type returns v's NaN-box type tag. Untagged (numeric) values report TNum.

type VarKind

type VarKind uint8

VarKind is a declaration kind (ant sv_var_kind_t).

const (
	VarVar VarKind = iota
	VarLet
	VarConst
	VarUsing
	VarAwaitUsing
)

Source Files

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL