From 72bdcfd535282adea2a7f4b26917f3594dfe4379 Mon Sep 17 00:00:00 2001 From: "guangyi.hgy" Date: Sat, 28 Sep 2019 17:57:25 +0800 Subject: [PATCH] init --- README.md | 31 ++++++++++++++++++++++++++- core/console.go | 21 +++++++++++++++++++ core/event-loop.go | 1 + core/loader.go | 52 ++++++++++++++++++++++++++++++++++++++++++++++ core/rts.go | 33 +++++++++++++++++++++++++++++ go.mod | 10 +++++++++ go.sum | 9 ++++++++ main.go | 23 ++++++++++++++++++++ test.js | 8 +++++++ 9 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 core/console.go create mode 100644 core/event-loop.go create mode 100644 core/loader.go create mode 100644 core/rts.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 test.js diff --git a/README.md b/README.md index 4136185..b82beae 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,31 @@ # gode -A test project to implement a Node like javascript environment based on Golang + +A test project to implement a Node like javascript environment based on goja + +# Example + +```golang +package main + +import ( + "fmt" + + "github.com/81120/gode/core" +) + +func main() { + gode := core.New() + gode.RegisterBuildInModule() + + r := gode.GetRts() + v, err := r.RunString(` + var t = require('./test.js'); + t.test(); + `) + if err != nil { + fmt.Print(err) + } else { + fmt.Println(v) + } +} +``` diff --git a/core/console.go b/core/console.go new file mode 100644 index 0000000..ad3c65f --- /dev/null +++ b/core/console.go @@ -0,0 +1,21 @@ +package core + +import ( + "fmt" + + js "github.com/dop251/goja" +) + +func log(call js.FunctionCall) js.Value { + str := call.Argument(0) + fmt.Print(str.String()) + return str +} + +// RegisterConsole register a console.log to runtime +func RegisterConsole(c *Core) { + r := c.GetRts() + o := r.NewObject() + o.Set("log", log) + r.Set("console", o) +} diff --git a/core/event-loop.go b/core/event-loop.go new file mode 100644 index 0000000..9a8bc95 --- /dev/null +++ b/core/event-loop.go @@ -0,0 +1 @@ +package core diff --git a/core/loader.go b/core/loader.go new file mode 100644 index 0000000..9325ead --- /dev/null +++ b/core/loader.go @@ -0,0 +1,52 @@ +package core + +import ( + "io/ioutil" + "path/filepath" + + js "github.com/dop251/goja" +) + +func moduleTemplate(c string) string { + return "(function(module, exports) {" + c + "\n})" +} + +func createModule(c *Core) *js.Object { + r := c.GetRts() + m := r.NewObject() + e := r.NewObject() + m.Set("exports", e) + + return m +} + +func loadModule(c *Core, p string) *js.Program { + p = filepath.Clean(p) + pkg := c.Pkg[p] + if pkg == nil { + code, _ := ioutil.ReadFile(p) + text := moduleTemplate(string(code)) + pkg, _ = js.Compile(p, text, false) + c.Pkg[p] = pkg + } + return pkg +} + +// RegisterLoader register a simple commonjs style loader to runtime +func RegisterLoader(c *Core) { + r := c.GetRts() + + r.Set("require", func(call js.FunctionCall) js.Value { + p := call.Argument(0).String() + prg := loadModule(c, p) + + f, _ := r.RunProgram(prg) + g, _ := js.AssertFunction(f) + + m := createModule(c) + jsExports := m.Get("exports") + g(jsExports, m, jsExports) + + return m.Get("exports") + }) +} diff --git a/core/rts.go b/core/rts.go new file mode 100644 index 0000000..6dc0a90 --- /dev/null +++ b/core/rts.go @@ -0,0 +1,33 @@ +package core + +import ( + js "github.com/dop251/goja" +) + +// Core is the basic struct of gode +type Core struct { + Rts *js.Runtime + Pkg map[string]*js.Program +} + +// New create a *Core +func New() *Core { + vm := js.New() + pkg := make(map[string]*js.Program) + + return &Core{ + Rts: vm, + Pkg: pkg, + } +} + +// GetRts get the object of javascript runtime +func (c *Core) GetRts() *js.Runtime { + return c.Rts +} + +// RegisterBuildInModule register some build in modules to the runtime +func (c *Core) RegisterBuildInModule() { + RegisterConsole(c) + RegisterLoader(c) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f4c8eba --- /dev/null +++ b/go.mod @@ -0,0 +1,10 @@ +module github.com/81120/gode + +go 1.13 + +require ( + github.com/dlclark/regexp2 v1.2.0 // indirect + github.com/dop251/goja v0.0.0-20190912223329-aa89e6a4c733 + github.com/go-sourcemap/sourcemap v2.1.2+incompatible // indirect + golang.org/x/text v0.3.2 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..1a516af --- /dev/null +++ b/go.sum @@ -0,0 +1,9 @@ +github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk= +github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dop251/goja v0.0.0-20190912223329-aa89e6a4c733 h1:cyNc40Dx5YNEO94idePU8rhVd3dn+sd04Arh0kDBAaw= +github.com/dop251/goja v0.0.0-20190912223329-aa89e6a4c733/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible h1:0b/xya7BKGhXuqFESKM4oIiRo9WOt2ebz7KxfreD6ug= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/main.go b/main.go new file mode 100644 index 0000000..0e1ef84 --- /dev/null +++ b/main.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" + + "github.com/81120/gode/core" +) + +func main() { + gode := core.New() + gode.RegisterBuildInModule() + + r := gode.GetRts() + v, err := r.RunString(` + var t = require('./test.js'); + t.test(); + `) + if err != nil { + fmt.Print(err) + } else { + fmt.Println(v) + } +} diff --git a/test.js b/test.js new file mode 100644 index 0000000..998c259 --- /dev/null +++ b/test.js @@ -0,0 +1,8 @@ +function test() { + console.log('hello world\n'); + return 'Hello Golang~'; +} + +module.exports = { + test: test, +};