Is there any future plans about improving the JavaScript Engine?

There’s lots of issue in the current version of the JavaScript Engine, like: the “new” operator can’t work, and the “[]” operator can’t get a index of a String etc.

I really love JUCE, and I used it a lot in my personal project.
But when I trying to use the JavaScript capabilities of JUCE to do some scripting things, I find it really frustrating…

So, is there any plans to improve the JavaScript Engine in the future like 6.0 or something?

Also, I would like to know when and what will be the next release?
Directly to 6.0, or something like 5.4?
After all, it’s been almost five months since the last release, so can you disclose some information about this?

thx!

We’ll be releasing a 5.4 later this year, and 6.0 next year.

Haven’t actually got any time allocated for the JS engine, but if you have specific bugs or FRs for it, let us know and it might be something straightforward to add. But it was never intended to be a full-blown standards-compliant engine though, just a subset that’s handy for casual use and which integrates nicely with the rest of juce.

Got it!
Thanks Jules~

If you’re looking for something a bit heavier but not as big as V8, the Microsoft Edge engine Chakra has a library version. https://github.com/Microsoft/ChakraCore It’s pretty fast too.

Yes if you rely on a standard compliant Javascript engine, you need to look elsewhere, however I second Jules argument that the integration with JUCE is so tight that you will definitely benefit from it if you’re already using Identifiers, vars or DynamicObjects for any kind of data processing.

I also found the code of the Javascript interpreter to be exceptionally easy to extend, so adding eg. String []-access are two lines of code at the right place (in this case add the code that returns the given character of the string to ArraySubscript::getResult() in juce_Javascript.cpp).

I’m actually in the midst of extending it right now… just for fun mind you.

I’ll be flying off for intense POC work soon though so I won’t be able to complete my changes soon by any means.

Also, for a quick integration check out duktape as an alternative JS interpreter - it does a pretty decent job and we use it in a few apps that are in production. I know various game devs that use it for hackday projects too.

I would also love to see some improvements to the javascript engine. I have used as a musician, the Javascript Scripter that is built into LogicPro. It processes real time midi and works very very very well. But alas, only on LogicPro. I think real time midi processing in the processBlock() function, via Javascript, is certainly something that could be done. Javascript has to be careful to avoid memory allocation and other expensive operations, just like well mannered C++ code would.

A guy has made a LuaScript plugin using JUCE, that can handle both audio and midi real time operations in the process block. check it out:

https://www.osar.fr/protoplug/

I’d like to be able to do the same kind of thing, but with Javascript. I think the built in javascript support is not up to this task as is. As someone mentioned in 2013, one thing needed is to divide the javascript parsing from the execution. Then probably some support for both native functions and objects too maybe, for example so that midi event objects in C++ processBlock, or perhaps the midi and audio buffers, have a thin javascript wrapper around them to access via javascript.

The LogicPro Scripter basically has a notion of some callbacks, that the user can provide in Javascript. HandleMIDI(), ProcessMIDI(), Idle(), a couple others. Then LogicPro calls those functions when it has a chance. For example, both HandleMIDI and ProcessMIDI() would be called from the C++ processBlock function. Then the user can run some javascript. HandleMIDI is called with one argument, a single event object. A more generalized approach might be to simply have a javascript processBlock callback…or even more generalized, let us call javascript functions from the C++. Then the javascript itself provides the functions to be called from C++. In this way we could make a midi or audio processing extension in javascript via callbacks… just one approach, maybe there are others…

I like what the guy did with Lua in ProtoPlug so I might try to take his projects as a starting point and try to see if I can get something working with V8, which is probably way too heavy duty, but I haven’t dug into what else is out there. I think LogicPro somehow leverages the Javascript engine in Safari.

Seems to have been done by someone at least?

I honestly don’t think it’s worth the effort, when there are already good options for well-maintained, modern javascript engines that can be integrated into a C++ app.

1 Like

As @adamski mentioned, there are more mature options out there that are actively maintained.

If you’re up for the exercise, you’re more than welcome to contribute to my branch: https://github.com/jrlanglois/JUCE/commits/JSMath

In that branch I’ve added:

The other objects are more or less completed… Some are exceptionally tricky - like attempting to implement Date by using juce::Time although the UTC support and timezone offset aren’t there. Same goes for JS objects like WeakMap and WeakSet.

Didn’t @ncthom package a 3rd party JS library for use in Blueprint?
Would it make sense to move that out in to it’s own JUCE module?

1 Like

Yeah, it’s called duktape. We’re investigating whether it’d make sense to use it for juce - the only tricky bit is that the juce JS interpreter is closely tied into the var class, which is used pervasively, so not sure whether or not a 3rd party interpreter could replace it.

Yep, I’m packaging Duktape for use in Blueprint, and actually one of my immediate TODOs is to refactor the integration there behind a class API that will be almost identical to JUCE’s JavascriptEngine (https://github.com/nick-thompson/blueprint/issues/9). I’ve already completed tight integration with the juce::var and juce::var::NativeFunctionArgs, so once I do this bit of refactoring, my DuktapeEngine will be basically a trivial drop-in replacement.

I’m also doing a bit of polyfill work for providing globals like setTimeout/setInterval, and eventually I’d like to get fetch in there too. ES6 features like WeakMap/WeakSet as mentioned above I have polyfilled via core-js currently, and could extend that as well if need be.

1 Like

Hi nick, this seems very promising and I’m currently looking to replace the default juce JS Engine, we’ve been narrowing down the research to V8 and duktape.
If we can be of any help regarding the dev of the DuktapeEngine juce module I would be happy to, we kinda dedicated this week to advanced on this matter.
You can check out the project I want to work on this for : http://benjamin.kuperberg.fr/chataigne (also note that this is one of the softwares using the OrganicUI juce module I created, and implementing duktape would mean all the other softwares using OrganicUI would benefit from it as well, yaay !)

https://bellard.org/quickjs/bench.html This might be worth considering also. It’s still under a meg in size but it’s much faster than duktape.

1 Like

Thank you for this info, it may be interesting to check out indeed !
One remaining question is how the integrated Juce JavascriptEngine performs compared to those

Played around and integrated a handful of JavaScript engines for a couple projects… Some thoughts off the top of my head.

  1. JavaScript Core iOS/macOS/(Windows C API) - easy to add to objective-c/objective-c++; Nice c++ wrapper around the C api here: https://github.com/appcelerator/HAL. Great speed, JavaScript Core is a pig when it comes to memory though (at least in our case when using the objective-c version), you can get in there and force some GC (https://github.com/appcelerator/HAL takes care of this for you) but it seemed a little unwieldy for us. We had a nice run with it for about 1.5 years for some internal tooling.

  2. Bellar’s QuickJS - Really nice library, ref-counted, works out of the box. Nice c++17 wrapper work happening here: https://github.com/ftk/quickjspp. Faster than JavaScript Core - We did all of our testing inside a graphics render and or audio callback loop, creating a bunch of objects, calling into and back out of JavaScript. Great memory footprint.

  3. Google’s v8 - This is a beast; Nice c++17 wrapper here https://github.com/pmed/v8pp/tree/c++17. Google’s documentation isn’t that great (maybe it’s me) but once you’ve got all the building out of the way it’s a breeze. They also have a JIT-less version (pass a flag during initialization) for low memory mobile devices or devices/os-es that do not allow JIT.

Notable mentions:
Facebook’s Hermes - https://github.com/facebook/hermes Came out a day after QuickJS release. At the time the documentation was null, so we really never gave it a real go.

If you’re doing simple UI layout then any options will do. For more complex video/graphics rendering or realtime midi message processing on non embedded devices I’d recommend v8; then QuickJS if you have real memory constraints.

4 Likes

Wow, awesome everyone, thanks for all the info.

@benkuper thanks :slight_smile: The duktapeEngine refactor is next up on my todo list, and your nudge might be the reason I finally get around to doing it heh. I’ll take a stab at it tonight, and report back here afterwards

In regards to the comparison with the existing JavaScriptEngine, I immediately ruled it out not for performance but because it is not ECMAScript 5+ compliant. In order to execute React in the environment I needed to be able to pull all sorts of NPM packages in, bundle them up, and run them correctly, which immediately pushed the JavaScriptEngine past its capabilities.

In regards to the other comparisons, V8 was indeed high on my list but Duktape ultimately won out because the performance is already quite good and the ease of integration is great. But, looking at all this info, I’m realizing there’s no reason my DuktapeEngine couldn’t define a generic interface to an embedded js engine and let the user swap out the underlying implementation at compile time. Perhaps this will be my goal during the refactor work I mentioned above…