mirror of
https://github.com/google/go-jsonnet.git
synced 2025-09-29 09:21:03 +02:00
Add wasm build
This commit is contained in:
parent
e3c7ddab44
commit
2f2f6d664f
2
.gitignore
vendored
2
.gitignore
vendored
@ -30,3 +30,5 @@ gojsonnet.egg-info/
|
|||||||
/jsonnet-lint
|
/jsonnet-lint
|
||||||
/jsonnet-deps
|
/jsonnet-deps
|
||||||
/builtin-benchmark-results
|
/builtin-benchmark-results
|
||||||
|
|
||||||
|
libjsonnet.wasm
|
||||||
|
12
README.md
12
README.md
@ -112,6 +112,18 @@ For additional target platform names, see the per-Go release definitions [here](
|
|||||||
|
|
||||||
Additionally if any files were moved around, see the section [Keeping the Bazel files up to date](#keeping-the-bazel-files-up-to-date).
|
Additionally if any files were moved around, see the section [Keeping the Bazel files up to date](#keeping-the-bazel-files-up-to-date).
|
||||||
|
|
||||||
|
## Building libjsonnet.wasm
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GOOS=js GOARCH=wasm go build -o libjsonnet.wasm ./cmd/wasm
|
||||||
|
```
|
||||||
|
|
||||||
|
Or if using bazel:
|
||||||
|
|
||||||
|
```
|
||||||
|
bazel build //cmd/wasm:libjsonnet.wasm
|
||||||
|
```
|
||||||
|
|
||||||
## Running tests
|
## Running tests
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
22
cmd/wasm/BUILD.bazel
Normal file
22
cmd/wasm/BUILD.bazel
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = [
|
||||||
|
"main.go",
|
||||||
|
],
|
||||||
|
importpath = "github.com/google/go-jsonnet/cmd/wasm",
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
deps = [
|
||||||
|
"//:go_default_library",
|
||||||
|
"//internal/formatter:go_default_library",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
go_binary(
|
||||||
|
name = "libjsonnet.wasm",
|
||||||
|
embed = [":go_default_library"],
|
||||||
|
goarch = "wasm",
|
||||||
|
goos = "js",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
143
cmd/wasm/main.go
Normal file
143
cmd/wasm/main.go
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
//go:build js && wasm
|
||||||
|
// +build js,wasm
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"syscall/js"
|
||||||
|
|
||||||
|
"github.com/google/go-jsonnet"
|
||||||
|
"github.com/google/go-jsonnet/internal/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
// JavascriptImporter allows importing files from a pre-defined map of absolute
|
||||||
|
// paths.
|
||||||
|
type JavascriptImporter struct {
|
||||||
|
files map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import looks up files in JavascriptImporter
|
||||||
|
func (importer *JavascriptImporter) Import(importedFrom, importedPath string) (jsonnet.Contents, string, error) {
|
||||||
|
fileRootPath := filepath.Dir(importedFrom)
|
||||||
|
fullFilePath := filepath.Clean(fmt.Sprintf("%s/%s", fileRootPath, importedPath))
|
||||||
|
|
||||||
|
fileContent, exists := importer.files[fullFilePath]
|
||||||
|
if exists {
|
||||||
|
return jsonnet.MakeContents(fileContent), importedPath, nil
|
||||||
|
} else {
|
||||||
|
return jsonnet.Contents{}, "", fmt.Errorf("File not found %v", fullFilePath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func processObjectParam(name string, value js.Value) (map[string]string, error) {
|
||||||
|
if value.Type() != js.TypeObject {
|
||||||
|
return nil, fmt.Errorf("'%s' was not an object: %v", name, value)
|
||||||
|
}
|
||||||
|
jsKeysArray := js.Global().Get("Object").Get("keys").Invoke(value)
|
||||||
|
result := make(map[string]string)
|
||||||
|
for i := 0; i < jsKeysArray.Length(); i++ {
|
||||||
|
filename := jsKeysArray.Index(i).String()
|
||||||
|
keyValue := value.Get(filename)
|
||||||
|
if keyValue.Type() != js.TypeString {
|
||||||
|
return nil, fmt.Errorf("'%s' key '%s' was not bound to a string: %v", name, filename, keyValue)
|
||||||
|
}
|
||||||
|
result[filename] = keyValue.String()
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func jsonnetEvaluateSnippet(this js.Value, p []js.Value) (interface{}, error) {
|
||||||
|
if len(p) != 7 {
|
||||||
|
return "", fmt.Errorf("wrong number of parameters: %d", len(p))
|
||||||
|
}
|
||||||
|
if p[0].Type() != js.TypeString {
|
||||||
|
return "", fmt.Errorf("filename was not a string: %v", p[0])
|
||||||
|
}
|
||||||
|
if p[1].Type() != js.TypeString {
|
||||||
|
return "", fmt.Errorf("code was not a string: %v", p[0])
|
||||||
|
}
|
||||||
|
filename := p[0].String()
|
||||||
|
code := p[1].String()
|
||||||
|
files, err := processObjectParam("files", p[2].JSValue())
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
extStrs, err := processObjectParam("extStrs", p[3].JSValue())
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
extCodes, err := processObjectParam("extCodes", p[4].JSValue())
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
tlaStrs, err := processObjectParam("tlaStrs", p[5].JSValue())
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
tlaCodes, err := processObjectParam("tlaCodes", p[6].JSValue())
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
vm := jsonnet.MakeVM()
|
||||||
|
vm.Importer(&JavascriptImporter{files: files})
|
||||||
|
for key, val := range extStrs {
|
||||||
|
vm.ExtVar(key, val)
|
||||||
|
}
|
||||||
|
for key, val := range extCodes {
|
||||||
|
vm.ExtCode(key, val)
|
||||||
|
}
|
||||||
|
for key, val := range tlaStrs {
|
||||||
|
vm.TLAVar(key, val)
|
||||||
|
}
|
||||||
|
for key, val := range tlaCodes {
|
||||||
|
vm.TLACode(key, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
return vm.EvaluateAnonymousSnippet(filename, code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func jsonnetFmtSnippet(this js.Value, p []js.Value) (interface{}, error) {
|
||||||
|
if len(p) != 2 {
|
||||||
|
return "", fmt.Errorf("wrong number of parameters: %d", len(p))
|
||||||
|
}
|
||||||
|
if p[0].Type() != js.TypeString {
|
||||||
|
return "", fmt.Errorf("filename was not a string: %v", p[0])
|
||||||
|
}
|
||||||
|
if p[1].Type() != js.TypeString {
|
||||||
|
return "", fmt.Errorf("code was not a string: %v", p[0])
|
||||||
|
}
|
||||||
|
filename := p[0].String()
|
||||||
|
code := p[1].String()
|
||||||
|
|
||||||
|
return formatter.Format(filename, code, formatter.DefaultOptions())
|
||||||
|
}
|
||||||
|
|
||||||
|
// promiseFuncOf is like js.FuncOf but returns a promise.
|
||||||
|
// The promise is able to propagate errors naturally across the wasm /
|
||||||
|
// javascript bridge.
|
||||||
|
func promiseFuncOf(jsFunc func(this js.Value, p []js.Value) (interface{}, error)) js.Func {
|
||||||
|
return js.FuncOf(func(this js.Value, p []js.Value) interface{} {
|
||||||
|
return js.Global().Get("Promise").New(js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
||||||
|
resolve := args[0]
|
||||||
|
reject := args[1]
|
||||||
|
go func() {
|
||||||
|
value, err := jsFunc(this, p)
|
||||||
|
if err != nil {
|
||||||
|
reject.Invoke(js.Global().Get("Error").New(err.Error()))
|
||||||
|
} else {
|
||||||
|
resolve.Invoke(js.ValueOf(value))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
js.Global().Set("jsonnet_evaluate_snippet", promiseFuncOf(jsonnetEvaluateSnippet))
|
||||||
|
js.Global().Set("jsonnet_fmt_snippet", promiseFuncOf(jsonnetFmtSnippet))
|
||||||
|
<-make(chan bool)
|
||||||
|
}
|
1
tests.sh
1
tests.sh
@ -24,6 +24,7 @@ export OVERRIDE_DIR="$PWD/testdata/cpp-tests-override/"
|
|||||||
|
|
||||||
go build ./cmd/jsonnet
|
go build ./cmd/jsonnet
|
||||||
go build ./cmd/jsonnetfmt
|
go build ./cmd/jsonnetfmt
|
||||||
|
GOOS=js GOARCH=wasm go build -o libjsonnet.wasm ./cmd/wasm
|
||||||
|
|
||||||
export DISABLE_LIB_TESTS=true
|
export DISABLE_LIB_TESTS=true
|
||||||
export DISABLE_ERROR_TESTS=true
|
export DISABLE_ERROR_TESTS=true
|
||||||
|
Loading…
x
Reference in New Issue
Block a user