From 9c75f13a4fdfc7aa2c46c2ac3d08877226eacf6e Mon Sep 17 00:00:00 2001 From: jules Date: Tue, 7 Mar 2017 15:51:01 +0000 Subject: [PATCH] Added a method JavascriptEngine::callFunctionObject() for invoking javascript methods in DynamicObject native methods --- .../juce_core/javascript/juce_Javascript.cpp | 73 ++++++++++++++----- .../juce_core/javascript/juce_Javascript.h | 9 +++ 2 files changed, 65 insertions(+), 17 deletions(-) diff --git a/modules/juce_core/javascript/juce_Javascript.cpp b/modules/juce_core/javascript/juce_Javascript.cpp index cd6a73c8de..a697f9d85b 100644 --- a/modules/juce_core/javascript/juce_Javascript.cpp +++ b/modules/juce_core/javascript/juce_Javascript.cpp @@ -144,15 +144,15 @@ struct JavascriptEngine::RootObject : public DynamicObject var findFunctionCall (const CodeLocation& location, const var& targetObject, const Identifier& functionName) const { - if (DynamicObject* o = targetObject.getDynamicObject()) + if (auto* o = targetObject.getDynamicObject()) { - if (const var* prop = getPropertyPointer (o, functionName)) + if (auto* prop = getPropertyPointer (o, functionName)) return *prop; - for (DynamicObject* p = o->getProperty (getPrototypeIdentifier()).getDynamicObject(); p != nullptr; + for (auto* p = o->getProperty (getPrototypeIdentifier()).getDynamicObject(); p != nullptr; p = p->getProperty (getPrototypeIdentifier()).getDynamicObject()) { - if (const var* prop = getPropertyPointer (p, functionName)) + if (auto* prop = getPropertyPointer (p, functionName)) return *prop; } @@ -162,23 +162,23 @@ struct JavascriptEngine::RootObject : public DynamicObject } if (targetObject.isString()) - if (var* m = findRootClassProperty (StringClass::getClassName(), functionName)) + if (auto* m = findRootClassProperty (StringClass::getClassName(), functionName)) return *m; if (targetObject.isArray()) - if (var* m = findRootClassProperty (ArrayClass::getClassName(), functionName)) + if (auto* m = findRootClassProperty (ArrayClass::getClassName(), functionName)) return *m; - if (var* m = findRootClassProperty (ObjectClass::getClassName(), functionName)) + if (auto* m = findRootClassProperty (ObjectClass::getClassName(), functionName)) return *m; location.throwError ("Unknown function '" + functionName.toString() + "'"); - return var(); + return {}; } var* findRootClassProperty (const Identifier& className, const Identifier& propName) const { - if (DynamicObject* cls = root->getProperty (className).getDynamicObject()) + if (auto* cls = root->getProperty (className).getDynamicObject()) return getPropertyPointer (cls, propName); return nullptr; @@ -186,7 +186,7 @@ struct JavascriptEngine::RootObject : public DynamicObject var findSymbolInParentScopes (const Identifier& name) const { - if (const var* v = getPropertyPointer (scope, name)) + if (auto* v = getPropertyPointer (scope, name)) return *v; return parent != nullptr ? parent->findSymbolInParentScopes (name) @@ -195,13 +195,13 @@ struct JavascriptEngine::RootObject : public DynamicObject bool findAndInvokeMethod (const Identifier& function, const var::NativeFunctionArgs& args, var& result) const { - DynamicObject* target = args.thisObject.getDynamicObject(); + auto* target = args.thisObject.getDynamicObject(); if (target == nullptr || target == scope) { - if (const var* m = getPropertyPointer (scope, function)) + if (auto* m = getPropertyPointer (scope, function)) { - if (FunctionObject* fo = dynamic_cast (m->getObject())) + if (auto fo = dynamic_cast (m->getObject())) { result = fo->invoke (*this, args); return true; @@ -209,16 +209,35 @@ struct JavascriptEngine::RootObject : public DynamicObject } } - const NamedValueSet& props = scope->getProperties(); + const auto& props = scope->getProperties(); for (int i = 0; i < props.size(); ++i) - if (DynamicObject* o = props.getValueAt (i).getDynamicObject()) + if (auto* o = props.getValueAt (i).getDynamicObject()) if (Scope (this, root, o).findAndInvokeMethod (function, args, result)) return true; return false; } + bool invokeMethod (const var& m, const var::NativeFunctionArgs& args, var& result) const + { + if (isFunction (m)) + { + auto* target = args.thisObject.getDynamicObject(); + + if (target == nullptr || target == scope) + { + if (auto fo = dynamic_cast (m.getObject())) + { + result = fo->invoke (*this, args); + return true; + } + } + } + + return false; + } + void checkTimeOut (const CodeLocation& location) const { if (Time::getCurrentTime() > root->timeout) @@ -1372,7 +1391,7 @@ struct JavascriptEngine::RootObject : public DynamicObject template Expression* parsePreIncDec() { - Expression* e = parseFactor(); // careful - bare pointer is deliberately alised + Expression* e = parseFactor(); // careful - bare pointer is deliberately aliased ExpPtr lhs (e), one (new LiteralValue (location, (int) 1)); return new SelfAssignment (location, e, new OpType (location, lhs, one)); } @@ -1380,7 +1399,7 @@ struct JavascriptEngine::RootObject : public DynamicObject template Expression* parsePostIncDec (ExpPtr& lhs) { - Expression* e = lhs.release(); // careful - bare pointer is deliberately alised + Expression* e = lhs.release(); // careful - bare pointer is deliberately aliased ExpPtr lhs2 (e), one (new LiteralValue (location, (int) 1)); return new PostAssignment (location, e, new OpType (location, lhs2, one)); } @@ -1850,6 +1869,26 @@ var JavascriptEngine::callFunction (const Identifier& function, const var::Nativ return returnVal; } +var JavascriptEngine::callFunctionObject (DynamicObject* objectScope, const var& functionObject, + const var::NativeFunctionArgs& args, Result* result) +{ + var returnVal (var::undefined()); + + try + { + prepareTimeout(); + if (result != nullptr) *result = Result::ok(); + RootObject::Scope rootScope (nullptr, root, root); + RootObject::Scope (&rootScope, root, objectScope).invokeMethod (functionObject, args, returnVal); + } + catch (String& error) + { + if (result != nullptr) *result = Result::fail (error); + } + + return returnVal; +} + const NamedValueSet& JavascriptEngine::getRootObjectProperties() const noexcept { return root->getProperties(); diff --git a/modules/juce_core/javascript/juce_Javascript.h b/modules/juce_core/javascript/juce_Javascript.h index 17fc2ba1a6..430b171c28 100644 --- a/modules/juce_core/javascript/juce_Javascript.h +++ b/modules/juce_core/javascript/juce_Javascript.h @@ -84,6 +84,15 @@ public: const var::NativeFunctionArgs& args, Result* errorMessage = nullptr); + /** Calls a function object in the namespace of a dynamic object, and returns the result. + The function arguments are passed in the same format as used by native + methods in the var class. + */ + var callFunctionObject (DynamicObject* objectScope, + const var& functionObject, + const var::NativeFunctionArgs& args, + Result* errorMessage = nullptr); + /** Adds a native object to the root namespace. The object passed-in is reference-counted, and will be retained by the engine until the engine is deleted. The name must be a simple JS identifier,