v8go

package module
Version: v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Dec 8, 2021 License: BSD-3-Clause Imports: 14 Imported by: 50

README

Execute JavaScript from Go

Github release Go Report Card Go Reference CI V8 Build codecov FOSSA Status

V8 Gopher based on original artwork from the amazing Renee French

Usage

import v8 "rogchap.com/v8go"
Running a script
ctx := v8.NewContext() // creates a new V8 context with a new Isolate aka VM
ctx.RunScript("const add = (a, b) => a + b", "math.js") // executes a script on the global context
ctx.RunScript("const result = add(3, 4)", "main.js") // any functions previously added to the context can be called
val, _ := ctx.RunScript("result", "value.js") // return a value in JavaScript back to Go
fmt.Printf("addition result: %s", val)
One VM, many contexts
iso := v8.NewIsolate() // creates a new JavaScript VM
ctx1 := v8.NewContext(iso) // new context within the VM
ctx1.RunScript("const multiply = (a, b) => a * b", "math.js")

ctx2 := v8.NewContext(iso) // another context on the same VM
if _, err := ctx2.RunScript("multiply(3, 4)", "main.js"); err != nil {
  // this will error as multiply is not defined in this context
}
JavaScript function with Go callback
iso := v8.NewIsolate() // create a new VM
// a template that represents a JS function
printfn := v8.NewFunctionTemplate(iso, func(info *v8.FunctionCallbackInfo) *v8.Value {
    fmt.Printf("%v", info.Args()) // when the JS function is called this Go callback will execute
    return nil // you can return a value back to the JS caller if required
})
global := v8.NewObjectTemplate(iso) // a template that represents a JS Object
global.Set("print", printfn) // sets the "print" property of the Object to our function
ctx := v8.NewContext(iso, global) // new Context with the global Object set to our object template
ctx.RunScript("print('foo')", "print.js") // will execute the Go callback with a single argunent 'foo'
Update a JavaScript object from Go
ctx := v8.NewContext() // new context with a default VM
obj := ctx.Global() // get the global object from the context
obj.Set("version", "v1.0.0") // set the property "version" on the object
val, _ := ctx.RunScript("version", "version.js") // global object will have the property set within the JS VM
fmt.Printf("version: %s", val)

if obj.Has("version") { // check if a property exists on the object
    obj.Delete("version") // remove the property from the object
}
JavaScript errors
val, err := ctx.RunScript(src, filename)
if err != nil {
  e := err.(*v8.JSError) // JavaScript errors will be returned as the JSError struct
  fmt.Println(e.Message) // the message of the exception thrown
  fmt.Println(e.Location) // the filename, line number and the column where the error occured
  fmt.Println(e.StackTrace) // the full stack trace of the error, if available

  fmt.Printf("javascript error: %v", e) // will format the standard error message
  fmt.Printf("javascript stack trace: %+v", e) // will format the full error stack trace
}
Pre-compile context-independent scripts to speed-up execution times

For scripts that are large or are repeatedly run in different contexts, it is beneficial to compile the script once and used the cached data from that compilation to avoid recompiling every time you want to run it.

source := "const multiply = (a, b) => a * b"
iso1 := v8.NewIsolate() // creates a new JavaScript VM
ctx1 := v8.NewContext(iso1) // new context within the VM
script1, _ := iso1.CompileUnboundScript(source, "math.js", v8.CompileOptions{}) // compile script to get cached data
val, _ := script1.Run(ctx1)

cachedData := script1.CreateCodeCache()

iso2 := v8.NewIsolate() // create a new JavaScript VM
ctx2 := v8.NewContext(iso2) // new context within the VM

script2, _ := iso2.CompileUnboundScript(source, "math.js", v8.CompileOptions{CachedData: cachedData}) // compile script in new isolate with cached data
val, _ = script2.Run(ctx2)
Terminate long running scripts
vals := make(chan *v8.Value, 1)
errs := make(chan error, 1)

go func() {
    val, err := ctx.RunScript(script, "forever.js") // exec a long running script
    if err != nil {
        errs <- err
        return
    }
    vals <- val
}()

select {
case val := <- vals:
    // success
case err := <- errs:
    // javascript error
case <- time.After(200 * time.Milliseconds):
    vm := ctx.Isolate() // get the Isolate from the context
    vm.TerminateExecution() // terminate the execution
    err := <- errs // will get a termination error back from the running script
}
CPU Profiler
func createProfile() {
	iso := v8.NewIsolate()
	ctx := v8.NewContext(iso)
	cpuProfiler := v8.NewCPUProfiler(iso)

	cpuProfiler.StartProfiling("my-profile")

	ctx.RunScript(profileScript, "script.js") # this script is defined in cpuprofiler_test.go
	val, _ := ctx.Global().Get("start")
	fn, _ := val.AsFunction()
	fn.Call(ctx.Global())

	cpuProfile := cpuProfiler.StopProfiling("my-profile")

	printTree("", cpuProfile.GetTopDownRoot()) # helper function to print the profile
}

func printTree(nest string, node *v8.CPUProfileNode) {
	fmt.Printf("%s%s %s:%d:%d\n", nest, node.GetFunctionName(), node.GetScriptResourceName(), node.GetLineNumber(), node.GetColumnNumber())
	count := node.GetChildrenCount()
	if count == 0 {
		return
	}
	nest = fmt.Sprintf("%s  ", nest)
	for i := 0; i < count; i++ {
		printTree(nest, node.GetChild(i))
	}
}

// Output
// (root) :0:0
//   (program) :0:0
//   start script.js:23:15
//     foo script.js:15:13
//       delay script.js:12:15
//         loop script.js:1:14
//       bar script.js:13:13
//         delay script.js:12:15
//           loop script.js:1:14
//       baz script.js:14:13
//         delay script.js:12:15
//           loop script.js:1:14
//   (garbage collector) :0:0

Documentation

Go Reference & more examples: https://pkg.go.dev/rogchap.com/v8go

Support

If you would like to ask questions about this library or want to keep up-to-date with the latest changes and releases, please join the #v8go channel on Gophers Slack. Click here to join the Gophers Slack community!

Windows

There used to be Windows binary support. For further information see, PR #234.

The v8go library would welcome contributions from anyone able to get an external windows build of the V8 library linking with v8go, using the version of V8 checked out in the deps/v8 git submodule, and documentation of the process involved. This process will likely involve passing a linker flag when building v8go (e.g. using the CGO_LDFLAGS environment variable.

V8 dependency

V8 version: 9.0.257.18 (April 2021)

In order to make v8go usable as a standard Go package, prebuilt static libraries of V8 are included for Linux and macOS. you should not require to build V8 yourself.

Due to security concerns of binary blobs hiding malicious code, the V8 binary is built via CI ONLY.

Project Goals

To provide a high quality, idiomatic, Go binding to the V8 C++ API.

The API should match the original API as closely as possible, but with an API that Gophers (Go enthusiasts) expect. For example: using multiple return values to return both result and error from a function, rather than throwing an exception.

This project also aims to keep up-to-date with the latest (stable) release of V8.

License

FOSSA Status

Development

Recompile V8 with debug info and debug checks

Aside from data races, Go should be memory-safe and v8go should preserve this property by adding the necessary checks to return an error or panic on these unsupported code paths. Release builds of v8go don't include debugging information for the V8 library since it significantly adds to the binary size, slows down compilation and shouldn't be needed by users of v8go. However, if a v8go bug causes a crash (e.g. during new feature development) then it can be helpful to build V8 with debugging information to get a C++ backtrace with line numbers. The following steps will not only do that, but also enable V8 debug checking, which can help with catching misuse of the V8 API.

  1. Make sure to clone the projects submodules (ie. the V8's depot_tools project): git submodule update --init --recursive
  2. Build the V8 binary for your OS: deps/build.py --debug. V8 is a large project, and building the binary can take up to 30 minutes.
  3. Build the executable to debug, using go build for commands or go test -c for tests. You may need to add the -ldflags=-compressdwarf=false option to disable debug information compression so this information can be read by the debugger (e.g. lldb that comes with Xcode v12.5.1, the latest Xcode released at the time of writing)
  4. Run the executable with a debugger (e.g. lldb -- ./v8go.test -test.run TestThatIsCrashing, run to start execution then use bt to print a bracktrace after it breaks on a crash), since backtraces printed by Go or V8 don't currently include line number information.
Upgrading the V8 binaries

We have the upgradev8 workflow. The workflow is triggered every day or manually.

If the current v8_version is different from the latest stable version, the workflow takes care of fetching the latest stable v8 files and copying them into deps/include. The last step of the workflow opens a new PR with the branch name v8_upgrade/<v8-version> with all the changes.

The next steps are:

  1. The build is not yet triggered automatically. To trigger it manually, go to the V8 Build Github Action, Select "Run workflow", and select your pushed branch eg. v8_upgrade/<v8-version>.
  2. Once built, this should open 3 PRs against your branch to add the libv8.a for Linux (for x86_64) and macOS for x86_64 and arm64; merge these PRs into your branch. You are now ready to raise the PR against master with the latest version of V8.
Flushing after C/C++ standard library printing for debugging

When using the C/C++ standard library functions for printing (e.g. printf), then the output will be buffered by default. This can cause some confusion, especially because the test binary (created through go test) does not flush the buffer at exit (at the time of writing). When standard output is the terminal, then it will use line buffering and flush when a new line is printed, otherwise (e.g. if the output is redirected to a pipe or file) it will be fully buffered and not even flush at the end of a line. When the test binary is executed through go test . (e.g. instead of separately compiled with go test -c and run with ./v8go.test) Go may redirect standard output internally, resulting in standard output being fully buffered.

A simple way to avoid this problem is to flush the standard output stream after printing with the fflush(stdout); statement. Not relying on the flushing at exit can also help ensure the output is printed before a crash.

Local leak checking

Leak checking is automatically done in CI, but it can be useful to do locally to debug leaks.

Leak checking is done using the Leak Sanitizer which is a part of LLVM. As such, compiling with clang as the C/C++ compiler seems to produce more complete backtraces (unfortunately still only of the system stack at the time of writing).

For instance, on a Debian-based Linux system, you can use sudo apt-get install clang-12 to install a recent version of clang. Then CC and CXX environment variables are needed to use that compiler. With that compiler, the tests can be run as follows

CC=clang-12 CXX=clang++-12 go test -c --tags leakcheck && ./v8go.test

The separate compile and link commands are currently needed to get line numbers in the backtrace.

On macOS, leak checking isn't available with the version of clang that comes with Xcode, so a separate compiler installation is needed. For example, with homebrew, brew install llvm will install a version of clang with support for this. The ASAN_OPTIONS environment variable will also be needed to run the code with leak checking enabled, since it isn't enabled by default on macOS. E.g. with the homebrew installation of llvm, the tests can be run with

CXX=/usr/local/opt/llvm/bin/clang++ CC=/usr/local/opt/llvm/bin/clang go test -c --tags leakcheck -ldflags=-compressdwarf=false
ASAN_OPTIONS=detect_leaks=1 ./v8go.test

The -ldflags=-compressdwarf=false is currently (with clang 13) needed to get line numbers in the backtrace.

Formatting

Go has go fmt, C has clang-format. Any changes to the v8go.h|cc should be formated with clang-format with the "Chromium" Coding style. This can be done easily by running the go generate command.

brew install clang-format to install on macOS.


V8 Gopher image based on original artwork from the amazing Renee French.

Documentation

Overview

Package v8go provides an API to execute JavaScript.

Index

Examples

Constants

This section is empty.

Variables

Functions

func JSONStringify added in v0.5.0

func JSONStringify(ctx *Context, val Valuer) (string, error)

JSONStringify tries to stringify the JSON-serializable object value and returns it as string.

Example
package main

import (
	"fmt"

	v8 "rogchap.com/v8go"
)

func main() {
	ctx := v8.NewContext()
	defer ctx.Isolate().Dispose()
	defer ctx.Close()
	val, _ := v8.JSONParse(ctx, `{
		"a": 1,
		"b": "foo"
	}`)
	jsonStr, _ := v8.JSONStringify(ctx, val)
	fmt.Println(jsonStr)
}
Output:

{"a":1,"b":"foo"}

func SetFlags added in v0.6.0

func SetFlags(flags ...string)

SetFlags sets flags for V8. For possible flags: https://github.com/v8/v8/blob/master/src/flags/flag-definitions.h Flags are expected to be prefixed with `--`, for example: `--harmony`. Flags can be reverted using the `--no` prefix equivalent, for example: `--use_strict` vs `--nouse_strict`. Flags will affect all Isolates created, even after creation.

func Version

func Version() string

Version returns the version of the V8 Engine with the -v8go suffix

Types

type CPUProfile added in v0.7.0

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

func (*CPUProfile) Delete added in v0.7.0

func (c *CPUProfile) Delete()

Deletes the profile and removes it from CpuProfiler's list. All pointers to nodes previously returned become invalid.

func (*CPUProfile) GetDuration added in v0.7.0

func (c *CPUProfile) GetDuration() time.Duration

Returns the duration of the profile.

func (*CPUProfile) GetTitle added in v0.7.0

func (c *CPUProfile) GetTitle() string

Returns CPU profile title.

func (*CPUProfile) GetTopDownRoot added in v0.7.0

func (c *CPUProfile) GetTopDownRoot() *CPUProfileNode

Returns the root node of the top down call tree.

type CPUProfileNode added in v0.7.0

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

func (*CPUProfileNode) GetChild added in v0.7.0

func (c *CPUProfileNode) GetChild(index int) *CPUProfileNode

Retrieves a child node by index.

func (*CPUProfileNode) GetChildrenCount added in v0.7.0

func (c *CPUProfileNode) GetChildrenCount() int

func (*CPUProfileNode) GetColumnNumber added in v0.7.0

func (c *CPUProfileNode) GetColumnNumber() int

Returns number of the column where the function originates.

func (*CPUProfileNode) GetFunctionName added in v0.7.0

func (c *CPUProfileNode) GetFunctionName() string

Returns function name (empty string for anonymous functions.)

func (*CPUProfileNode) GetLineNumber added in v0.7.0

func (c *CPUProfileNode) GetLineNumber() int

Returns number of the line where the function originates.

func (*CPUProfileNode) GetParent added in v0.7.0

func (c *CPUProfileNode) GetParent() *CPUProfileNode

Retrieves the ancestor node, or nil if the root.

func (*CPUProfileNode) GetScriptResourceName added in v0.7.0

func (c *CPUProfileNode) GetScriptResourceName() string

Returns resource name for script from where the function originates.

type CPUProfiler added in v0.7.0

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

func NewCPUProfiler added in v0.7.0

func NewCPUProfiler(iso *Isolate) *CPUProfiler

CPUProfiler is used to control CPU profiling.

func (*CPUProfiler) Dispose added in v0.7.0

func (c *CPUProfiler) Dispose()

Dispose will dispose the profiler.

func (*CPUProfiler) StartProfiling added in v0.7.0

func (c *CPUProfiler) StartProfiling(title string)

StartProfiling starts collecting a CPU profile. Title may be an empty string. Several profiles may be collected at once. Attempts to start collecting several profiles with the same title are silently ignored.

func (*CPUProfiler) StopProfiling added in v0.7.0

func (c *CPUProfiler) StopProfiling(title string) *CPUProfile

Stops collecting CPU profile with a given title and returns it. If the title given is empty, finishes the last profile started.

type CompileMode added in v0.7.0

type CompileMode C.int

type CompileOptions added in v0.7.0

type CompileOptions struct {
	CachedData *CompilerCachedData

	Mode CompileMode
}

type CompilerCachedData added in v0.7.0

type CompilerCachedData struct {
	Bytes    []byte
	Rejected bool
}

type Context

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

Context is a global root execution environment that allows separate, unrelated, JavaScript applications to run in a single instance of V8.

Example
package main

import (
	"fmt"

	v8 "rogchap.com/v8go"
)

func main() {
	ctx := v8.NewContext()
	defer ctx.Isolate().Dispose()
	defer ctx.Close()
	ctx.RunScript("const add = (a, b) => a + b", "math.js")
	ctx.RunScript("const result = add(3, 4)", "main.js")
	val, _ := ctx.RunScript("result", "value.js")
	fmt.Println(val)
}
Output:

7
Example (GlobalTemplate)
package main

import (
	"fmt"

	v8 "rogchap.com/v8go"
)

func main() {
	iso := v8.NewIsolate()
	defer iso.Dispose()
	obj := v8.NewObjectTemplate(iso)
	obj.Set("version", "v1.0.0")
	ctx := v8.NewContext(iso, obj)
	defer ctx.Close()
	val, _ := ctx.RunScript("version", "main.js")
	fmt.Println(val)
}
Output:

v1.0.0
Example (Isolate)
package main

import (
	"fmt"

	v8 "rogchap.com/v8go"
)

func main() {
	iso := v8.NewIsolate()
	defer iso.Dispose()
	ctx1 := v8.NewContext(iso)
	defer ctx1.Close()
	ctx1.RunScript("const foo = 'bar'", "context_one.js")
	val, _ := ctx1.RunScript("foo", "foo.js")
	fmt.Println(val)

	ctx2 := v8.NewContext(iso)
	defer ctx2.Close()
	_, err := ctx2.RunScript("foo", "context_two.js")
	fmt.Println(err)
}
Output:

bar
ReferenceError: foo is not defined

func NewContext

func NewContext(opt ...ContextOption) *Context

NewContext creates a new JavaScript context; if no Isolate is passed as a ContextOption than a new Isolate will be created.

func (*Context) Close added in v0.2.0

func (c *Context) Close()

Close will dispose the context and free the memory. Access to any values associated with the context after calling Close may panic.

func (*Context) Global added in v0.5.0

func (c *Context) Global() *Object

Global returns the global proxy object. Global proxy object is a thin wrapper whose prototype points to actual context's global object with the properties like Object, etc. This is done that way for security reasons. Please note that changes to global proxy object prototype most probably would break the VM — V8 expects only global object as a prototype of global proxy object.

func (*Context) Isolate

func (c *Context) Isolate() *Isolate

Isolate gets the current context's parent isolate.An error is returned if the isolate has been terninated.

func (*Context) PerformMicrotaskCheckpoint added in v0.6.0

func (c *Context) PerformMicrotaskCheckpoint()

PerformMicrotaskCheckpoint runs the default MicrotaskQueue until empty. This is used to make progress on Promises.

func (*Context) RunScript

func (c *Context) RunScript(source string, origin string) (*Value, error)

RunScript executes the source JavaScript; origin (a.k.a. filename) provides a reference for the script and used in the stack trace if there is an error. error will be of type `JSError` if not nil.

type ContextOption added in v0.5.0

type ContextOption interface {
	// contains filtered or unexported methods
}

ContextOption sets options such as Isolate and Global Template to the NewContext

type Function added in v0.6.0

type Function struct {
	*Value
}

Function is a JavaScript function.

func (*Function) Call added in v0.6.0

func (fn *Function) Call(recv Valuer, args ...Valuer) (*Value, error)

Call this JavaScript function with the given arguments.

func (*Function) NewInstance added in v0.7.0

func (fn *Function) NewInstance(args ...Valuer) (*Object, error)

Invoke a constructor function to create an object instance.

func (*Function) SourceMapUrl added in v0.7.0

func (fn *Function) SourceMapUrl() *Value

Return the source map url for a function.

type FunctionCallback added in v0.5.0

type FunctionCallback func(info *FunctionCallbackInfo) *Value

FunctionCallback is a callback that is executed in Go when a function is executed in JS.

type FunctionCallbackInfo added in v0.5.0

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

FunctionCallbackInfo is the argument that is passed to a FunctionCallback.

func (*FunctionCallbackInfo) Args added in v0.5.0

func (i *FunctionCallbackInfo) Args() []*Value

Args returns a slice of the value arguments that are passed to the JS function.

func (*FunctionCallbackInfo) Context added in v0.5.0

func (i *FunctionCallbackInfo) Context() *Context

Context is the current context that the callback is being executed in.

func (*FunctionCallbackInfo) This added in v0.7.0

func (i *FunctionCallbackInfo) This() *Object

This returns the receiver object "this".

type FunctionTemplate added in v0.5.0

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

FunctionTemplate is used to create functions at runtime. There can only be one function created from a FunctionTemplate in a context. The lifetime of the created function is equal to the lifetime of the context.

Example
package main

import (
	"fmt"

	v8 "rogchap.com/v8go"
)

func main() {
	iso := v8.NewIsolate()
	defer iso.Dispose()
	global := v8.NewObjectTemplate(iso)
	printfn := v8.NewFunctionTemplate(iso, func(info *v8.FunctionCallbackInfo) *v8.Value {
		fmt.Printf("%+v\n", info.Args())
		return nil
	})
	global.Set("print", printfn, v8.ReadOnly)
	ctx := v8.NewContext(iso, global)
	defer ctx.Close()
	ctx.RunScript("print('foo', 'bar', 0, 1)", "")
}
Output:

[foo bar 0 1]
Example (Fetch)
package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"

	v8 "rogchap.com/v8go"
)

func main() {
	iso := v8.NewIsolate()
	defer iso.Dispose()
	global := v8.NewObjectTemplate(iso)

	fetchfn := v8.NewFunctionTemplate(iso, func(info *v8.FunctionCallbackInfo) *v8.Value {
		args := info.Args()
		url := args[0].String()

		resolver, _ := v8.NewPromiseResolver(info.Context())

		go func() {
			res, _ := http.Get(url)
			body, _ := ioutil.ReadAll(res.Body)
			val, _ := v8.NewValue(iso, string(body))
			resolver.Resolve(val)
		}()
		return resolver.GetPromise().Value
	})
	global.Set("fetch", fetchfn, v8.ReadOnly)

	ctx := v8.NewContext(iso, global)
	defer ctx.Close()
	val, _ := ctx.RunScript("fetch('https://rogchap.com/v8go')", "")
	prom, _ := val.AsPromise()

	// wait for the promise to resolve
	for prom.State() == v8.Pending {
		continue
	}
	fmt.Printf("%s\n", strings.Split(prom.Result().String(), "\n")[0])
}
Output:

<!DOCTYPE html>

func NewFunctionTemplate added in v0.5.0

func NewFunctionTemplate(iso *Isolate, callback FunctionCallback) *FunctionTemplate

NewFunctionTemplate creates a FunctionTemplate for a given callback.

func (*FunctionTemplate) GetFunction added in v0.6.0

func (tmpl *FunctionTemplate) GetFunction(ctx *Context) *Function

GetFunction returns an instance of this function template bound to the given context.

func (FunctionTemplate) Set added in v0.5.0

func (t FunctionTemplate) Set(name string, val interface{}, attributes ...PropertyAttribute) error

Set adds a property to each instance created by this template. The property must be defined either as a primitive value, or a template. If the value passed is a Go supported primitive (string, int32, uint32, int64, uint64, float64, big.Int) then a value will be created and set as the value property.

type HeapStatistics added in v0.2.0

type HeapStatistics struct {
	TotalHeapSize            uint64
	TotalHeapSizeExecutable  uint64
	TotalPhysicalSize        uint64
	TotalAvailableSize       uint64
	UsedHeapSize             uint64
	HeapSizeLimit            uint64
	MallocedMemory           uint64
	ExternalMemory           uint64
	PeakMallocedMemory       uint64
	NumberOfNativeContexts   uint64
	NumberOfDetachedContexts uint64
}

HeapStatistics represents V8 isolate heap statistics

type Isolate

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

Isolate is a JavaScript VM instance with its own heap and garbage collector. Most applications will create one isolate with many V8 contexts for execution.

func NewIsolate

func NewIsolate() *Isolate

NewIsolate creates a new V8 isolate. Only one thread may access a given isolate at a time, but different threads may access different isolates simultaneously. When an isolate is no longer used its resources should be freed by calling iso.Dispose(). An *Isolate can be used as a v8go.ContextOption to create a new Context, rather than creating a new default Isolate.

func (*Isolate) Close deprecated added in v0.2.0

func (i *Isolate) Close()

Deprecated: use `iso.Dispose()`.

func (*Isolate) CompileUnboundScript added in v0.7.0

func (i *Isolate) CompileUnboundScript(source, origin string, opts CompileOptions) (*UnboundScript, error)

CompileUnboundScript will create an UnboundScript (i.e. context-indepdent) using the provided source JavaScript, origin (a.k.a. filename), and options. If options contain a non-null CachedData, compilation of the script will use that code cache. error will be of type `JSError` if not nil.

func (*Isolate) Dispose added in v0.5.0

func (i *Isolate) Dispose()

Dispose will dispose the Isolate VM; subsequent calls will panic.

func (*Isolate) GetHeapStatistics added in v0.2.0

func (i *Isolate) GetHeapStatistics() HeapStatistics

GetHeapStatistics returns heap statistics for an isolate.

func (*Isolate) IsExecutionTerminating added in v0.7.0

func (i *Isolate) IsExecutionTerminating() bool

IsExecutionTerminating returns whether V8 is currently terminating Javascript execution. If true, there are still JavaScript frames on the stack and the termination exception is still active.

func (*Isolate) TerminateExecution

func (i *Isolate) TerminateExecution()

TerminateExecution terminates forcefully the current thread of JavaScript execution in the given isolate.

func (*Isolate) ThrowException added in v0.7.0

func (i *Isolate) ThrowException(value *Value) *Value

ThrowException schedules an exception to be thrown when returning to JavaScript. When an exception has been scheduled it is illegal to invoke any JavaScript operation; the caller must return immediately and only after the exception has been handled does it become legal to invoke JavaScript operations.

type JSError

type JSError struct {
	Message    string
	Location   string
	StackTrace string
}

JSError is an error that is returned if there is are any JavaScript exceptions handled in the context. When used with the fmt verb `%+v`, will output the JavaScript stack trace, if available.

func (*JSError) Error

func (e *JSError) Error() string

func (*JSError) Format

func (e *JSError) Format(s fmt.State, verb rune)

Format implements the fmt.Formatter interface to provide a custom formatter primarily to output the javascript stack trace with %+v

type Object added in v0.5.0

type Object struct {
	*Value
}

Object is a JavaScript object (ECMA-262, 4.3.3)

Example (Global)
package main

import (
	"fmt"

	v8 "rogchap.com/v8go"
)

func main() {
	iso := v8.NewIsolate()
	defer iso.Dispose()
	ctx := v8.NewContext(iso)
	defer ctx.Close()
	global := ctx.Global()

	console := v8.NewObjectTemplate(iso)
	logfn := v8.NewFunctionTemplate(iso, func(info *v8.FunctionCallbackInfo) *v8.Value {
		fmt.Println(info.Args()[0])
		return nil
	})
	console.Set("log", logfn)
	consoleObj, _ := console.NewInstance(ctx)

	global.Set("console", consoleObj)
	ctx.RunScript("console.log('foo')", "")
}
Output:

foo

func (*Object) Delete added in v0.5.0

func (o *Object) Delete(key string) bool

Delete returns true if successful in deleting a named property on the object.

func (*Object) DeleteIdx added in v0.5.0

func (o *Object) DeleteIdx(idx uint32) bool

DeleteIdx returns true if successful in deleting a value at a given index of the object.

func (*Object) Get added in v0.5.0

func (o *Object) Get(key string) (*Value, error)

Get tries to get a Value for a given Object property key.

func (*Object) GetIdx added in v0.5.0

func (o *Object) GetIdx(idx uint32) (*Value, error)

GetIdx tries to get a Value at a give Object index.

func (*Object) GetInternalField added in v0.7.0

func (o *Object) GetInternalField(idx uint32) *Value

GetInternalField gets the Value set by SetInternalField for the given index or the JS undefined value if the index hadn't been set. Panics if given an out of range index.

func (*Object) Has added in v0.5.0

func (o *Object) Has(key string) bool

Has calls the abstract operation HasProperty(O, P) described in ECMA-262, 7.3.10. Returns true, if the object has the property, either own or on the prototype chain.

func (*Object) HasIdx added in v0.5.0

func (o *Object) HasIdx(idx uint32) bool

HasIdx returns true if the object has a value at the given index.

func (*Object) InternalFieldCount added in v0.7.0

func (o *Object) InternalFieldCount() uint32

InternalFieldCount returns the number of internal fields this Object has.

func (*Object) MethodCall added in v0.7.0

func (o *Object) MethodCall(methodName string, args ...Valuer) (*Value, error)

func (*Object) Set added in v0.5.0

func (o *Object) Set(key string, val interface{}) error

Set will set a property on the Object to a given value. Supports all value types, eg: Object, Array, Date, Set, Map etc If the value passed is a Go supported primitive (string, int32, uint32, int64, uint64, float64, big.Int) then a *Value will be created and set as the value property.

func (*Object) SetIdx added in v0.5.0

func (o *Object) SetIdx(idx uint32, val interface{}) error

Set will set a given index on the Object to a given value. Supports all value types, eg: Object, Array, Date, Set, Map etc If the value passed is a Go supported primitive (string, int32, uint32, int64, uint64, float64, big.Int) then a *Value will be created and set as the value property.

func (*Object) SetInternalField added in v0.7.0

func (o *Object) SetInternalField(idx uint32, val interface{}) error

SetInternalField sets the value of an internal field for an ObjectTemplate instance. Panics if the index isn't in the range set by (*ObjectTemplate).SetInternalFieldCount.

type ObjectTemplate added in v0.5.0

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

ObjectTemplate is used to create objects at runtime. Properties added to an ObjectTemplate are added to each object created from the ObjectTemplate.

func NewObjectTemplate added in v0.5.0

func NewObjectTemplate(iso *Isolate) *ObjectTemplate

NewObjectTemplate creates a new ObjectTemplate. The *ObjectTemplate can be used as a v8go.ContextOption to create a global object in a Context.

func (*ObjectTemplate) InternalFieldCount added in v0.7.0

func (o *ObjectTemplate) InternalFieldCount() uint32

InternalFieldCount returns the number of internal fields that instances of this template will have.

func (*ObjectTemplate) NewInstance added in v0.5.0

func (o *ObjectTemplate) NewInstance(ctx *Context) (*Object, error)

NewInstance creates a new Object based on the template.

func (ObjectTemplate) Set added in v0.5.0

func (t ObjectTemplate) Set(name string, val interface{}, attributes ...PropertyAttribute) error

Set adds a property to each instance created by this template. The property must be defined either as a primitive value, or a template. If the value passed is a Go supported primitive (string, int32, uint32, int64, uint64, float64, big.Int) then a value will be created and set as the value property.

func (*ObjectTemplate) SetInternalFieldCount added in v0.7.0

func (o *ObjectTemplate) SetInternalFieldCount(fieldCount uint32)

SetInternalFieldCount sets the number of internal fields that instances of this template will have.

type Promise added in v0.6.0

type Promise struct {
	*Object
}

Promise is the JavaScript promise object defined in ES6

func (*Promise) Catch added in v0.6.0

func (p *Promise) Catch(cb FunctionCallback) *Promise

Catch invokes the given function if the promise is rejected. See Then for other details.

func (*Promise) Result added in v0.6.0

func (p *Promise) Result() *Value

Result is the value result of the Promise. The Promise must NOT be in a Pending state, otherwise may panic. Call promise.State() to validate state before calling for the result.

func (*Promise) State added in v0.6.0

func (p *Promise) State() PromiseState

State returns the current state of the Promise.

func (*Promise) Then added in v0.6.0

func (p *Promise) Then(cbs ...FunctionCallback) *Promise

Then accepts 1 or 2 callbacks. The first is invoked when the promise has been fulfilled. The second is invoked when the promise has been rejected. The returned Promise resolves after the callback finishes execution.

V8 only invokes the callback when processing "microtasks". The default MicrotaskPolicy processes them when the call depth decreases to 0. Call (*Context).PerformMicrotaskCheckpoint to trigger it manually.

type PromiseResolver added in v0.6.0

type PromiseResolver struct {
	*Object
	// contains filtered or unexported fields
}

PromiseResolver is the resolver object for the promise. Most cases will create a new PromiseResolver and return the associated Promise from the resolver.

func NewPromiseResolver added in v0.6.0

func NewPromiseResolver(ctx *Context) (*PromiseResolver, error)

MewPromiseResolver creates a new Promise resolver for the given context. The associated Promise will be in a Pending state.

func (*PromiseResolver) GetPromise added in v0.6.0

func (r *PromiseResolver) GetPromise() *Promise

GetPromise returns the associated Promise object for this resolver. The Promise object is unique to the resolver and returns the same object on multiple calls.

func (*PromiseResolver) Reject added in v0.6.0

func (r *PromiseResolver) Reject(err *Value) bool

Reject invokes the Promise reject state with the given value. The Promise state will transition from Pending to Rejected.

func (*PromiseResolver) Resolve added in v0.6.0

func (r *PromiseResolver) Resolve(val Valuer) bool

Resolve invokes the Promise resolve state with the given value. The Promise state will transition from Pending to Fulfilled.

type PromiseState added in v0.6.0

type PromiseState int

PromiseState is the state of the Promise.

const (
	Pending PromiseState = iota
	Fulfilled
	Rejected
)

type PropertyAttribute added in v0.5.0

type PropertyAttribute uint8

PropertyAttribute are the attribute flags for a property on an Object. Typical usage when setting an Object or TemplateObject property, and can also be validated when accessing a property.

const (
	// None.
	None PropertyAttribute = 0
	// ReadOnly, ie. not writable.
	ReadOnly PropertyAttribute = 1 << iota
	// DontEnum, ie. not enumerable.
	DontEnum
	// DontDelete, ie. not configurable.
	DontDelete
)

type UnboundScript added in v0.7.0

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

func (*UnboundScript) CreateCodeCache added in v0.7.0

func (u *UnboundScript) CreateCodeCache() *CompilerCachedData

Create a code cache from the unbound script.

func (*UnboundScript) Run added in v0.7.0

func (u *UnboundScript) Run(ctx *Context) (*Value, error)

Run will bind the unbound script to the provided context and run it. If the context provided does not belong to the same isolate that the script was compiled in, Run will panic. If an error occurs, it will be of type `JSError`.

type Value

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

Value represents all Javascript values and objects

func JSONParse added in v0.5.0

func JSONParse(ctx *Context, str string) (*Value, error)

JSONParse tries to parse the string and returns it as *Value if successful. Any JS errors will be returned as `JSError`.

Example
package main

import (
	"fmt"

	v8 "rogchap.com/v8go"
)

func main() {
	ctx := v8.NewContext()
	defer ctx.Isolate().Dispose()
	defer ctx.Close()
	val, _ := v8.JSONParse(ctx, `{"foo": "bar"}`)
	fmt.Println(val)
}
Output:

[object Object]

func NewValue added in v0.5.0

func NewValue(iso *Isolate, val interface{}) (*Value, error)

NewValue will create a primitive value. Supported values types to create are:

string -> V8::String
int32 -> V8::Integer
uint32 -> V8::Integer
bool -> V8::Boolean
int64 -> V8::BigInt
uint64 -> V8::BigInt
bool -> V8::Boolean
*big.Int -> V8::BigInt

func Null added in v0.7.0

func Null(iso *Isolate) *Value

Null returns the `null` JS value

func Undefined added in v0.7.0

func Undefined(iso *Isolate) *Value

Undefined returns the `undefined` JS value

func (*Value) ArrayIndex added in v0.4.0

func (v *Value) ArrayIndex() (idx uint32, ok bool)

ArrayIndex attempts to converts a string to an array index. Returns ok false if conversion fails.

func (*Value) AsFunction added in v0.6.0

func (v *Value) AsFunction() (*Function, error)

func (*Value) AsObject added in v0.5.0

func (v *Value) AsObject() (*Object, error)

AsObject will cast the value to the Object type. If the value is not an Object then an error is returned. Use `value.Object()` to do the JS equivalent of `Object(value)`.

func (*Value) AsPromise added in v0.6.0

func (v *Value) AsPromise() (*Promise, error)

func (*Value) BigInt added in v0.5.0

func (v *Value) BigInt() *big.Int

BigInt perform the equivalent of `BigInt(value)` in JS.

func (*Value) Boolean added in v0.4.0

func (v *Value) Boolean() bool

Boolean perform the equivalent of `Boolean(value)` in JS. This can never fail.

func (*Value) DetailString added in v0.4.0

func (v *Value) DetailString() string

DetailString provide a string representation of this value usable for debugging.

func (*Value) Format added in v0.4.0

func (v *Value) Format(s fmt.State, verb rune)

Format implements the fmt.Formatter interface to provide a custom formatter primarily to output the detail string (for debugging) with `%+v` verb.

func (*Value) Int32 added in v0.4.0

func (v *Value) Int32() int32

Int32 perform the equivalent of `Number(value)` in JS and convert the result to a signed 32-bit integer by performing the steps in https://tc39.es/ecma262/#sec-toint32.

func (*Value) Integer added in v0.4.0

func (v *Value) Integer() int64

Integer perform the equivalent of `Number(value)` in JS and convert the result to an integer. Negative values are rounded up, positive values are rounded down. NaN is converted to 0. Infinite values yield undefined results.

func (*Value) IsArgumentsObject added in v0.4.0

func (v *Value) IsArgumentsObject() bool

IsArgumentsObject returns true if this value is an Arguments object.

func (*Value) IsArray added in v0.4.0

func (v *Value) IsArray() bool

IsArray returns true if this value is an array. Note that it will return false for a `Proxy` of an array.

func (*Value) IsArrayBuffer added in v0.4.0

func (v *Value) IsArrayBuffer() bool

IsArrayBuffer returns true if this value is an `ArrayBuffer`.

func (*Value) IsArrayBufferView added in v0.4.0

func (v *Value) IsArrayBufferView() bool

IsArrayBufferView returns true if this value is an `ArrayBufferView`.

func (*Value) IsAsyncFunction added in v0.4.0

func (v *Value) IsAsyncFunction() bool

IsAsyncFunc returns true if this value is an async function.

func (*Value) IsBigInt added in v0.4.0

func (v *Value) IsBigInt() bool

IsBigInt returns true if this value is a bigint. This is equivalent to `typeof value === 'bigint'` in JS.

func (*Value) IsBigInt64Array added in v0.4.0

func (v *Value) IsBigInt64Array() bool

IsBigInt64Array returns true if this value is a `BigInt64Array`.

func (*Value) IsBigIntObject added in v0.4.0

func (v *Value) IsBigIntObject() bool

IsBigIntObject returns true if this value is a BigInt object.

func (*Value) IsBigUint64Array added in v0.4.0

func (v *Value) IsBigUint64Array() bool

IsBigUint64Array returns true if this value is a BigUint64Array`.

func (*Value) IsBoolean added in v0.4.0

func (v *Value) IsBoolean() bool

IsBoolean returns true if this value is boolean. This is equivalent to `typeof value === 'boolean'` in JS.

func (*Value) IsDataView added in v0.4.0

func (v *Value) IsDataView() bool

IsDataView returns true if this value is a `DataView`.

func (*Value) IsDate added in v0.4.0

func (v *Value) IsDate() bool

IsDate returns true if this value is a `Date`.

func (*Value) IsExternal added in v0.4.0

func (v *Value) IsExternal() bool

IsExternal returns true if this value is an `External` object.

func (*Value) IsFalse added in v0.4.0

func (v *Value) IsFalse() bool

IsFalse returns true if this value is false. This is not the same as `!BooleanValue()`. The latter performs a conversion to boolean, i.e. the result of `!Boolean(value)` in JS, whereas this checks `value === false`.

func (*Value) IsFloat32Array added in v0.4.0

func (v *Value) IsFloat32Array() bool

IsFloat32Array returns true if this value is a `Float32Array`.

func (*Value) IsFloat64Array added in v0.4.0

func (v *Value) IsFloat64Array() bool

IsFloat64Array returns true if this value is a `Float64Array`.

func (*Value) IsFunction added in v0.4.0

func (v *Value) IsFunction() bool

IsFunction returns true if this value is a function. This is equivalent to `typeof value === 'function'` in JS.

func (*Value) IsGeneratorFunction added in v0.4.0

func (v *Value) IsGeneratorFunction() bool

Is IsGeneratorFunc returns true if this value is a Generator function.

func (*Value) IsGeneratorObject added in v0.4.0

func (v *Value) IsGeneratorObject() bool

IsGeneratorObject returns true if this value is a Generator object (iterator).

func (*Value) IsInt16Array added in v0.4.0

func (v *Value) IsInt16Array() bool

IsInt16Array returns true if this value is an `Int16Array`.

func (*Value) IsInt32 added in v0.4.0

func (v *Value) IsInt32() bool

IsInt32 returns true if this value is a 32-bit signed integer.

func (*Value) IsInt32Array added in v0.4.0

func (v *Value) IsInt32Array() bool

IsInt32Array returns true if this value is an `Int32Array`.

func (*Value) IsInt8Array added in v0.4.0

func (v *Value) IsInt8Array() bool

IsInt8Array returns true if this value is an `Int8Array`.

func (*Value) IsMap added in v0.4.0

func (v *Value) IsMap() bool

IsMap returns true if this value is a `Map`.

func (*Value) IsMapIterator added in v0.4.0

func (v *Value) IsMapIterator() bool

IsMapIterator returns true if this value is a `Map` Iterator.

func (*Value) IsModuleNamespaceObject added in v0.4.0

func (v *Value) IsModuleNamespaceObject() bool

IsModuleNamespaceObject returns true if the value is a `Module` Namespace `Object`.

func (*Value) IsName added in v0.4.0

func (v *Value) IsName() bool

IsName returns true if this value is a symbol or a string. This is equivalent to `typeof value === 'string' || typeof value === 'symbol'` in JS.

func (*Value) IsNativeError added in v0.4.0

func (v *Value) IsNativeError() bool

IsNativeError returns true if this value is a NativeError.

func (*Value) IsNull added in v0.4.0

func (v *Value) IsNull() bool

IsNull returns true if this value is the null value. See ECMA-262 4.3.11.

func (*Value) IsNullOrUndefined added in v0.4.0

func (v *Value) IsNullOrUndefined() bool

IsNullOrUndefined returns true if this value is either the null or the undefined value. See ECMA-262 4.3.11. and 4.3.12 This is equivalent to `value == null` in JS.

func (*Value) IsNumber added in v0.4.0

func (v *Value) IsNumber() bool

IsNumber returns true if this value is a number. This is equivalent to `typeof value === 'number'` in JS.

func (*Value) IsNumberObject added in v0.4.0

func (v *Value) IsNumberObject() bool

IsNumberObject returns true if this value is a `Number` object.

func (*Value) IsObject added in v0.4.0

func (v *Value) IsObject() bool

IsObject returns true if this value is an object.

func (*Value) IsPromise added in v0.4.0

func (v *Value) IsPromise() bool

IsPromise returns true if this value is a `Promise`.

func (*Value) IsProxy added in v0.4.0

func (v *Value) IsProxy() bool

IsProxy returns true if this value is a JavaScript `Proxy`.

func (*Value) IsRegExp added in v0.4.0

func (v *Value) IsRegExp() bool

IsRegExp returns true if this value is a `RegExp`.

func (*Value) IsSet added in v0.4.0

func (v *Value) IsSet() bool

IsSet returns true if this value is a `Set`.

func (*Value) IsSetIterator added in v0.4.0

func (v *Value) IsSetIterator() bool

IsSetIterator returns true if this value is a `Set` Iterator.

func (*Value) IsSharedArrayBuffer added in v0.4.0

func (v *Value) IsSharedArrayBuffer() bool

IsSharedArrayBuffer returns true if this value is a `SharedArrayBuffer`.

func (*Value) IsString added in v0.4.0

func (v *Value) IsString() bool

IsString returns true if this value is an instance of the String type. See ECMA-262 8.4. This is equivalent to `typeof value === 'string'` in JS.

func (*Value) IsStringObject added in v0.4.0

func (v *Value) IsStringObject() bool

IsStringObject returns true if this value is a `String` object.

func (*Value) IsSymbol added in v0.4.0

func (v *Value) IsSymbol() bool

IsSymbol returns true if this value is a symbol. This is equivalent to `typeof value === 'symbol'` in JS.

func (*Value) IsSymbolObject added in v0.4.0

func (v *Value) IsSymbolObject() bool

IsSymbolObject returns true if this value is a `Symbol` object.

func (*Value) IsTrue added in v0.4.0

func (v *Value) IsTrue() bool

IsTrue returns true if this value is true. This is not the same as `BooleanValue()`. The latter performs a conversion to boolean, i.e. the result of `Boolean(value)` in JS, whereas this checks `value === true`.

func (*Value) IsTypedArray added in v0.4.0

func (v *Value) IsTypedArray() bool

IsTypedArray returns true if this value is one of TypedArrays.

func (*Value) IsUint16Array added in v0.4.0

func (v *Value) IsUint16Array() bool

IsUint16Array returns true if this value is an `Uint16Array`.

func (*Value) IsUint32 added in v0.4.0

func (v *Value) IsUint32() bool

IsUint32 returns true if this value is a 32-bit unsigned integer.

func (*Value) IsUint32Array added in v0.4.0

func (v *Value) IsUint32Array() bool

IsUint32Array returns true if this value is an `Uint32Array`.

func (*Value) IsUint8Array added in v0.4.0

func (v *Value) IsUint8Array() bool

IsUint8Array returns true if this value is an `Uint8Array`.

func (*Value) IsUint8ClampedArray added in v0.4.0

func (v *Value) IsUint8ClampedArray() bool

IsUint8ClampedArray returns true if this value is an `Uint8ClampedArray`.

func (*Value) IsUndefined added in v0.4.0

func (v *Value) IsUndefined() bool

IsUndefined returns true if this value is the undefined value. See ECMA-262 4.3.10.

func (*Value) IsWasmModuleObject added in v0.4.0

func (v *Value) IsWasmModuleObject() bool

IsWasmModuleObject returns true if this value is a `WasmModuleObject`.

func (*Value) IsWeakMap added in v0.4.0

func (v *Value) IsWeakMap() bool

IsWeakMap returns true if this value is a `WeakMap`.

func (*Value) IsWeakSet added in v0.4.0

func (v *Value) IsWeakSet() bool

IsWeakSet returns true if this value is a `WeakSet`.

func (*Value) MarshalJSON added in v0.5.0

func (v *Value) MarshalJSON() ([]byte, error)

MarshalJSON implements the json.Marshaler interface.

func (*Value) Number added in v0.4.0

func (v *Value) Number() float64

Number perform the equivalent of `Number(value)` in JS.

func (*Value) Object added in v0.5.0

func (v *Value) Object() *Object

Object perform the equivalent of Object(value) in JS. To just cast this value as an Object use AsObject() instead.

func (*Value) SameValue added in v0.7.0

func (v *Value) SameValue(other *Value) bool

SameValue returns true if the other value is the same value. This is equivalent to `Object.is(v, other)` in JS.

func (*Value) String

func (v *Value) String() string

String perform the equivalent of `String(value)` in JS. Primitive values are returned as-is, objects will return `[object Object]` and functions will print their definition.

func (*Value) Uint32 added in v0.4.0

func (v *Value) Uint32() uint32

Uint32 perform the equivalent of `Number(value)` in JS and convert the result to an unsigned 32-bit integer by performing the steps in https://tc39.es/ecma262/#sec-touint32.

type Valuer added in v0.5.0

type Valuer interface {
	// contains filtered or unexported methods
}

Valuer is an interface that reperesents anything that extends from a Value eg. Object, Array, Date etc

Directories

Path Synopsis
deps
darwin_arm64
Package darwin_arm64 is required to provide support for vendoring modules DO NOT REMOVE
Package darwin_arm64 is required to provide support for vendoring modules DO NOT REMOVE
darwin_x86_64
Package darwin_x86_64 is required to provide support for vendoring modules DO NOT REMOVE
Package darwin_x86_64 is required to provide support for vendoring modules DO NOT REMOVE
include
Generated by deps/upgrade_v8.py, DO NOT REMOVE/EDIT MANUALLY.
Generated by deps/upgrade_v8.py, DO NOT REMOVE/EDIT MANUALLY.
include/cppgc
Generated by deps/upgrade_v8.py, DO NOT REMOVE/EDIT MANUALLY.
Generated by deps/upgrade_v8.py, DO NOT REMOVE/EDIT MANUALLY.
include/libplatform
Generated by deps/upgrade_v8.py, DO NOT REMOVE/EDIT MANUALLY.
Generated by deps/upgrade_v8.py, DO NOT REMOVE/EDIT MANUALLY.
linux_x86_64
Package linux_x86_64 is required to provide support for vendoring modules DO NOT REMOVE
Package linux_x86_64 is required to provide support for vendoring modules DO NOT REMOVE

Jump to

Keyboard shortcuts

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