

Show HN: CandyJS – transparent bridge between Go and JavaScript - mcuadros
https://github.com/mcuadros/go-candyjs

======
ivan4th
Nice project! One little remark: I see you're being slightly lazy and using
JSON to save some value conversion work. One problem is that this is not very
good from a performance standpoint. The other, more serious issue is that your
code will not work if someone tries to pass around a data structure containing
NaN value, like []float64{math.NaN()} Got bitten by this problem, had to fix
it: [https://github.com/contactless/wb-
rules/commit/067ff7564f16a...](https://github.com/contactless/wb-
rules/commit/067ff7564f16aba0d21ff7c2761839dd15f97ac9)

~~~
mcuadros
True in some cases I fold back to JSON: [https://github.com/mcuadros/go-
candyjs/blob/master/base.go#L...](https://github.com/mcuadros/go-
candyjs/blob/master/base.go#L272)

But the main goal of the project is be fully transparent more than the
performance. At the very beginning I was making every case by hand but this is
a endless work: [https://github.com/mcuadros/go-
candyjs/blob/54c8beb723aa8b1b...](https://github.com/mcuadros/go-
candyjs/blob/54c8beb723aa8b1b21f2d5864b0809f326d9a85d/engine/duktape/register.go#L142-L167)

I will take a closer look to the NaN issue and also a closer look to your
code.

BTW I made a PR to go-duktape based on you fork:
[https://github.com/olebedev/go-
duktape/commit/65f0be48ece4f6...](https://github.com/olebedev/go-
duktape/commit/65f0be48ece4f6405c93c3b5312fab074320bfef)

~~~
ivan4th
Unfortunately NaN behavior seems to be hard-wired in encoding/json code. The
proper way to fix it is perhaps taking encoding/json sources and converting
marshalling/unmarshalling code to use go-duktape Push/To/etc. functions
instead of JSON writing/parsing. That's indeed a sizable amount of work,
though.

As of integrating (some of) changes from my fork to the go-duktape mainline,
thanks a lot! Didn't get around to do it myself.

------
chrisfarms
I built a package to bridge spidermonkey/Go last year[0]. I ended up doing
most of the communication via JSON (after several less stable versions using
reflect) which was fine for the use-case I had. Unfortunately since it builds
spidermonkey and some wrapper code it ruined any chance of "go get" working
cleanly which doesn't make it a very attractive package.

CandyJS looks much simpler. Good work.

[0] [https://github.com/chrisfarms/jsapi](https://github.com/chrisfarms/jsapi)

~~~
mcuadros
Hi Chris, thanks for your support. Your packages looks like very interesting,
I couldn't find it before.

About the pool of workers, they share the stack? Or how you keep the same
status on each.

~~~
chrisfarms
No the contexts in pools do not share any state. Once you call an Eval from
Go-land you'll be tied to context until that Eval returns, but Go-land will
yield during that time so other goroutines(/contexts) are free to execute.
It's just a convenience for setting up and working with multiple contexts to
take advantage of multiple cores. Probably better to think of it like a
process-pool.

The use case I had was along the lines of:

    
    
        * Bind/Expose a bunch of Go functions to N JS worker contexts.
        * Execute a large queue of JS-functions using the workers.
    

Spidermonkey did actually have a way to do a kind of shallow copy of a context
and save/restore stack, which shared state, however this actually ended up
making things much slower for my use as it required locking the threads and
constantly copying stacks.

------
nathan_f77
This is pretty interesting, although I don't know if it's... necessary.

What do you think are some of the pros/cons between Go and JavaScript? When
would you prefer to use JavaScript instead of Go, or vice versa?

I think Go can be more performant than Node.js, but I remember seeing some
conflicting benchmarks where V8 can actually manage more RPS.

The other thing that comes to mind is how React Native uses JavaScript to
manipulate UI Components on iOS. If Google ever supports Go on Android, then
this kind of thing could be pretty interesting.

~~~
ivan4th
Duktape is good for scripting. My particular app is a simple rule engine for
smart home applications which runs on relatively low-powered ARM board. It
would hardly be practical to have Go compiler there, and duktape is resource-
efficient ECMAScript engine which serves this purpose just fine.

~~~
nathan_f77
Oh I see, that's pretty cool!

------
tav
Great work! But is there any reason that you didn't build on top of the really
nice V8 binding
[https://github.com/ry/v8worker](https://github.com/ry/v8worker) instead of
Duktape?

~~~
mcuadros
v8worker, was one of the evaluated projects, but V8 is not very fast
compiling... takes several mins.

With go-duktape, you can compile CandyJS just lake a normal Go package without
any other tool or library.

Other reason is that many of the features are based on ECMA6 Proxy, something
that is not supported on v8.

------
manucorporat
cool! why and how are the Go methods called with camelcase names?

    
    
      var engine = gin.default();
      engine.get("/back", CandyJS.proxy(function(ctx) {
        var future = time.date(2015, 10, 21, 4, 29 ,0, 0, time.UTC);
        var now = time.now();
    
        ctx.json(200, {
          future: future.string(),
          now: now.string(),
          nsecs: future.sub(now)
        });
      }));

~~~
mcuadros
the method and field names are converted to lowerCamelCase to be compliant
with the JS coding style. Let's see if this transformation becomes a headache.

BTW this behaviour is undocumented, I will fix that.

~~~
manucorporat
got it!

