From c975ddcd035e679c9ead286a43b0de3880162dab Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Sat, 3 Dec 2022 12:09:22 -0800 Subject: [PATCH] use goja for elk --- d2layouts/d2elklayout/layout.go | 50 +++++++++++++-------------------- d2layouts/d2elklayout/setup.js | 1 + 2 files changed, 21 insertions(+), 30 deletions(-) diff --git a/d2layouts/d2elklayout/layout.go b/d2layouts/d2elklayout/layout.go index 811cd1a14..94a0e7ebd 100644 --- a/d2layouts/d2elklayout/layout.go +++ b/d2layouts/d2elklayout/layout.go @@ -11,8 +11,7 @@ import ( "fmt" "math" - "rogchap.com/v8go" - + "github.com/dop251/goja" "oss.terrastruct.com/util-go/xdefer" "oss.terrastruct.com/util-go/go2" @@ -88,30 +87,17 @@ type ELKLayoutOptions struct { func Layout(ctx context.Context, g *d2graph.Graph) (err error) { defer xdefer.Errorf(&err, "failed to ELK layout") - iso := v8go.NewIsolate() - global := v8go.NewObjectTemplate(iso) + vm := goja.New() - // setTimeout is not defined by in v8go global - // As far as I can tell, it's not actually useful in elk.js - // The comment above one of the instances it's used is "why do we even need this" - // and it's a timeout of 0. - // If weird things happen though, look here. - setTimeout := v8go.NewFunctionTemplate(iso, func(info *v8go.FunctionCallbackInfo) *v8go.Value { - args := info.Args() - fn, _ := args[0].AsFunction() - receiver := v8go.NewObjectTemplate(iso) - s, _ := receiver.NewInstance(info.Context()) - fn.Call(s) - - return s.Value - }) - global.Set("setTimeout", setTimeout, v8go.ReadOnly) - - v8ctx := v8go.NewContext(iso, global) - if _, err := v8ctx.RunScript(elkJS, "elk.js"); err != nil { + console := vm.NewObject() + if err := vm.Set("console", console); err != nil { return err } - if _, err := v8ctx.RunScript(setupJS, "setup.js"); err != nil { + + if _, err := vm.RunString(elkJS); err != nil { + return err + } + if _, err := vm.RunString(setupJS); err != nil { return err } @@ -205,37 +191,41 @@ func Layout(ctx context.Context, g *d2graph.Graph) (err error) { loadScript := fmt.Sprintf(`var graph = %s`, raw) - if _, err := v8ctx.RunScript(loadScript, "load.js"); err != nil { + if _, err := vm.RunString(loadScript); err != nil { return err } - val, err := v8ctx.RunScript(`elk.layout(graph) + val, err := vm.RunString(`elk.layout(graph) .then(s => s) .catch(s => s) -`, "layout.js") +`) if err != nil { return err } - promise, err := val.AsPromise() + p := val.Export() if err != nil { return err } - for promise.State() == v8go.Pending { + promise := p.(*goja.Promise) + + for promise.State() == goja.PromiseStatePending { if err := ctx.Err(); err != nil { return err } continue } - jsonOut, err := promise.Result().MarshalJSON() + jsonOut := promise.Result().Export().(map[string]interface{}) + + jsonBytes, err := json.Marshal(jsonOut) if err != nil { return err } - err = json.Unmarshal(jsonOut, &elkGraph) + err = json.Unmarshal(jsonBytes, &elkGraph) if err != nil { return err } diff --git a/d2layouts/d2elklayout/setup.js b/d2layouts/d2elklayout/setup.js index 0f6babefe..1a86687b3 100644 --- a/d2layouts/d2elklayout/setup.js +++ b/d2layouts/d2elklayout/setup.js @@ -1 +1,2 @@ +var setTimeout = function(f) {f()}; const elk = new ELK();