js

package
v0.11.0 Latest Latest
Warning

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

Go to latest
Published: Feb 19, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package js provides an abstraction on top of script engines.

The purpose is to allow a modular approach to implementing client-side APIs, where the modules don't need to address a specific script engine; and client code can switch between script engines.

The ability to switch script engine seems like a really good idea, as you have two different priorities you might want to switch between:

- Using an engine that you know contains latest ES standards (V8) - Using a pure Go engine, simplifying the build pipeline.

Additionally, if other projects would support SpiderMonkey (Firefox) and JavaScriptCore (Safari), you could verify your code using the script engines of the different browsers. (Do note, that it is outside the scope of this project to simulate the differences of different browsers).

Index

Constants

This section is empty.

Variables

View Source
var ErrMissingArgument = errors.New("missing argument")
View Source
var ErrNoInternalValue = errors.New("object does not have an internal instance")
View Source
var ErrNotIterable = errors.New("gost-dom/scripting: value not iterable")
View Source
var NotIntercepted = errors.New("Not intercepted")

Functions

func ArgsLogAttr added in v0.9.3

func ArgsLogAttr[T any](cbCtx CallbackContext[T]) slog.Attr

func As

func As[T any](val any, err error) (rtnVal T, rtnErr error)

func ConsumeArgument added in v0.7.2

func ConsumeArgument[T, U any](
	args CallbackContext[U],
	name string,
	defaultValue func() T,
	decoders ...func(Scope[U], Value[U]) (T, error),
) (result T, err error)

ConsumeArgument pulls one of the passed arguments and tries to convert it to target type T using one of the passed decoders. The return value will be taken from the first decode that does not return an error. If no decoder is succeeds, an error is returned.

If no more arguments are present, or the next argument is undefined, the defaultValue function will be used if not nil; otherwise an error is returned.

If the function returns with an error, the name will be used in the error message. Otherwise, name has ho effect on the function.

func ConsumeOptionalArg added in v0.7.2

func ConsumeOptionalArg[T, U any](
	cbCtx CallbackContext[T],
	name string,
	decoders ...func(Scope[T], Value[T]) (U, error),
) (result U, found bool, err error)

func ConsumeRestArguments added in v0.7.2

func ConsumeRestArguments[T, U any](
	args CallbackContext[U],
	name string,
	decoders ...func(Scope[U], Value[U]) (T, error),
) (results []T, err error)

func DecodeInto added in v0.11.0

func DecodeInto[T, U any](
	scope Scope[T],
	target *U,
	opts Object[T],
	key string,
	decoder func(Scope[T], Value[T]) (U, error),
) error

func InstallIterator added in v0.11.0

func InstallIterator[T, U any](class Class[U], entityLookup ValueResolver[T, U])

InstallIterator creates prototype operations the web IDL value iterables should implement, including Symbol.iterator and entries. This requires that instances must wrap a value providing method All() returning an iter.Seq[T].

See also: https://webidl.spec.whatwg.org/#idl-iterable

func InstallIterator2 added in v0.11.0

func InstallIterator2[K, V, U any](
	class Class[U],
	keyLookup ValueResolver[K, U],
	valueLookup ValueResolver[V, U],
)

InstallIterator2 creates prototype operations the web IDL key/value iterables should implement, including Symbol.iterator and entries. This requires that instances must wrap a value providing method All() returning an iter.Seq2[K,V].

See also: https://webidl.spec.whatwg.org/#idl-iterable

func IsBoolean added in v0.11.0

func IsBoolean[T any](v Value[T]) bool

func IsNullish added in v0.8.0

func IsNullish[T any](v Value[T]) bool

IsNullish returns whether a JavaScript value is null or undefined.

func IsUndefined added in v0.10.3

func IsUndefined[T any](v Value[T]) bool

func Iterate added in v0.10.3

func Iterate[T any](v Value[T]) iter.Seq2[Value[T], error]

iterate returns a seq.Iter2 exposing a JavaScript iterable as a Go iterator. The returned Seq will yield an error value if the value is not an Iterable, or JavaScript iterator throws an error during iteration.

func LogAttr added in v0.9.2

func LogAttr[T any](key string, val Value[T]) slog.Attr

func ObjectEnumerableOwnPropertyKeys added in v0.10.3

func ObjectEnumerableOwnPropertyKeys[T any](
	scope CallbackScope[T],
	obj Object[T],
) iter.Seq2[Value[T], error]

ObjectEnumerableOwnPropertyKeys iterates over all enumerable [[OwnPropertyKeys]]

func ParseSetterArg added in v0.7.2

func ParseSetterArg[T, U any](
	ctx CallbackContext[T],
	parsers ...func(Scope[T], Value[T]) (U, error),
) (result U, err error)

ParseSetterArg parses a single argument and is intended for attribute setters, where exactly one argument must be passed by JS.

func ThisLogAttr added in v0.9.2

func ThisLogAttr[T any](cbCtx CallbackContext[T]) slog.Attr

ThisLogAttr creates an slog.Attr representing the JavaScript this value in a callback.

Types

type ArgumentConsumer added in v0.7.2

type ArgumentConsumer[T any] interface {
	// ConsumeArg pulls argument from the list of passed arguments. The return
	// value arg will contain the argument. If no argument is passed, or
	// the value is undefined, arg will be nil. Ok indicates whether there were
	// more arguments to consume,
	// the function returns nil. (e.g., if you call the method 3 times, but only
	// two arguments were passed).
	//
	// For most use cases, the client shouldn't care about the ok return value;
	// but treat the value as if undefined was passed. The primary use for ok is
	// when consuming the remaining arguments for a variadic argument list, e.g.
	// [Element.append]
	//
	// [Element.append]: https://developer.mozilla.org/en-US/docs/Web/API/Element/append
	ConsumeArg() (arg Value[T], ok bool)
	Args() []Value[T]
}

type Callback added in v0.11.0

type Callback[T any] interface {
	Call(CallbackContext[T]) (Value[T], error)
}

type CallbackContext

type CallbackContext[T any] interface {
	ArgumentConsumer[T]
	CallbackScope[T]
}

CallbackContext represents the execution context of a JavaScript function or handler callback. For example

- Calling a native function or constructor - Getting or setting an accessor property backed by a native function

An instance of CallbackContext can only be used inside the actual function callback.

type CallbackFunc added in v0.11.0

type CallbackFunc[T any] func(CallbackContext[T]) (Value[T], error)

func (CallbackFunc[T]) Call added in v0.11.0

func (f CallbackFunc[T]) Call(ctx CallbackContext[T]) (Value[T], error)

func (CallbackFunc[T]) WithLog added in v0.11.0

func (c CallbackFunc[T]) WithLog(class, method string) CallbackFunc[T]

type CallbackScope added in v0.7.2

type CallbackScope[T any] interface {
	Scope[T]

	// Instance returns the Go value that is wrapped by "this", with "this"
	// referring the the JavaScript value of "this". If the object does not
	// contain an internal Go value an [ErrNoInternalValue] error is returned.
	Instance() (any, error)

	This() Object[T]

	Eval(script, location string) (Value[T], error)
}

type Class added in v0.7.2

type Class[T any] interface {
	CreateOperation(name string, cb CallbackFunc[T])
	CreateIteratorMethod(cb CallbackFunc[T])
	CreateAttribute(
		name string,
		getter CallbackFunc[T],
		setter CallbackFunc[T],
		opts ...PropertyOption,
	)
	CreateIndexedHandler(getter ...IndexedHandlerOption[T])
	CreateNamedHandler(opts ...NamedHandlerOption[T])
}

Class represents a JavaScript "class" that wraps a Go object.

This package has two separate abstractions for a class serving two different roles. This abstractions serves the role of configuring the methods and attributes that exists on a class. To create an instance of a class, you use the Constructor

This is independent of any actual execution context, so values in global scope can be declared before creating a JavaScript execution context.

func CreateClass added in v0.11.0

func CreateClass[T any](
	e ScriptEngine[T],
	className, inherits string,
	constructorCallback CallbackFunc[T],
) Class[T]

CreateClass creates a new JavaScript "class" with a constructor, implementing an IDL interface. If inherits is non-empty, the new class will inherit from the named class. If constructor is nil, IllegalConstructor will be used. Panics if a non-empty inherits argument doesn't match a previously created class.

Note, web IDL standards use the term "inherits". JavaScript classes use the keyword "extends". The web IDL term is used here.

func MustGetClass added in v0.11.0

func MustGetClass[T any](e ScriptEngine[T], className string) Class[T]

MustGetClass finds a previously registered class. Returns nil if className is empty. Panics if className is non-empty and not previously registered.

type Configurer added in v0.11.0

type Configurer[T any] interface{ Configure(ScriptEngine[T]) }

type ConfigurerFunc added in v0.7.2

type ConfigurerFunc[T any] func(ScriptEngine[T])

func (ConfigurerFunc[T]) Configure added in v0.7.2

func (f ConfigurerFunc[T]) Configure(e ScriptEngine[T])

type Constructor added in v0.7.2

type Constructor[T any] interface {
	NewInstance(nativeValue any) (Object[T], error)
}

Constructor represents a JavaScript "class" that wraps a Go object.

This package has two separate abstractions for a class serving two different roles. This abstraction is used to create instances of a class in a JavaScript execution context.

The class must previously have been configured using the Class interface.

type Disposable added in v0.7.2

type Disposable interface{ Dispose() }

disposable represents a resource that needs cleanup when a context is closed. E.g., cgo handles that need to be released.

type Error added in v0.8.0

type Error[T any] interface {
	Value[T]
	error
}

Error is a "throwable" error. In JavaScript, you can throw any value. This includes interface error, making it a valid Go error value as well.

Function ToJsError can convert sn error returned from a native Go function to Error[T].

To keep the original go error, the implementing type **must** be able to keep an optional error value, that can be obtained through an Unwrap() function. Error[T] doesn't include the Unwrap() function as the return type is unknown at design time; it can be either error or []error.

func ToJsError added in v0.11.0

func ToJsError[T any](s Scope[T], err error) (res Error[T])

ToJsError converts a Go error instance to a value the script engine can handle. Passing a nil value will return nil, making the function safe to use where it's not known at compile time if there is an error or not. If the error is already a js-engine compatible error, it is returned as is. TODO: The total list of possible errors needs to be configurable on the script engine, and not coupled to the error types known by the core browser.

type ErrorHandler added in v0.11.0

type ErrorHandler[T any] interface {
	HandleError(Scope[T], error)
}

type ErrorHandlerFunc added in v0.11.0

type ErrorHandlerFunc[T any] func(Scope[T], error)

func (ErrorHandlerFunc[T]) HandleError added in v0.11.0

func (f ErrorHandlerFunc[T]) HandleError(s Scope[T], err error)

type Function added in v0.7.2

type Function[T any] interface {
	Value[T]

	Call(this Object[T], args ...Value[T]) (Value[T], error)
}

func AsFunction added in v0.10.3

func AsFunction[T any](v Value[T]) (Function[T], bool)

func ObjectGetFunction added in v0.10.3

func ObjectGetFunction[T any](o Object[T], name string) (res Function[T], ok bool, err error)

func ObjectGetFunctionx added in v0.10.3

func ObjectGetFunctionx[T any](
	o Object[T],
	getter objectGetter[T],
) (res Function[T], ok bool, err error)

func ObjectGetIterator added in v0.10.3

func ObjectGetIterator[T any](o Object[T]) (res Function[T], ok bool, err error)

type GlobalObject added in v0.10.0

type GlobalObject[T any] interface {
	CreateFunction(name string, cb CallbackFunc[T])
}

GlobalObject represents an object that will be present in global scope. The JavaScript console object is an example of a global object.

type HandlerCallbacks added in v0.7.2

type HandlerCallbacks[Tjs, Tkey any] struct {
	Getter     HandlerGetterCallback[Tjs, Tkey]
	Setter     HandlerSetterCallback[Tjs, Tkey]
	Deleter    HandlerDeleterCallback[Tjs, Tkey]
	Enumerator HandlerEnumeratorCallback[Tjs, Tkey]
}

type HandlerDeleterCallback added in v0.7.2

type HandlerDeleterCallback[T, U any] func(scope CallbackScope[T], key U) (bool, error)

type HandlerEnumeratorCallback added in v0.7.2

type HandlerEnumeratorCallback[T, U any] func(CallbackScope[T]) ([]U, error)

type HandlerGetterCallback added in v0.7.2

type HandlerGetterCallback[T, U any] func(scope CallbackScope[T], key U) (Value[T], error)

type HandlerOption added in v0.7.2

type HandlerOption[T, U any] = func(*HandlerCallbacks[T, U])

func WithDeleterCallback added in v0.7.2

func WithDeleterCallback[T, U any](cb HandlerDeleterCallback[T, U]) HandlerOption[T, U]

func WithEnumeratorCallback added in v0.7.2

func WithEnumeratorCallback[T, U any](cb HandlerEnumeratorCallback[T, U]) HandlerOption[T, U]

func WithGetterCallback added in v0.7.2

func WithGetterCallback[T, U any](cb HandlerGetterCallback[T, U]) HandlerOption[T, U]

func WithSetterCallback added in v0.7.2

func WithSetterCallback[T, U any](cb HandlerSetterCallback[T, U]) HandlerOption[T, U]

type HandlerSetterCallback added in v0.7.2

type HandlerSetterCallback[T, U any] func(scope CallbackScope[T], key U, value Value[T]) error

type IndexLenCallback added in v0.8.0

type IndexLenCallback[T any] func(CallbackScope[T]) (int, error)

type IndexedHandlerCallbacks added in v0.8.0

type IndexedHandlerCallbacks[T any] struct {
	Getter HandlerGetterCallback[T, int]
	Len    IndexLenCallback[T]
}

type IndexedHandlerOption added in v0.8.0

type IndexedHandlerOption[T any] = func(*IndexedHandlerCallbacks[T])

func WithIndexedGetterCallback added in v0.8.0

func WithIndexedGetterCallback[T any](cb HandlerGetterCallback[T, int]) IndexedHandlerOption[T]

func WithLengthCallback added in v0.8.0

func WithLengthCallback[T any](cb IndexLenCallback[T]) IndexedHandlerOption[T]

type Iterator added in v0.7.2

type Iterator[E, T any] struct {
	Resolver ValueResolver[E, T]
}

Iterator implements the iterator protocol for a Go iter.Seq[E]. Type parameter T is the type parameter for the script engine. The field Resolver is a function that is used to generate a JavaScript value for an element of type E.

func NewIterator deprecated added in v0.7.2

func NewIterator[T, U any](entityLookup ValueResolver[T, U]) Iterator[T, U]

Deprecated: Use InstallIterator

func (Iterator[T, U]) InstallPrototype added in v0.7.2

func (i Iterator[T, U]) InstallPrototype(class Class[U])

Method InstallPrototype creates the following prototype methods:

- Symbol iterator - implementing the iterable protocol - "entries" - which all web API implement

func (Iterator[T, U]) NewIterator added in v0.7.2

func (i Iterator[T, U]) NewIterator(s Scope[U], items iter.Seq[T]) (Value[U], error)

Method NewIterator on an iterator returns a new iterator, iterating from the beginning of the specified sequence.

type Iterator2 added in v0.7.2

type Iterator2[K, V, U any] struct {
	// contains filtered or unexported fields
}

Iterator2 is like Iterator, but implements a key/value iterator over an iter.Seq2[K,V] value.

func NewIterator2 deprecated added in v0.7.2

func NewIterator2[K, V, U any](
	keyLookup ValueResolver[K, U],
	valueLookup ValueResolver[V, U],
) Iterator2[K, V, U]

Deprecated: Use InstallIterator2

func (Iterator2[K, V, U]) InstallPrototype added in v0.7.2

func (i Iterator2[K, V, U]) InstallPrototype(cls Class[U])

InstallPrototype creates the following prototype methods on cls.

- Symbol Iterator - "entries" - Returns the same iterator as Symbol Iterator - "keys" - Returns an iterator over all keys - "values" - Returns an iterator over all values

type IteratorKey added in v0.10.3

type IteratorKey[T any] struct{}

type NamedHandlerCallbacks added in v0.7.2

type NamedHandlerCallbacks[T any] = HandlerCallbacks[T, Value[T]]

type NamedHandlerOption added in v0.7.2

type NamedHandlerOption[T any] = func(*HandlerCallbacks[T, Value[T]])

type Object added in v0.7.2

type Object[T any] interface {
	Value[T]
	NativeValue() any
	SetNativeValue(any)
	Keys() ([]string, error)
	Get(name string) (Value[T], error)
	Set(name string, val Value[T]) error
	Iterator() (Value[T], error)
}

func AssertObjectArg added in v0.7.2

func AssertObjectArg[T any](s Scope[T], v Value[T]) (Object[T], error)

AssertObject asserts that an argument is of an object type. A TypeError is returned if the value is not an object

type Option added in v0.11.0

type Option struct {
	// instanceMember indicates that the member will be an own property on
	// instance of the interface; not the prototype instance.
	InstanceMember bool
}

func InitOpts added in v0.11.0

func InitOpts(opts ...PropertyOption) Option

type Promise added in v0.8.0

type Promise[T any] interface {
	Value[T]
	Resolve(Value[T])

	// Reject rejects the promise with an Error instance, representing a Go
	// error value. This is based on two assumptions
	//
	//  - You always want to reject with Error values.
	//  - The cause will be an instance of a Go error value.
	//
	// So while you can reject with any value in JavaScript, it is best practice
	// to only use instances of the Error class. This implementation assumes
	// that all API implementations follow that practice.
	Reject(Value[T])
}

Promise represents a JavaScript promise that is controlled from Go-code.

type PropertyDescriptor added in v0.10.3

type PropertyDescriptor[T any] interface {
	Object[T]
	Enumerable() bool
}

func ObjectOwnPropertyDescriptor added in v0.10.3

func ObjectOwnPropertyDescriptor[T any](
	ctx CallbackScope[T],
	o Object[T],
	p Value[T],
) (PropertyDescriptor[T], error)

type PropertyDescriptorIter added in v0.10.3

type PropertyDescriptorIter[T any] struct {
	PropertyDescriptor[T]
	Key Value[T]
}

type PropertyOption added in v0.11.0

type PropertyOption func(*Option)

func LegacyUnforgeable added in v0.11.0

func LegacyUnforgeable() PropertyOption

type Scope added in v0.7.2

type Scope[T any] interface {
	ValueFactory[T]

	Logger() *slog.Logger
	Context() context.Context
	GlobalThis() Object[T]
	Clock() *clock.Clock
	Constructor(string) Constructor[T]
}

Scope provides access to the JavaScript execution context not coupled to a specific function callback. CallbackScope is safe use outside the scope of a function callback.

One case for storing the callback scope is when JavaScript code passes a function as a callback argument, which Go code need to call at a later point in time. E.g., when adding event listeners.

type ScriptEngine added in v0.7.2

type ScriptEngine[T any] interface {
	CreateClass(name string, Parent Class[T], cb CallbackFunc[T]) Class[T]
	Class(name string) (Class[T], bool)
	CreateGlobalObject(name string) GlobalObject[T]
	SetUnhandledPromiseRejectionHandler(ErrorHandler[T])
	ConfigureGlobalScope(name string, Parent Class[T]) Class[T]

	// InstallPolyfill is an escape hatch for when creating the right DOM
	// environment was easier to do in JS - or usable polyfills were found.
	InstallPolyfill(script, src string)
}

type StringKey added in v0.10.3

type StringKey[T any] string

type Value

type Value[T any] interface {
	Self() T

	String() string
	Int32() int32
	Uint32() uint32
	Boolean() bool

	IsUndefined() bool
	IsNull() bool
	IsSymbol() bool
	IsString() bool
	IsObject() bool
	IsBoolean() bool
	IsFunction() bool

	AsFunction() (Function[T], bool)
	AsObject() (Object[T], bool)

	StrictEquals(Value[T]) bool
}

Value represents a value in JavaScript. Referential equality cannot be used to check if to Value instances represent the same value in JavaScript. Use StrictEquals to check if two values are equal.

A script engine can use the method Self to return internal values.

The type parameter T is controlled by the actual script engine, permitting retriving the internal value used by the engine without type assertions, but more importantly, prevents bugs caused by misuse by client code. With the type parameter, only values produced by a script engine can be supplied to the engine, not any object that conforms to the interface.

func IllegalConstructor added in v0.11.0

func IllegalConstructor[T any](ctx CallbackContext[T]) (Value[T], error)

A callback function that returns an "Illegal constructor" TypeError in JavaScript. To be used for all classes that cannot be constructed by client code directly.

func ObjectEntries added in v0.10.3

func ObjectEntries[T any](ctx CallbackScope[T], o Object[T]) (Value[T], error)

func ObjectKeys added in v0.10.3

func ObjectKeys[T any](ctx CallbackScope[T], o Object[T]) (Value[T], error)

type ValueFactory

type ValueFactory[T any] interface {
	Undefined() Value[T]
	Null() Value[T]

	NewPromise() Promise[T]
	NewString(string) Value[T]
	NewBoolean(bool) Value[T]
	NewObject() Object[T]
	NewFunction(Callback[T]) Function[T]
	NewUint8Array([]byte) Value[T]
	NewUint32(uint32) Value[T]
	NewInt32(int32) Value[T]
	NewInt64(int64) Value[T]

	// NewArray creates a JavaScript array containing the values. If any value
	// is nil, it will become undefined in the resulting array.
	NewArray(...Value[T]) Value[T]
	// NewIterator returns an object implementing the [Iterator protocol]
	//
	// [Iterator protocol]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterator_protocol
	NewIterator(iter.Seq2[Value[T], error]) Value[T]

	NewTypeError(msg string) Error[T]

	// Create a JS throwable Error[T] value from a Go error
	NewError(err error) Error[T]

	// Wrap a JavaScript value in an Error[T], making it compatible with go
	// error values. The err argument is optional. See also [Error].
	NewValueError(v Value[T], err error) Error[T]

	JSONStringify(val Value[T]) string
	JSONParse(val string) (Value[T], error)
}

ValueFactory allows creating JavaScript values from Go values

type ValueResolver added in v0.7.2

type ValueResolver[T, U any] func(s Scope[U], value T) (Value[U], error)

Jump to

Keyboard shortcuts

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