10 ms·
Goja: A Golang JavaScript Runtime
- throwaway13337 2y agoThis is the runtime pocketbase uses to allow javascript interop. Pocketbase is the framework that makes me want to switch to golang. It just makes a lot of sense. One thing that concerned me, though. How do I debug goja? It doesn't seem like I can set breakpoints as usual. https://pocketbase.io/ https://pocketbase.io/
- thangngoc89 2y agoActually I decided to learn golang for extending using Golang for better DX (type hints and compiler errors)
- throwaway13337 2y agoIt's certainly a good idea to know golang while using something like pocketbase. However, one of the strengths of pocketbase, I think, is that the creator chose to add bindings for a very well known scripting language (js) to allow projects to be rapidly developed. It feels like django rethought. Using go for the base of your project and then gluing things together via scripting seems like a good idea. It's quite a big feature of the framework.
- skeeter2020 2y agoperformance seems pretty solid too, removing one of my prime motivators for switching to Go for extension work. PocketBase just seems to have made a lot of great decisions based on the conceptual integrity of the project goals.
- jtarchie 2y agoI've used Pocketbase for some other projects. A quick small web app, but it was so easy.
- steve_adams_86 2y agoPocketBase is a ton of fun. I’ve been using it for building my business’s store, and integrating with stripe was such a breeze. I’m using it sort of like a headless CMS/store. I considered other things like Payload CMS (which is awesome too) but the simplicity and productivity of pocket was such a draw. I don’t regret it.
- nine_k 2y agoIn short: Goja is an ES5 interpreter written in pure Go and seamlessly integrating with it. You pass a struct, the JS side receives an object, you update it, and the Go side seamlessly gets an updated struct. No cgo overhead.
- chrsig 2y agoIt's definitely cool, and and accomplishment. I think it's a bit strange to compare it to "no cgo overhead" though I say that because it's an interpreter rather than a jit, and doesn't have nearly as many person hours put into it as v8. I can see the argument that if you just need to evaluate a quick expression or maybe some user supplied script or something, it could be very handy, but I have a hard time believing that the cgo overhead is a factor when using cgo to invoke v8 compared to the parse/jit overhead that v8 will do. This is all armchair speculation of course. I use go regularly, but have no taste for javascript, so I have no dogs in that race. Definitely cool that there's an interpreter focused on correctness though.
- mappu 2y agoCalling a C function with Cgo has a certain overhead if you compare it to calling a Go function. But cgo overheads are completely negligible as soon as the function does any kind of real work. (A bigger reason to avoid cgo would be if you want easier cross-compilation.)
- randomdata 2y agocgo execution overhead is a nothingburger, but the programmer overhead to convert between Go types and C->Javascript types, and vice versa, as required by the use of a third-party engine (v8, etc.) is still significant as compared to what Goja offers. That is what the parent is talking about.
- siamese_puff 2y agoGreat article. I was looking for something like this last week.
- jtarchie 2y agoI'm glad it was helpful. It was a list of things I had known before I used it. So it was meant to be a quick getting started like doc.
- nchmy 2y agoThe examples in the article seem awfully contrived. Can someone please explain what a real-world use case for something like this would be? Why not just do it all in Go? Or is the point of it to be able to use existing JS scripts within a Go application?
- BobVawter 2y agoI've been using goja in a logical replication tool to make it field-programmable by the end users. No two deployments look alike, so a great deal of flexibility is needed for ETL uses. There's a tendency for configuration languages to become Turing-complete, so we started with a Turing-complete language for configuration. JS, or in Replicator's case, TypeScript (shout-out to esbuild), is sufficiently well-known that any dev group will have some experience with it. On the whole, I've been very impressed with how straightforward it's been to have user-scripts integrated into the processing pipeline. https://github.com/cockroachdb/replicator/wiki/User-Scripts https://github.com/cockroachdb/replicator/wiki/User-Scripts
- nchmy 2y agoAh, that makes a lot of sense - far easier to expose a JS api for user-extension than Golang (which is probably not even all that possible, except for via wasm, which would still be challenging) And, I suppose my initial hunch is probably correct - for the dev/application to be able to use existing JS libraries (be it part of your broader application/system or external) within a Go app. Check out my other comment [1] in this post for a newer, better version/fork of Goja - from the grafana/k6 team. [1] https://news.ycombinator.com/item?id=41470601 https://news.ycombinator.com/item?id=41470601
- jtarchie 2y agoNot doing it all, Go allows my API endpoint to accept sandboxed javascript code to enable users to run more complex queries against my data. It is also faster because they don't have to make individual API calls for each data set. Therefore, more data is required to be sent over the wire to them.
- dialogbox 2y agoThe name looks a obvious choice but... Ouch. It's a very funny name for Korean. It means eunuch. Lol
- michaelsbradley 2y agoThen there’s Ejacs https://github.com/emacsattic/ejacs https://github.com/emacsattic/ejacs http://steve-yegge.blogspot.com/2008/11/ejacs-javascript-interpreter-for-emacs.html http://steve-yegge.blogspot.com/2008/11/ejacs-javascript-int...
- jtarchie 2y agoSomeone on Reddit mentioned in Norwegian, it means "nothing."
- t3rra 2y agoI actually came to comments to say that.. lol.
- alixanderwang 2y agoI work on the D2 project ([0]) and we switched from other Javascript runners (v8go) to Goja. Using a JS runtime with a dependency on cgo means your Go program loses the (huge) benefit of cross-compiling to different architectures, since at build time it gets linked to the current system's libc. If you're interested in some production code with Goja, this is our code for calling RoughJS ([1]) from Go in order to produce the hand-drawn diagram look: [2] [0] https://github.com/terrastruct/d2 https://github.com/terrastruct/d2 [1] https://roughjs.com/ https://roughjs.com/ [2] https://github.com/terrastruct/d2/blob/master/d2renderers/d2sketch/sketch.go https://github.com/terrastruct/d2/blob/master/d2renderers/d2...
- dilyevsky 2y agoIt is quite easy to cross-compile cgo program to most architectures - just use Zig for this: CC="zig cc -target aarch64-linux"
- donatj 2y agoI've been a pretty happy Otto[1] user for a number of years now. The article makes no comparisons seemingly? I don't think there's even a never. I find that pretty odd. I'm curious if there'd be any reason to switch. https://github.com/robertkrimen/otto https://github.com/robertkrimen/otto
- jtarchie 2y agoI just wanted to share the details of my experience with Goja. It was not relevant to compare Otto.
- nchmy 2y agoI just dug through a lot of the issues and PRs in Goja, and eventually found that the grafana/k6 team recently forked Goja as Sobek [1], because the Goja dev has not been able to dedicate sufficient time to their PRs - namely ES Modules support [2], which was one of the only modern (ES6+) JS features outstanding [3] So, Sobek seems to be the way forward... [1] https://github.com/grafana/sobek/ https://github.com/grafana/sobek/ [2] https://github.com/dop251/goja/pull/430 https://github.com/dop251/goja/pull/430 [3] https://github.com/dop251/goja/milestone/1 https://github.com/dop251/goja/milestone/1
- jtarchie 2y agoI did see that. I'm going to let the fork simmer for awhile. I didn't require module support for my runtime. Since its meant to be very basic ETL runtime.
- nchmy 2y agoFair enough! Though they're quite clearly a much more serious/focused/resourced team than the goja dev, and they've fully integrated it into the K6 codebase now. I expect it'll have a bright future. Since you're doing ETL, did you consider something like Conduit, which is written in Golang and also allows for JS processing in the pipeline? Or is that overkill for what youre doing? https://conduit.io/docs/processors/builtin/custom.javascript https://conduit.io/docs/processors/builtin/custom.javascript
- dlock17 2y agoWhile I'm sure Goja is great for just JavaScript, using something like wazero allows your app to support more languages (anything that compiles to WASM) while keeping the benefits of CGO. https://wazero.io/ https://wazero.io/ I've used Wazero myself on C++ -> WASM code but I'm sure you could use Emscripten or something to compile JavaScript to WASM.
- bitwize 2y agoYou know, back when I got started as a Schemer, I remember people complaining about how many implementations of Scheme there were and how difficult it was to port between them. Today in JavaScript land we have Node, Deno, Bun, Goja, Sobek, Nashorn, whatever the browsers have, QML, GNOME, all of them subtly different. But instead of complaining, which people seem inclined to do when they encounter nested parens, people bro down and wrote code necessary to make them all interoperate if necessary -- despite JS having even less of a core language standard than Scheme does. I guess it's the Lisp Curse or something, I dunno.