Help us shape the future of Go! Take the 2026 Go Developer Survey

manifold

package module
v0.0.0-...-c0dd8db Latest Latest
Warning

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

Go to latest
Published: Feb 18, 2019 License: MIT Imports: 4 Imported by: 0

README

manifold

manifold is a toolkit for building v8/go APIs. It uses a fork of v8worker2 as the communication layer. This is a simple abstraction for message passing between Go and JS running in v8.

This is not meant to be used as complete bindings for v8, but rather a barebones library for communication and extensibility between the languages.

Usage

Manifold consists of very few interfaces which allow for the loading of importable modules, executing scripts and handling message passing. The message passing is handled by the Invoker interface which is invoked every time the JS sends a message. The message handler uses the simplistic signature of Invoke(fn string, args []string) []byte. The message is then handled and the raw bytes are sent back to the JS as an ArrayBuffer which is parsed as JSON upon receipt.

Execution Environment

There are only a few methods exposed to the JS runtime. v8worker2 provides for global print, send and recv methods. However, send is wrapped to provide for the builtin formatting of the messages. Additionally, due to the ability to load modules, base64 support is also provided. More builtin modules can easily be added. Builtin modules are loaded via the simpleassets command line tool.

Complete example

//go:generate simpleassets -p lib -o lib/gen.go -t "./" ./*js
package main

import (
	"fmt"
	"log"
	"os"

	"github.com/eliquious/manifold"
	"github.com/eliquious/manifold/examples/incr/lib"
)

func main() {
	logger := log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lmicroseconds)

	// New manifold
	m, err := manifold.New(&Invoker{})
	if err != nil {
		panic(err)
	}
	defer m.Dispose()

	LoadAssets(logger, m)
	ExecuteScript(logger, m)
}

// ExecuteScript runs the script.
func ExecuteScript(logger *log.Logger, r *manifold.Runtime) {
	src, err := lib.ReadAsset("index.js")
	if err != nil {
		log.Fatal(err)
	}
	err = r.Execute("index.js", string(src))
	if err != nil {
		log.Fatal(err)
	}
}

// LoadAssets loads requried assets.
func LoadAssets(logger *log.Logger, r *manifold.Runtime) {
	for _, asset := range lib.ListAssetNames() {
		if asset != "index.js" {
			src, err := lib.ReadAsset(asset)
			if err != nil {
				logger.Fatal(err)
			}
			if err := r.Load(asset, string(src)); err != nil {
				logger.Fatal(err)
			}
		}
	}
}

// Invoker managed the API and state
type Invoker struct {
	num int
}

// Invoke calls a function on the API
func (i *Invoker) Invoke(fn string, args []string) []byte {
	if fn == "incr" {
		return i.Incr()
	} else if fn == "decr" {
		return i.Decr()
	} else if fn == "get" {
		return manifold.EncodeResponse(i.num)
	}
	return manifold.Error(fmt.Errorf("undefined function: %s", fn))
}

// Incr increments the stored value
func (i *Invoker) Incr() []byte {
	i.num++
	return manifold.EncodeResponse(i.num)
}

// Decr decrements the stored value
func (i *Invoker) Decr() []byte {
	if i.num > 0 {
		i.num--
		return manifold.EncodeResponse(i.num)
	}
	return manifold.Error(fmt.Errorf("cannot decrement below 0"))
}

Future Work

The API needs to be updated to provide the ability to limit the size of the v8 runtime. This is currently possible via v8 flags and a heap listener it just needs to be supported on the API.

More builtin libraries could be added or optionally included in the runtime.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func EncodeResponse

func EncodeResponse(data interface{}) []byte

EncodeResponse marshals a response into JSON.

func Error

func Error(err error) []byte

Error marshals an error into JSON.

Types

type Invoker

type Invoker interface {
	Invoke(fn string, args []string) []byte
}

Invoker handles the invocation of a Golang function by v8.

type Request

type Request struct {
	Function string   `json:"fn"`
	Args     []string `json:"args"`
}

Request is a simple struct for passing data from v8 into Manifold.

type Response

type Response struct {
	Data  interface{} `json:"data"`
	Error string      `json:"err"`
}

Response is a simple struct for returning data to v8 after execution.

type Runtime

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

Runtime is the execution environment for v8 code. It resolves imports and manages communications between Go and v8.

func New

func New(i Invoker) (*Runtime, error)

New creates a new runtime with the given Invoker.

func (*Runtime) Dispose

func (r *Runtime) Dispose()

func (*Runtime) Execute

func (r *Runtime) Execute(main, code string) error

func (*Runtime) Load

func (r *Runtime) Load(scriptName string, code string) error

func (*Runtime) LoadAsset

func (r *Runtime) LoadAsset(scriptName string) error

func (*Runtime) Terminate

func (r *Runtime) Terminate()

type Store

type Store interface {
	ReadModule(scriptName string) (string, error)
	WriteModule(scriptName string, code string) error
}

Store stores module code in a virtual file system.

func MemStore

func MemStore() Store

MemStore creates a new in-memory module store

Directories

Path Synopsis
Code generated by simpleassets DO NOT EDIT.
Code generated by simpleassets DO NOT EDIT.
examples
incr command
incr/lib
Code generated by simpleassets DO NOT EDIT.
Code generated by simpleassets DO NOT EDIT.

Jump to

Keyboard shortcuts

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