Using the "new" keyword in the Javascript Engine

so i’ve been messing about with JUCE’s Javascript Engine class and have noticed that while it does support the “new” keyword, this doesn’t really apply to classes I’ve written in my code as I can’t write something like this in my JS code:

var obj = new myObject();
obj.myFunction();

where my class looks like this in my c++ code:

    struct ConsoleClass  : public DynamicObject
    {
        ConsoleClass (JavaScriptComponent& demo) : owner (demo)
        {
            DBG("Console Class Constructor");
            setMethod ("print", print);
            setMethod ("clear", clear);
        }
        static Identifier getClassName()    { return "console"; }

        static var print (const var::NativeFunctionArgs& args)
        {
            if (args.numArguments > 0)
            {
                if (auto* thisObject = dynamic_cast<ConsoleClass*> (args.thisObject.getObject())) {
                    thisObject->owner.consolePrint (args.arguments[0].toString());
                }
            }
            return var::undefined();
        }

        static var clear (const var::NativeFunctionArgs& args)
        {
           if (args.numArguments <= 0)
            {
                if (auto* thisObject = dynamic_cast<ConsoleClass*> (args.thisObject.getObject())) {
                    thisObject->owner.consoleClear();
                }
            }
            return var::undefined();
        }

        JavaScriptComponent& owner;
        JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ConsoleClass)
    };

i figured a small work around that looks like this in my ConsoleClass struct:

        static var create(const var::NativeFunctionArgs& args)
        {
            if (args.numArguments <= 0)
            {
                if (auto* thisObject = dynamic_cast<PluginClass*> (args.thisObject.getObject())) {
                    return var(new ConsoleClass(thisObject->owner));
                }
            }
            return var::undefined();
        }

but i don’t really like this as its a bit more finicky and less intuitive on the scripting side imo.

also had a look in the juce_Javascript.cpp file and found this stuff but wouldn’t really know where to begin if i wanted to change it to support the new keyword a bit better?

    struct NewOperator  : public FunctionCall
    {
        NewOperator (const CodeLocation& l) noexcept : FunctionCall (l) {}

        var getResult (const Scope& s) const override
        {
            var classOrFunc = object->getResult (s);
            const bool isFunc = isFunction (classOrFunc);

            if (! (isFunc || classOrFunc.getDynamicObject() != nullptr))
                return var::undefined();

            DynamicObject::Ptr newObject (new DynamicObject());

            if (isFunc)
                invokeFunction (s, classOrFunc, newObject.get());
            else
                newObject->setProperty (getPrototypeIdentifier(), classOrFunc);

            return newObject.get(); 
        }
    };

anyone got any suggestions?

Use Duktape instead of JUCE’s JS interpreter. Duktape is actively maintained.

thanks for this, i’ll check that out. are there any examples around of integrating it with a juce application in place of the juce js engine?

also still just wondering about what it would take to modify juce’s js interpreter to support the new keyword? would it be in that section of code i’ve shared from the juce_Javascript.cpp?

I did this some time ago: GitHub - SquarePine/squarepine_duktape: A C++ unity build module in the format of a JUCE module. . Haven’t tested it in forever though. TLDR: you can include Duktape’s header file(s) and .c file(s) as needed into your project (Projucer or cmake or otherwise). It’s not that bad.

It’s barely worth faffing about with that. There are tons of PRs and requests about JUCE’s JS engine that have been around for a long time.