juce_Javascript.cpp 70 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711
  1. /*
  2. ==============================================================================
  3. This file is part of the juce_core module of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission to use, copy, modify, and/or distribute this software for any purpose with
  6. or without fee is hereby granted, provided that the above copyright notice and this
  7. permission notice appear in all copies.
  8. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  9. TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  10. NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  11. DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  12. IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  13. CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14. ------------------------------------------------------------------------------
  15. NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
  16. All other JUCE modules are covered by a dual GPL/commercial license, so if you are
  17. using any other modules, be sure to check that you also comply with their license.
  18. For more details, visit www.juce.com
  19. ==============================================================================
  20. */
  21. #define JUCE_JS_OPERATORS(X) \
  22. X(semicolon, ";") X(dot, ".") X(comma, ",") \
  23. X(openParen, "(") X(closeParen, ")") X(openBrace, "{") X(closeBrace, "}") \
  24. X(openBracket, "[") X(closeBracket, "]") X(colon, ":") X(question, "?") \
  25. X(typeEquals, "===") X(equals, "==") X(assign, "=") \
  26. X(typeNotEquals, "!==") X(notEquals, "!=") X(logicalNot, "!") \
  27. X(plusEquals, "+=") X(plusplus, "++") X(plus, "+") \
  28. X(minusEquals, "-=") X(minusminus, "--") X(minus, "-") \
  29. X(timesEquals, "*=") X(times, "*") X(divideEquals, "/=") X(divide, "/") \
  30. X(moduloEquals, "%=") X(modulo, "%") X(xorEquals, "^=") X(bitwiseXor, "^") \
  31. X(andEquals, "&=") X(logicalAnd, "&&") X(bitwiseAnd, "&") \
  32. X(orEquals, "|=") X(logicalOr, "||") X(bitwiseOr, "|") \
  33. X(leftShiftEquals, "<<=") X(lessThanOrEqual, "<=") X(leftShift, "<<") X(lessThan, "<") \
  34. X(rightShiftUnsigned, ">>>") X(rightShiftEquals, ">>=") X(rightShift, ">>") X(greaterThanOrEqual, ">=") X(greaterThan, ">")
  35. #define JUCE_JS_KEYWORDS(X) \
  36. X(var, "var") X(if_, "if") X(else_, "else") X(do_, "do") X(null_, "null") \
  37. X(while_, "while") X(for_, "for") X(break_, "break") X(continue_, "continue") X(undefined, "undefined") \
  38. X(function, "function") X(return_, "return") X(true_, "true") X(false_, "false") X(new_, "new")
  39. namespace TokenTypes
  40. {
  41. #define JUCE_DECLARE_JS_TOKEN(name, str) static const char* const name = str;
  42. JUCE_JS_KEYWORDS (JUCE_DECLARE_JS_TOKEN)
  43. JUCE_JS_OPERATORS (JUCE_DECLARE_JS_TOKEN)
  44. JUCE_DECLARE_JS_TOKEN (eof, "$eof")
  45. JUCE_DECLARE_JS_TOKEN (literal, "$literal")
  46. JUCE_DECLARE_JS_TOKEN (identifier, "$identifier")
  47. }
  48. #if JUCE_MSVC
  49. #pragma warning (push)
  50. #pragma warning (disable: 4702)
  51. #endif
  52. //==============================================================================
  53. struct JavascriptEngine::RootObject : public DynamicObject
  54. {
  55. RootObject()
  56. {
  57. setMethod ("exec", exec);
  58. setMethod ("eval", eval);
  59. setMethod ("trace", trace);
  60. setMethod ("charToInt", charToInt);
  61. setMethod ("parseInt", IntegerClass::parseInt);
  62. }
  63. Time timeout;
  64. typedef const var::NativeFunctionArgs& Args;
  65. typedef const char* TokenType;
  66. void execute (const String& code)
  67. {
  68. ExpressionTreeBuilder tb (code);
  69. ScopedPointer<BlockStatement> (tb.parseStatementList())->perform (Scope (nullptr, this, this), nullptr);
  70. }
  71. var evaluate (const String& code)
  72. {
  73. ExpressionTreeBuilder tb (code);
  74. return ExpPtr (tb.parseExpression())->getResult (Scope (nullptr, this, this));
  75. }
  76. //==============================================================================
  77. static bool areTypeEqual (const var& a, const var& b)
  78. {
  79. return a.hasSameTypeAs (b) && isFunction (a) == isFunction (b)
  80. && (((a.isUndefined() || a.isVoid()) && (b.isUndefined() || b.isVoid())) || a == b);
  81. }
  82. static String getTokenName (TokenType t) { return t[0] == '$' ? String (t + 1) : ("'" + String (t) + "'"); }
  83. static bool isFunction (const var& v) { return dynamic_cast<FunctionObject*> (v.getObject()) != nullptr; }
  84. static bool isNumericOrUndefined (const var& v) { return v.isInt() || v.isDouble() || v.isInt64() || v.isBool() || v.isUndefined(); }
  85. static int64 getOctalValue (const String& s) { BigInteger b; b.parseString (s, 8); return b.toInt64(); }
  86. static Identifier getPrototypeIdentifier() { static const Identifier i ("prototype"); return i; }
  87. //==============================================================================
  88. struct CodeLocation
  89. {
  90. CodeLocation (const String& code) noexcept : program (code), location (program.getCharPointer()) {}
  91. CodeLocation (const CodeLocation& other) noexcept : program (other.program), location (other.location) {}
  92. void throwError (const String& message) const
  93. {
  94. int col = 1, line = 1;
  95. for (String::CharPointerType i (program.getCharPointer()); i < location && ! i.isEmpty(); ++i)
  96. {
  97. ++col;
  98. if (*i == '\n') { col = 1; ++line; }
  99. }
  100. throw "Line " + String (line) + ", column " + String (col) + " : " + message;
  101. }
  102. String program;
  103. String::CharPointerType location;
  104. };
  105. //==============================================================================
  106. struct Scope
  107. {
  108. Scope (const Scope* p, RootObject* r, DynamicObject* s) noexcept : parent (p), root (r), scope (s) {}
  109. const Scope* parent;
  110. ReferenceCountedObjectPtr<RootObject> root;
  111. DynamicObject::Ptr scope;
  112. var findFunctionCall (const CodeLocation& location, const var& targetObject, Identifier functionName) const
  113. {
  114. if (DynamicObject* o = targetObject.getDynamicObject())
  115. {
  116. if (var* prop = o->getProperties().getVarPointer (functionName))
  117. return *prop;
  118. for (DynamicObject* p = o->getProperty (getPrototypeIdentifier()).getDynamicObject(); p != nullptr;
  119. p = p->getProperty (getPrototypeIdentifier()).getDynamicObject())
  120. {
  121. if (var* prop = p->getProperties().getVarPointer (functionName))
  122. return *prop;
  123. }
  124. }
  125. if (targetObject.isString())
  126. if (var* m = findRootClassProperty (StringClass::getClassName(), functionName))
  127. return *m;
  128. if (targetObject.isArray())
  129. if (var* m = findRootClassProperty (ArrayClass::getClassName(), functionName))
  130. return *m;
  131. if (var* m = findRootClassProperty (ObjectClass::getClassName(), functionName))
  132. return *m;
  133. location.throwError ("Unknown function '" + functionName.toString() + "'");
  134. return var();
  135. }
  136. var* findRootClassProperty (Identifier className, Identifier propName) const
  137. {
  138. if (DynamicObject* cls = root->getProperty (className).getDynamicObject())
  139. return cls->getProperties().getVarPointer (propName);
  140. return nullptr;
  141. }
  142. var findSymbolInParentScopes (Identifier name) const
  143. {
  144. if (var* v = scope->getProperties().getVarPointer (name))
  145. return *v;
  146. return parent != nullptr ? parent->findSymbolInParentScopes (name)
  147. : var::undefined();
  148. }
  149. bool findAndInvokeMethod (Identifier function, const var::NativeFunctionArgs& args, var& result) const
  150. {
  151. const NamedValueSet& props = scope->getProperties();
  152. DynamicObject* target = args.thisObject.getDynamicObject();
  153. if (target == nullptr || target == scope)
  154. {
  155. if (const var* m = props.getVarPointer (function))
  156. {
  157. if (FunctionObject* fo = dynamic_cast<FunctionObject*> (m->getObject()))
  158. {
  159. result = fo->invoke (*this, args);
  160. return true;
  161. }
  162. }
  163. }
  164. for (int i = 0; i < props.size(); ++i)
  165. if (DynamicObject* o = props.getValueAt (i).getDynamicObject())
  166. if (Scope (this, root, o).findAndInvokeMethod (function, args, result))
  167. return true;
  168. return false;
  169. }
  170. void checkTimeOut (const CodeLocation& location) const
  171. {
  172. if (Time::getCurrentTime() > root->timeout)
  173. location.throwError ("Execution timed-out");
  174. }
  175. };
  176. //==============================================================================
  177. struct Statement
  178. {
  179. Statement (const CodeLocation& l) noexcept : location (l) {}
  180. virtual ~Statement() {}
  181. enum ResultCode { ok = 0, returnWasHit, breakWasHit, continueWasHit };
  182. virtual ResultCode perform (const Scope&, var*) const { return ok; }
  183. CodeLocation location;
  184. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Statement)
  185. };
  186. struct Expression : public Statement
  187. {
  188. Expression (const CodeLocation& l) noexcept : Statement (l) {}
  189. virtual var getResult (const Scope&) const { return var::undefined(); }
  190. virtual void assign (const Scope&, const var&) const { location.throwError ("Cannot assign to this expression!"); }
  191. ResultCode perform (const Scope& s, var*) const override { getResult (s); return ok; }
  192. };
  193. typedef ScopedPointer<Expression> ExpPtr;
  194. struct BlockStatement : public Statement
  195. {
  196. BlockStatement (const CodeLocation& l) noexcept : Statement (l) {}
  197. ResultCode perform (const Scope& s, var* returnedValue) const override
  198. {
  199. for (int i = 0; i < statements.size(); ++i)
  200. if (ResultCode r = statements.getUnchecked(i)->perform (s, returnedValue))
  201. return r;
  202. return ok;
  203. }
  204. OwnedArray<Statement> statements;
  205. };
  206. struct IfStatement : public Statement
  207. {
  208. IfStatement (const CodeLocation& l) noexcept : Statement (l) {}
  209. ResultCode perform (const Scope& s, var* returnedValue) const override
  210. {
  211. return (condition->getResult(s) ? trueBranch : falseBranch)->perform (s, returnedValue);
  212. }
  213. ExpPtr condition;
  214. ScopedPointer<Statement> trueBranch, falseBranch;
  215. };
  216. struct VarStatement : public Statement
  217. {
  218. VarStatement (const CodeLocation& l) noexcept : Statement (l) {}
  219. ResultCode perform (const Scope& s, var*) const override
  220. {
  221. s.scope->setProperty (name, initialiser->getResult (s));
  222. return ok;
  223. }
  224. Identifier name;
  225. ExpPtr initialiser;
  226. };
  227. struct LoopStatement : public Statement
  228. {
  229. LoopStatement (const CodeLocation& l, bool isDo) noexcept : Statement (l), isDoLoop (isDo) {}
  230. ResultCode perform (const Scope& s, var* returnedValue) const override
  231. {
  232. initialiser->perform (s, nullptr);
  233. while (isDoLoop || condition->getResult (s))
  234. {
  235. s.checkTimeOut (location);
  236. ResultCode r = body->perform (s, returnedValue);
  237. if (r == returnWasHit) return r;
  238. if (r == breakWasHit) break;
  239. iterator->perform (s, nullptr);
  240. if (isDoLoop && r != continueWasHit && ! condition->getResult (s))
  241. break;
  242. }
  243. return ok;
  244. }
  245. ScopedPointer<Statement> initialiser, iterator, body;
  246. ExpPtr condition;
  247. bool isDoLoop;
  248. };
  249. struct ReturnStatement : public Statement
  250. {
  251. ReturnStatement (const CodeLocation& l, Expression* v) noexcept : Statement (l), returnValue (v) {}
  252. ResultCode perform (const Scope& s, var* ret) const override
  253. {
  254. if (ret != nullptr) *ret = returnValue->getResult (s);
  255. return returnWasHit;
  256. }
  257. ExpPtr returnValue;
  258. };
  259. struct BreakStatement : public Statement
  260. {
  261. BreakStatement (const CodeLocation& l) noexcept : Statement (l) {}
  262. ResultCode perform (const Scope&, var*) const override { return breakWasHit; }
  263. };
  264. struct ContinueStatement : public Statement
  265. {
  266. ContinueStatement (const CodeLocation& l) noexcept : Statement (l) {}
  267. ResultCode perform (const Scope&, var*) const override { return continueWasHit; }
  268. };
  269. struct LiteralValue : public Expression
  270. {
  271. LiteralValue (const CodeLocation& l, const var& v) noexcept : Expression (l), value (v) {}
  272. var getResult (const Scope&) const override { return value; }
  273. var value;
  274. };
  275. struct UnqualifiedName : public Expression
  276. {
  277. UnqualifiedName (const CodeLocation& l, Identifier n) noexcept : Expression (l), name (n) {}
  278. var getResult (const Scope& s) const override { return s.findSymbolInParentScopes (name); }
  279. void assign (const Scope& s, const var& newValue) const override
  280. {
  281. if (var* v = s.scope->getProperties().getVarPointer (name))
  282. *v = newValue;
  283. else
  284. s.root->setProperty (name, newValue);
  285. }
  286. Identifier name;
  287. };
  288. struct DotOperator : public Expression
  289. {
  290. DotOperator (const CodeLocation& l, ExpPtr& p, Identifier c) noexcept : Expression (l), parent (p), child (c) {}
  291. var getResult (const Scope& s) const override
  292. {
  293. var p (parent->getResult (s));
  294. static const Identifier lengthID ("length");
  295. if (child == lengthID)
  296. {
  297. if (Array<var>* array = p.getArray()) return array->size();
  298. if (p.isString()) return p.toString().length();
  299. }
  300. if (DynamicObject* o = p.getDynamicObject())
  301. if (var* v = o->getProperties().getVarPointer (child))
  302. return *v;
  303. return var::undefined();
  304. }
  305. void assign (const Scope& s, const var& newValue) const override
  306. {
  307. if (DynamicObject* o = parent->getResult (s).getDynamicObject())
  308. o->setProperty (child, newValue);
  309. else
  310. Expression::assign (s, newValue);
  311. }
  312. ExpPtr parent;
  313. Identifier child;
  314. };
  315. struct ArraySubscript : public Expression
  316. {
  317. ArraySubscript (const CodeLocation& l) noexcept : Expression (l) {}
  318. var getResult (const Scope& s) const override
  319. {
  320. if (const Array<var>* array = object->getResult (s).getArray())
  321. return (*array) [static_cast<int> (index->getResult (s))];
  322. return var::undefined();
  323. }
  324. void assign (const Scope& s, const var& newValue) const override
  325. {
  326. if (Array<var>* array = object->getResult (s).getArray())
  327. {
  328. const int i = index->getResult (s);
  329. while (array->size() < i)
  330. array->add (var::undefined());
  331. array->set (i, newValue);
  332. return;
  333. }
  334. Expression::assign (s, newValue);
  335. }
  336. ExpPtr object, index;
  337. };
  338. struct BinaryOperatorBase : public Expression
  339. {
  340. BinaryOperatorBase (const CodeLocation& l, ExpPtr& a, ExpPtr& b, TokenType op) noexcept
  341. : Expression (l), lhs (a), rhs (b), operation (op) {}
  342. ExpPtr lhs, rhs;
  343. TokenType operation;
  344. };
  345. struct BinaryOperator : public BinaryOperatorBase
  346. {
  347. BinaryOperator (const CodeLocation& l, ExpPtr& a, ExpPtr& b, TokenType op) noexcept
  348. : BinaryOperatorBase (l, a, b, op) {}
  349. virtual var getWithUndefinedArg() const { return var::undefined(); }
  350. virtual var getWithDoubles (double, double) const { return throwError ("Double"); }
  351. virtual var getWithInts (int64, int64) const { return throwError ("Integer"); }
  352. virtual var getWithArrayOrObject (const var& a, const var&) const { return throwError (a.isArray() ? "Array" : "Object"); }
  353. virtual var getWithStrings (const String&, const String&) const { return throwError ("String"); }
  354. var getResult (const Scope& s) const override
  355. {
  356. var a (lhs->getResult (s)), b (rhs->getResult (s));
  357. if ((a.isUndefined() || a.isVoid()) && (b.isUndefined() || b.isVoid()))
  358. return getWithUndefinedArg();
  359. if (isNumericOrUndefined (a) && isNumericOrUndefined (b))
  360. return (a.isDouble() || b.isDouble()) ? getWithDoubles (a, b) : getWithInts (a, b);
  361. if (a.isArray() || a.isObject())
  362. return getWithArrayOrObject (a, b);
  363. return getWithStrings (a.toString(), b.toString());
  364. }
  365. var throwError (const char* typeName) const
  366. { location.throwError (getTokenName (operation) + " is not allowed on the " + typeName + " type"); return var(); }
  367. };
  368. struct EqualsOp : public BinaryOperator
  369. {
  370. EqualsOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::equals) {}
  371. var getWithUndefinedArg() const override { return true; }
  372. var getWithDoubles (double a, double b) const override { return a == b; }
  373. var getWithInts (int64 a, int64 b) const override { return a == b; }
  374. var getWithStrings (const String& a, const String& b) const override { return a == b; }
  375. var getWithArrayOrObject (const var& a, const var& b) const override { return a == b; }
  376. };
  377. struct NotEqualsOp : public BinaryOperator
  378. {
  379. NotEqualsOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::notEquals) {}
  380. var getWithUndefinedArg() const override { return false; }
  381. var getWithDoubles (double a, double b) const override { return a != b; }
  382. var getWithInts (int64 a, int64 b) const override { return a != b; }
  383. var getWithStrings (const String& a, const String& b) const override { return a != b; }
  384. var getWithArrayOrObject (const var& a, const var& b) const override { return a != b; }
  385. };
  386. struct LessThanOp : public BinaryOperator
  387. {
  388. LessThanOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::lessThan) {}
  389. var getWithDoubles (double a, double b) const override { return a < b; }
  390. var getWithInts (int64 a, int64 b) const override { return a < b; }
  391. var getWithStrings (const String& a, const String& b) const override { return a < b; }
  392. };
  393. struct LessThanOrEqualOp : public BinaryOperator
  394. {
  395. LessThanOrEqualOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::lessThanOrEqual) {}
  396. var getWithDoubles (double a, double b) const override { return a <= b; }
  397. var getWithInts (int64 a, int64 b) const override { return a <= b; }
  398. var getWithStrings (const String& a, const String& b) const override { return a <= b; }
  399. };
  400. struct GreaterThanOp : public BinaryOperator
  401. {
  402. GreaterThanOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::greaterThan) {}
  403. var getWithDoubles (double a, double b) const override { return a > b; }
  404. var getWithInts (int64 a, int64 b) const override { return a > b; }
  405. var getWithStrings (const String& a, const String& b) const override { return a > b; }
  406. };
  407. struct GreaterThanOrEqualOp : public BinaryOperator
  408. {
  409. GreaterThanOrEqualOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::greaterThanOrEqual) {}
  410. var getWithDoubles (double a, double b) const override { return a >= b; }
  411. var getWithInts (int64 a, int64 b) const override { return a >= b; }
  412. var getWithStrings (const String& a, const String& b) const override { return a >= b; }
  413. };
  414. struct AdditionOp : public BinaryOperator
  415. {
  416. AdditionOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::plus) {}
  417. var getWithDoubles (double a, double b) const override { return a + b; }
  418. var getWithInts (int64 a, int64 b) const override { return a + b; }
  419. var getWithStrings (const String& a, const String& b) const override { return a + b; }
  420. };
  421. struct SubtractionOp : public BinaryOperator
  422. {
  423. SubtractionOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::minus) {}
  424. var getWithDoubles (double a, double b) const override { return a - b; }
  425. var getWithInts (int64 a, int64 b) const override { return a - b; }
  426. };
  427. struct MultiplyOp : public BinaryOperator
  428. {
  429. MultiplyOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::times) {}
  430. var getWithDoubles (double a, double b) const override { return a * b; }
  431. var getWithInts (int64 a, int64 b) const override { return a * b; }
  432. };
  433. struct DivideOp : public BinaryOperator
  434. {
  435. DivideOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::divide) {}
  436. var getWithDoubles (double a, double b) const override { return a / b; }
  437. var getWithInts (int64 a, int64 b) const override { return a / b; }
  438. };
  439. struct ModuloOp : public BinaryOperator
  440. {
  441. ModuloOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::modulo) {}
  442. var getWithInts (int64 a, int64 b) const override { return a % b; }
  443. };
  444. struct BitwiseOrOp : public BinaryOperator
  445. {
  446. BitwiseOrOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::bitwiseOr) {}
  447. var getWithInts (int64 a, int64 b) const override { return a | b; }
  448. };
  449. struct BitwiseAndOp : public BinaryOperator
  450. {
  451. BitwiseAndOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::bitwiseAnd) {}
  452. var getWithInts (int64 a, int64 b) const override { return a & b; }
  453. };
  454. struct BitwiseXorOp : public BinaryOperator
  455. {
  456. BitwiseXorOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::bitwiseXor) {}
  457. var getWithInts (int64 a, int64 b) const override { return a ^ b; }
  458. };
  459. struct LeftShiftOp : public BinaryOperator
  460. {
  461. LeftShiftOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::leftShift) {}
  462. var getWithInts (int64 a, int64 b) const override { return ((int) a) << (int) b; }
  463. };
  464. struct RightShiftOp : public BinaryOperator
  465. {
  466. RightShiftOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::rightShift) {}
  467. var getWithInts (int64 a, int64 b) const override { return ((int) a) >> (int) b; }
  468. };
  469. struct RightShiftUnsignedOp : public BinaryOperator
  470. {
  471. RightShiftUnsignedOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::rightShiftUnsigned) {}
  472. var getWithInts (int64 a, int64 b) const override { return (int) (((uint32) a) >> (int) b); }
  473. };
  474. struct LogicalAndOp : public BinaryOperatorBase
  475. {
  476. LogicalAndOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperatorBase (l, a, b, TokenTypes::logicalAnd) {}
  477. var getResult (const Scope& s) const override { return lhs->getResult (s) && rhs->getResult (s); }
  478. };
  479. struct LogicalOrOp : public BinaryOperatorBase
  480. {
  481. LogicalOrOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperatorBase (l, a, b, TokenTypes::logicalOr) {}
  482. var getResult (const Scope& s) const override { return lhs->getResult (s) || rhs->getResult (s); }
  483. };
  484. struct TypeEqualsOp : public BinaryOperatorBase
  485. {
  486. TypeEqualsOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperatorBase (l, a, b, TokenTypes::typeEquals) {}
  487. var getResult (const Scope& s) const override { return areTypeEqual (lhs->getResult (s), rhs->getResult (s)); }
  488. };
  489. struct TypeNotEqualsOp : public BinaryOperatorBase
  490. {
  491. TypeNotEqualsOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperatorBase (l, a, b, TokenTypes::typeNotEquals) {}
  492. var getResult (const Scope& s) const override { return ! areTypeEqual (lhs->getResult (s), rhs->getResult (s)); }
  493. };
  494. struct ConditionalOp : public Expression
  495. {
  496. ConditionalOp (const CodeLocation& l) noexcept : Expression (l) {}
  497. var getResult (const Scope& s) const override { return (condition->getResult (s) ? trueBranch : falseBranch)->getResult (s); }
  498. void assign (const Scope& s, const var& v) const override { (condition->getResult (s) ? trueBranch : falseBranch)->assign (s, v); }
  499. ExpPtr condition, trueBranch, falseBranch;
  500. };
  501. struct Assignment : public Expression
  502. {
  503. Assignment (const CodeLocation& l, ExpPtr& dest, ExpPtr& source) noexcept : Expression (l), target (dest), newValue (source) {}
  504. var getResult (const Scope& s) const override
  505. {
  506. var value (newValue->getResult (s));
  507. target->assign (s, value);
  508. return value;
  509. }
  510. ExpPtr target, newValue;
  511. };
  512. struct SelfAssignment : public Expression
  513. {
  514. SelfAssignment (const CodeLocation& l, Expression* dest, Expression* source) noexcept
  515. : Expression (l), target (dest), newValue (source) {}
  516. var getResult (const Scope& s) const override
  517. {
  518. var value (newValue->getResult (s));
  519. target->assign (s, value);
  520. return value;
  521. }
  522. Expression* target; // Careful! this pointer aliases a sub-term of newValue!
  523. ExpPtr newValue;
  524. TokenType op;
  525. };
  526. struct PostAssignment : public SelfAssignment
  527. {
  528. PostAssignment (const CodeLocation& l, Expression* dest, Expression* source) noexcept : SelfAssignment (l, dest, source) {}
  529. var getResult (const Scope& s) const override
  530. {
  531. var oldValue (target->getResult (s));
  532. target->assign (s, newValue->getResult (s));
  533. return oldValue;
  534. }
  535. };
  536. struct FunctionCall : public Expression
  537. {
  538. FunctionCall (const CodeLocation& l) noexcept : Expression (l) {}
  539. var getResult (const Scope& s) const override
  540. {
  541. if (DotOperator* dot = dynamic_cast<DotOperator*> (object.get()))
  542. {
  543. var thisObject (dot->parent->getResult (s));
  544. return invokeFunction (s, s.findFunctionCall (location, thisObject, dot->child), thisObject);
  545. }
  546. var function (object->getResult (s));
  547. return invokeFunction (s, function, var (s.scope));
  548. }
  549. var invokeFunction (const Scope& s, const var& function, const var& thisObject) const
  550. {
  551. s.checkTimeOut (location);
  552. Array<var> argVars;
  553. for (int i = 0; i < arguments.size(); ++i)
  554. argVars.add (arguments.getUnchecked(i)->getResult (s));
  555. const var::NativeFunctionArgs args (thisObject, argVars.begin(), argVars.size());
  556. if (var::NativeFunction nativeFunction = function.getNativeFunction())
  557. return nativeFunction (args);
  558. if (FunctionObject* fo = dynamic_cast<FunctionObject*> (function.getObject()))
  559. return fo->invoke (s, args);
  560. location.throwError ("This expression is not a function!"); return var();
  561. }
  562. ExpPtr object;
  563. OwnedArray<Expression> arguments;
  564. };
  565. struct NewOperator : public FunctionCall
  566. {
  567. NewOperator (const CodeLocation& l) noexcept : FunctionCall (l) {}
  568. var getResult (const Scope& s) const override
  569. {
  570. var classOrFunc = object->getResult (s);
  571. const bool isFunc = isFunction (classOrFunc);
  572. if (! (isFunc || classOrFunc.getDynamicObject() != nullptr))
  573. return var::undefined();
  574. DynamicObject::Ptr newObject (new DynamicObject());
  575. if (isFunc)
  576. invokeFunction (s, classOrFunc, newObject.get());
  577. else
  578. newObject->setProperty (getPrototypeIdentifier(), classOrFunc);
  579. return newObject.get();
  580. }
  581. };
  582. struct ObjectDeclaration : public Expression
  583. {
  584. ObjectDeclaration (const CodeLocation& l) noexcept : Expression (l) {}
  585. var getResult (const Scope& s) const override
  586. {
  587. DynamicObject::Ptr newObject (new DynamicObject());
  588. for (int i = 0; i < names.size(); ++i)
  589. newObject->setProperty (names.getUnchecked(i), initialisers.getUnchecked(i)->getResult (s));
  590. return newObject.get();
  591. }
  592. Array<Identifier> names;
  593. OwnedArray<Expression> initialisers;
  594. };
  595. struct ArrayDeclaration : public Expression
  596. {
  597. ArrayDeclaration (const CodeLocation& l) noexcept : Expression (l) {}
  598. var getResult (const Scope& s) const override
  599. {
  600. Array<var> a;
  601. for (int i = 0; i < values.size(); ++i)
  602. a.add (values.getUnchecked(i)->getResult (s));
  603. return a;
  604. }
  605. OwnedArray<Expression> values;
  606. };
  607. //==============================================================================
  608. struct FunctionObject : public DynamicObject
  609. {
  610. FunctionObject() noexcept {}
  611. FunctionObject (const FunctionObject& other) : DynamicObject(), functionCode (other.functionCode)
  612. {
  613. ExpressionTreeBuilder tb (functionCode);
  614. tb.parseFunctionParamsAndBody (*this);
  615. }
  616. DynamicObject::Ptr clone() override { return new FunctionObject (*this); }
  617. void writeAsJSON (OutputStream& out, int /*indentLevel*/, bool /*allOnOneLine*/) override
  618. {
  619. out << "function " << functionCode;
  620. }
  621. var invoke (const Scope& s, const var::NativeFunctionArgs& args) const
  622. {
  623. DynamicObject::Ptr functionRoot (new DynamicObject());
  624. static const Identifier thisIdent ("this");
  625. functionRoot->setProperty (thisIdent, args.thisObject);
  626. for (int i = 0; i < parameters.size(); ++i)
  627. functionRoot->setProperty (parameters.getReference(i),
  628. i < args.numArguments ? args.arguments[i] : var::undefined());
  629. var result;
  630. body->perform (Scope (&s, s.root, functionRoot), &result);
  631. return result;
  632. }
  633. String functionCode;
  634. Array<Identifier> parameters;
  635. ScopedPointer<Statement> body;
  636. };
  637. //==============================================================================
  638. struct TokenIterator
  639. {
  640. TokenIterator (const String& code) : location (code), p (code.getCharPointer()) { skip(); }
  641. void skip()
  642. {
  643. skipWhitespaceAndComments();
  644. location.location = p;
  645. currentType = matchNextToken();
  646. }
  647. void match (TokenType expected)
  648. {
  649. if (currentType != expected)
  650. location.throwError ("Found " + getTokenName (currentType) + " when expecting " + getTokenName (expected));
  651. skip();
  652. }
  653. bool matchIf (TokenType expected) { if (currentType == expected) { skip(); return true; } return false; }
  654. bool matchesAny (TokenType t1, TokenType t2) const { return currentType == t1 || currentType == t2; }
  655. bool matchesAny (TokenType t1, TokenType t2, TokenType t3) const { return matchesAny (t1, t2) || currentType == t3; }
  656. CodeLocation location;
  657. TokenType currentType;
  658. var currentValue;
  659. private:
  660. String::CharPointerType p;
  661. static bool isIdentifierStart (const juce_wchar c) noexcept { return CharacterFunctions::isLetter (c) || c == '_'; }
  662. static bool isIdentifierBody (const juce_wchar c) noexcept { return CharacterFunctions::isLetterOrDigit (c) || c == '_'; }
  663. TokenType matchNextToken()
  664. {
  665. if (isIdentifierStart (*p))
  666. {
  667. String::CharPointerType end (p);
  668. while (isIdentifierBody (*++end)) {}
  669. const size_t len = (size_t) (end - p);
  670. #define JUCE_JS_COMPARE_KEYWORD(name, str) if (len == sizeof (str) - 1 && matchToken (TokenTypes::name, len)) return TokenTypes::name;
  671. JUCE_JS_KEYWORDS (JUCE_JS_COMPARE_KEYWORD)
  672. currentValue = String (p, end); p = end;
  673. return TokenTypes::identifier;
  674. }
  675. if (p.isDigit())
  676. {
  677. if (parseHexLiteral() || parseFloatLiteral() || parseOctalLiteral() || parseDecimalLiteral())
  678. return TokenTypes::literal;
  679. location.throwError ("Syntax error in numeric constant");
  680. }
  681. if (parseStringLiteral (*p) || (*p == '.' && parseFloatLiteral()))
  682. return TokenTypes::literal;
  683. #define JUCE_JS_COMPARE_OPERATOR(name, str) if (matchToken (TokenTypes::name, sizeof (str) - 1)) return TokenTypes::name;
  684. JUCE_JS_OPERATORS (JUCE_JS_COMPARE_OPERATOR)
  685. if (! p.isEmpty())
  686. location.throwError ("Unexpected character '" + String::charToString (*p) + "' in source");
  687. return TokenTypes::eof;
  688. }
  689. bool matchToken (TokenType name, const size_t len) noexcept
  690. {
  691. if (p.compareUpTo (CharPointer_ASCII (name), (int) len) != 0) return false;
  692. p += (int) len; return true;
  693. }
  694. void skipWhitespaceAndComments()
  695. {
  696. for (;;)
  697. {
  698. p = p.findEndOfWhitespace();
  699. if (*p == '/')
  700. {
  701. const juce_wchar c2 = p[1];
  702. if (c2 == '/') { p = CharacterFunctions::find (p, (juce_wchar) '\n'); continue; }
  703. if (c2 == '*')
  704. {
  705. location.location = p;
  706. p = CharacterFunctions::find (p + 2, CharPointer_ASCII ("*/"));
  707. if (p.isEmpty()) location.throwError ("Unterminated '/*' comment");
  708. p += 2; continue;
  709. }
  710. }
  711. break;
  712. }
  713. }
  714. bool parseStringLiteral (juce_wchar quoteType)
  715. {
  716. if (quoteType != '"' && quoteType != '\'')
  717. return false;
  718. Result r (JSON::parseQuotedString (p, currentValue));
  719. if (r.failed()) location.throwError (r.getErrorMessage());
  720. return true;
  721. }
  722. bool parseHexLiteral()
  723. {
  724. if (*p != '0' || (p[1] != 'x' && p[1] != 'X')) return false;
  725. String::CharPointerType t (++p);
  726. int64 v = CharacterFunctions::getHexDigitValue (*++t);
  727. if (v < 0) return false;
  728. for (;;)
  729. {
  730. const int digit = CharacterFunctions::getHexDigitValue (*++t);
  731. if (digit < 0) break;
  732. v = v * 16 + digit;
  733. }
  734. currentValue = v; p = t;
  735. return true;
  736. }
  737. bool parseFloatLiteral()
  738. {
  739. int numDigits = 0;
  740. String::CharPointerType t (p);
  741. while (t.isDigit()) { ++t; ++numDigits; }
  742. const bool hasPoint = (*t == '.');
  743. if (hasPoint)
  744. while ((++t).isDigit()) ++numDigits;
  745. if (numDigits == 0)
  746. return false;
  747. juce_wchar c = *t;
  748. const bool hasExponent = (c == 'e' || c == 'E');
  749. if (hasExponent)
  750. {
  751. c = *++t;
  752. if (c == '+' || c == '-') ++t;
  753. if (! t.isDigit()) return false;
  754. while ((++t).isDigit()) {}
  755. }
  756. if (! (hasExponent || hasPoint)) return false;
  757. currentValue = CharacterFunctions::getDoubleValue (p); p = t;
  758. return true;
  759. }
  760. bool parseOctalLiteral()
  761. {
  762. String::CharPointerType t (p);
  763. int64 v = *t - '0';
  764. if (v != 0) return false; // first digit of octal must be 0
  765. for (;;)
  766. {
  767. const int digit = (int) (*++t - '0');
  768. if (isPositiveAndBelow (digit, 8)) v = v * 8 + digit;
  769. else if (isPositiveAndBelow (digit, 10)) location.throwError ("Decimal digit in octal constant");
  770. else break;
  771. }
  772. currentValue = v; p = t;
  773. return true;
  774. }
  775. bool parseDecimalLiteral()
  776. {
  777. int64 v = 0;
  778. for (;; ++p)
  779. {
  780. const int digit = (int) (*p - '0');
  781. if (isPositiveAndBelow (digit, 10)) v = v * 10 + digit;
  782. else break;
  783. }
  784. currentValue = v;
  785. return true;
  786. }
  787. };
  788. //==============================================================================
  789. struct ExpressionTreeBuilder : private TokenIterator
  790. {
  791. ExpressionTreeBuilder (const String code) : TokenIterator (code) {}
  792. BlockStatement* parseStatementList()
  793. {
  794. ScopedPointer<BlockStatement> b (new BlockStatement (location));
  795. while (currentType != TokenTypes::closeBrace && currentType != TokenTypes::eof)
  796. b->statements.add (parseStatement());
  797. return b.release();
  798. }
  799. void parseFunctionParamsAndBody (FunctionObject& fo)
  800. {
  801. match (TokenTypes::openParen);
  802. while (currentType != TokenTypes::closeParen)
  803. {
  804. fo.parameters.add (currentValue.toString());
  805. match (TokenTypes::identifier);
  806. if (currentType != TokenTypes::closeParen)
  807. match (TokenTypes::comma);
  808. }
  809. match (TokenTypes::closeParen);
  810. fo.body = parseBlock();
  811. }
  812. Expression* parseExpression()
  813. {
  814. ExpPtr lhs (parseLogicOperator());
  815. if (matchIf (TokenTypes::question)) return parseTerneryOperator (lhs);
  816. if (matchIf (TokenTypes::assign)) { ExpPtr rhs (parseExpression()); return new Assignment (location, lhs, rhs); }
  817. if (matchIf (TokenTypes::plusEquals)) return parseInPlaceOpExpression<AdditionOp> (lhs);
  818. if (matchIf (TokenTypes::minusEquals)) return parseInPlaceOpExpression<SubtractionOp> (lhs);
  819. if (matchIf (TokenTypes::leftShiftEquals)) return parseInPlaceOpExpression<LeftShiftOp> (lhs);
  820. if (matchIf (TokenTypes::rightShiftEquals)) return parseInPlaceOpExpression<RightShiftOp> (lhs);
  821. return lhs.release();
  822. }
  823. private:
  824. void throwError (const String& err) const { location.throwError (err); }
  825. template <typename OpType>
  826. Expression* parseInPlaceOpExpression (ExpPtr& lhs)
  827. {
  828. ExpPtr rhs (parseExpression());
  829. Expression* bareLHS = lhs; // careful - bare pointer is deliberately alised
  830. return new SelfAssignment (location, bareLHS, new OpType (location, lhs, rhs));
  831. }
  832. BlockStatement* parseBlock()
  833. {
  834. match (TokenTypes::openBrace);
  835. ScopedPointer<BlockStatement> b (parseStatementList());
  836. match (TokenTypes::closeBrace);
  837. return b.release();
  838. }
  839. Statement* parseStatement()
  840. {
  841. if (currentType == TokenTypes::openBrace) return parseBlock();
  842. if (matchIf (TokenTypes::var)) return parseVar();
  843. if (matchIf (TokenTypes::if_)) return parseIf();
  844. if (matchIf (TokenTypes::while_)) return parseDoOrWhileLoop (false);
  845. if (matchIf (TokenTypes::do_)) return parseDoOrWhileLoop (true);
  846. if (matchIf (TokenTypes::for_)) return parseForLoop();
  847. if (matchIf (TokenTypes::return_)) return new ReturnStatement (location, matchIf (TokenTypes::semicolon) ? new Expression (location) : parseExpression());
  848. if (matchIf (TokenTypes::break_)) return new BreakStatement (location);
  849. if (matchIf (TokenTypes::continue_)) return new ContinueStatement (location);
  850. if (matchIf (TokenTypes::function)) return parseFunction();
  851. if (matchIf (TokenTypes::semicolon)) return new Statement (location);
  852. if (matchIf (TokenTypes::plusplus)) return parsePreIncDec<AdditionOp>();
  853. if (matchIf (TokenTypes::minusminus)) return parsePreIncDec<SubtractionOp>();
  854. if (matchesAny (TokenTypes::openParen, TokenTypes::openBracket))
  855. return matchEndOfStatement (parseFactor());
  856. if (matchesAny (TokenTypes::identifier, TokenTypes::literal, TokenTypes::minus))
  857. return matchEndOfStatement (parseExpression());
  858. throwError ("Found " + getTokenName (currentType) + " when expecting a statement");
  859. return nullptr;
  860. }
  861. Expression* matchEndOfStatement (Expression* ex) { ExpPtr e (ex); if (currentType != TokenTypes::eof) match (TokenTypes::semicolon); return e.release(); }
  862. Expression* matchCloseParen (Expression* ex) { ExpPtr e (ex); match (TokenTypes::closeParen); return e.release(); }
  863. Statement* parseIf()
  864. {
  865. ScopedPointer<IfStatement> s (new IfStatement (location));
  866. match (TokenTypes::openParen);
  867. s->condition = parseExpression();
  868. match (TokenTypes::closeParen);
  869. s->trueBranch = parseStatement();
  870. s->falseBranch = matchIf (TokenTypes::else_) ? parseStatement() : new Statement (location);
  871. return s.release();
  872. }
  873. Statement* parseVar()
  874. {
  875. ScopedPointer<VarStatement> s (new VarStatement (location));
  876. s->name = parseIdentifier();
  877. s->initialiser = matchIf (TokenTypes::assign) ? parseExpression() : new Expression (location);
  878. if (matchIf (TokenTypes::comma))
  879. {
  880. ScopedPointer<BlockStatement> block (new BlockStatement (location));
  881. block->statements.add (s.release());
  882. block->statements.add (parseVar());
  883. return block.release();
  884. }
  885. match (TokenTypes::semicolon);
  886. return s.release();
  887. }
  888. Statement* parseFunction()
  889. {
  890. Identifier name;
  891. var fn = parseFunctionDefinition (name);
  892. if (name.isNull())
  893. throwError ("Functions defined at statement-level must have a name");
  894. ExpPtr nm (new UnqualifiedName (location, name)), value (new LiteralValue (location, fn));
  895. return new Assignment (location, nm, value);
  896. }
  897. Statement* parseForLoop()
  898. {
  899. ScopedPointer<LoopStatement> s (new LoopStatement (location, false));
  900. match (TokenTypes::openParen);
  901. s->initialiser = parseStatement();
  902. if (matchIf (TokenTypes::semicolon))
  903. s->condition = new LiteralValue (location, true);
  904. else
  905. {
  906. s->condition = parseExpression();
  907. match (TokenTypes::semicolon);
  908. }
  909. s->iterator = parseExpression();
  910. match (TokenTypes::closeParen);
  911. s->body = parseStatement();
  912. return s.release();
  913. }
  914. Statement* parseDoOrWhileLoop (bool isDoLoop)
  915. {
  916. ScopedPointer<LoopStatement> s (new LoopStatement (location, isDoLoop));
  917. s->initialiser = new Statement (location);
  918. s->iterator = new Statement (location);
  919. if (isDoLoop)
  920. {
  921. s->body = parseBlock();
  922. match (TokenTypes::while_);
  923. }
  924. match (TokenTypes::openParen);
  925. s->condition = parseExpression();
  926. match (TokenTypes::closeParen);
  927. if (! isDoLoop)
  928. s->body = parseStatement();
  929. return s.release();
  930. }
  931. Identifier parseIdentifier()
  932. {
  933. Identifier i;
  934. if (currentType == TokenTypes::identifier)
  935. i = currentValue.toString();
  936. match (TokenTypes::identifier);
  937. return i;
  938. }
  939. var parseFunctionDefinition (Identifier& functionName)
  940. {
  941. const String::CharPointerType functionStart (location.location);
  942. if (currentType == TokenTypes::identifier)
  943. functionName = parseIdentifier();
  944. ScopedPointer<FunctionObject> fo (new FunctionObject());
  945. parseFunctionParamsAndBody (*fo);
  946. fo->functionCode = String (functionStart, location.location);
  947. return var (fo.release());
  948. }
  949. Expression* parseFunctionCall (FunctionCall* call, ExpPtr& function)
  950. {
  951. ScopedPointer<FunctionCall> s (call);
  952. s->object = function;
  953. match (TokenTypes::openParen);
  954. while (currentType != TokenTypes::closeParen)
  955. {
  956. s->arguments.add (parseExpression());
  957. if (currentType != TokenTypes::closeParen)
  958. match (TokenTypes::comma);
  959. }
  960. return matchCloseParen (s.release());
  961. }
  962. Expression* parseSuffixes (Expression* e)
  963. {
  964. ExpPtr input (e);
  965. if (matchIf (TokenTypes::dot))
  966. return parseSuffixes (new DotOperator (location, input, parseIdentifier()));
  967. if (currentType == TokenTypes::openParen)
  968. return parseSuffixes (parseFunctionCall (new FunctionCall (location), input));
  969. if (matchIf (TokenTypes::openBracket))
  970. {
  971. ScopedPointer<ArraySubscript> s (new ArraySubscript (location));
  972. s->object = input;
  973. s->index = parseExpression();
  974. match (TokenTypes::closeBracket);
  975. return parseSuffixes (s.release());
  976. }
  977. if (matchIf (TokenTypes::plusplus)) return parsePostIncDec<AdditionOp> (input);
  978. if (matchIf (TokenTypes::minusminus)) return parsePostIncDec<SubtractionOp> (input);
  979. return input.release();
  980. }
  981. Expression* parseFactor()
  982. {
  983. if (currentType == TokenTypes::identifier) return parseSuffixes (new UnqualifiedName (location, parseIdentifier()));
  984. if (matchIf (TokenTypes::openParen)) return parseSuffixes (matchCloseParen (parseExpression()));
  985. if (matchIf (TokenTypes::true_)) return parseSuffixes (new LiteralValue (location, (int) 1));
  986. if (matchIf (TokenTypes::false_)) return parseSuffixes (new LiteralValue (location, (int) 0));
  987. if (matchIf (TokenTypes::null_)) return parseSuffixes (new LiteralValue (location, var()));
  988. if (matchIf (TokenTypes::undefined)) return parseSuffixes (new Expression (location));
  989. if (currentType == TokenTypes::literal)
  990. {
  991. var v (currentValue); skip();
  992. return parseSuffixes (new LiteralValue (location, v));
  993. }
  994. if (matchIf (TokenTypes::openBrace))
  995. {
  996. ScopedPointer<ObjectDeclaration> e (new ObjectDeclaration (location));
  997. while (currentType != TokenTypes::closeBrace)
  998. {
  999. e->names.add (currentValue.toString());
  1000. match ((currentType == TokenTypes::literal && currentValue.isString())
  1001. ? TokenTypes::literal : TokenTypes::identifier);
  1002. match (TokenTypes::colon);
  1003. e->initialisers.add (parseExpression());
  1004. if (currentType != TokenTypes::closeBrace)
  1005. match (TokenTypes::comma);
  1006. }
  1007. match (TokenTypes::closeBrace);
  1008. return parseSuffixes (e.release());
  1009. }
  1010. if (matchIf (TokenTypes::openBracket))
  1011. {
  1012. ScopedPointer<ArrayDeclaration> e (new ArrayDeclaration (location));
  1013. while (currentType != TokenTypes::closeBracket)
  1014. {
  1015. e->values.add (parseExpression());
  1016. if (currentType != TokenTypes::closeBracket)
  1017. match (TokenTypes::comma);
  1018. }
  1019. match (TokenTypes::closeBracket);
  1020. return parseSuffixes (e.release());
  1021. }
  1022. if (matchIf (TokenTypes::function))
  1023. {
  1024. Identifier name;
  1025. var fn = parseFunctionDefinition (name);
  1026. if (name.isValid())
  1027. throwError ("Inline functions definitions cannot have a name");
  1028. return new LiteralValue (location, fn);
  1029. }
  1030. if (matchIf (TokenTypes::new_))
  1031. {
  1032. ExpPtr name (new UnqualifiedName (location, parseIdentifier()));
  1033. while (matchIf (TokenTypes::dot))
  1034. name = new DotOperator (location, name, parseIdentifier());
  1035. return parseFunctionCall (new NewOperator (location), name);
  1036. }
  1037. throwError ("Found " + getTokenName (currentType) + " when expecting an expression");
  1038. return nullptr;
  1039. }
  1040. template <typename OpType>
  1041. Expression* parsePreIncDec()
  1042. {
  1043. Expression* e = parseFactor(); // careful - bare pointer is deliberately alised
  1044. ExpPtr lhs (e), one (new LiteralValue (location, (int) 1));
  1045. return new SelfAssignment (location, e, new OpType (location, lhs, one));
  1046. }
  1047. template <typename OpType>
  1048. Expression* parsePostIncDec (ExpPtr& lhs)
  1049. {
  1050. Expression* e = lhs.release(); // careful - bare pointer is deliberately alised
  1051. ExpPtr lhs2 (e), one (new LiteralValue (location, (int) 1));
  1052. return new PostAssignment (location, e, new OpType (location, lhs2, one));
  1053. }
  1054. Expression* parseUnary()
  1055. {
  1056. if (matchIf (TokenTypes::minus)) { ExpPtr a (new LiteralValue (location, (int) 0)), b (parseUnary()); return new SubtractionOp (location, a, b); }
  1057. if (matchIf (TokenTypes::logicalNot)) { ExpPtr a (new LiteralValue (location, (int) 0)), b (parseUnary()); return new EqualsOp (location, a, b); }
  1058. if (matchIf (TokenTypes::plusplus)) return parsePreIncDec<AdditionOp>();
  1059. if (matchIf (TokenTypes::minusminus)) return parsePreIncDec<SubtractionOp>();
  1060. return parseFactor();
  1061. }
  1062. Expression* parseMultiplyDivide()
  1063. {
  1064. ExpPtr a (parseUnary());
  1065. for (;;)
  1066. {
  1067. if (matchIf (TokenTypes::times)) { ExpPtr b (parseUnary()); a = new MultiplyOp (location, a, b); }
  1068. else if (matchIf (TokenTypes::divide)) { ExpPtr b (parseUnary()); a = new DivideOp (location, a, b); }
  1069. else if (matchIf (TokenTypes::modulo)) { ExpPtr b (parseUnary()); a = new ModuloOp (location, a, b); }
  1070. else break;
  1071. }
  1072. return a.release();
  1073. }
  1074. Expression* parseAdditionSubtraction()
  1075. {
  1076. ExpPtr a (parseMultiplyDivide());
  1077. for (;;)
  1078. {
  1079. if (matchIf (TokenTypes::plus)) { ExpPtr b (parseMultiplyDivide()); a = new AdditionOp (location, a, b); }
  1080. else if (matchIf (TokenTypes::minus)) { ExpPtr b (parseMultiplyDivide()); a = new SubtractionOp (location, a, b); }
  1081. else break;
  1082. }
  1083. return a.release();
  1084. }
  1085. Expression* parseShiftOperator()
  1086. {
  1087. ExpPtr a (parseAdditionSubtraction());
  1088. for (;;)
  1089. {
  1090. if (matchIf (TokenTypes::leftShift)) { ExpPtr b (parseExpression()); a = new LeftShiftOp (location, a, b); }
  1091. else if (matchIf (TokenTypes::rightShift)) { ExpPtr b (parseExpression()); a = new RightShiftOp (location, a, b); }
  1092. else if (matchIf (TokenTypes::rightShiftUnsigned)) { ExpPtr b (parseExpression()); a = new RightShiftUnsignedOp (location, a, b); }
  1093. else break;
  1094. }
  1095. return a.release();
  1096. }
  1097. Expression* parseComparator()
  1098. {
  1099. ExpPtr a (parseShiftOperator());
  1100. for (;;)
  1101. {
  1102. if (matchIf (TokenTypes::equals)) { ExpPtr b (parseShiftOperator()); a = new EqualsOp (location, a, b); }
  1103. else if (matchIf (TokenTypes::notEquals)) { ExpPtr b (parseShiftOperator()); a = new NotEqualsOp (location, a, b); }
  1104. else if (matchIf (TokenTypes::typeEquals)) { ExpPtr b (parseShiftOperator()); a = new TypeEqualsOp (location, a, b); }
  1105. else if (matchIf (TokenTypes::typeNotEquals)) { ExpPtr b (parseShiftOperator()); a = new TypeNotEqualsOp (location, a, b); }
  1106. else if (matchIf (TokenTypes::lessThan)) { ExpPtr b (parseShiftOperator()); a = new LessThanOp (location, a, b); }
  1107. else if (matchIf (TokenTypes::lessThanOrEqual)) { ExpPtr b (parseShiftOperator()); a = new LessThanOrEqualOp (location, a, b); }
  1108. else if (matchIf (TokenTypes::greaterThan)) { ExpPtr b (parseShiftOperator()); a = new GreaterThanOp (location, a, b); }
  1109. else if (matchIf (TokenTypes::greaterThanOrEqual)) { ExpPtr b (parseShiftOperator()); a = new GreaterThanOrEqualOp (location, a, b); }
  1110. else break;
  1111. }
  1112. return a.release();
  1113. }
  1114. Expression* parseLogicOperator()
  1115. {
  1116. ExpPtr a (parseComparator());
  1117. for (;;)
  1118. {
  1119. if (matchIf (TokenTypes::logicalAnd)) { ExpPtr b (parseComparator()); a = new LogicalAndOp (location, a, b); }
  1120. else if (matchIf (TokenTypes::logicalOr)) { ExpPtr b (parseComparator()); a = new LogicalOrOp (location, a, b); }
  1121. else if (matchIf (TokenTypes::bitwiseAnd)) { ExpPtr b (parseComparator()); a = new BitwiseAndOp (location, a, b); }
  1122. else if (matchIf (TokenTypes::bitwiseOr)) { ExpPtr b (parseComparator()); a = new BitwiseOrOp (location, a, b); }
  1123. else if (matchIf (TokenTypes::bitwiseXor)) { ExpPtr b (parseComparator()); a = new BitwiseXorOp (location, a, b); }
  1124. else break;
  1125. }
  1126. return a.release();
  1127. }
  1128. Expression* parseTerneryOperator (ExpPtr& condition)
  1129. {
  1130. ScopedPointer<ConditionalOp> e (new ConditionalOp (location));
  1131. e->condition = condition;
  1132. e->trueBranch = parseExpression();
  1133. match (TokenTypes::colon);
  1134. e->falseBranch = parseExpression();
  1135. return e.release();
  1136. }
  1137. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ExpressionTreeBuilder)
  1138. };
  1139. //==============================================================================
  1140. static var get (Args a, int index) noexcept { return index < a.numArguments ? a.arguments[index] : var(); }
  1141. static bool isInt (Args a, int index) noexcept { return get (a, index).isInt() || get (a, index).isInt64(); }
  1142. static int getInt (Args a, int index) noexcept { return get (a, index); }
  1143. static double getDouble (Args a, int index) noexcept { return get (a, index); }
  1144. static String getString (Args a, int index) noexcept { return get (a, index).toString(); }
  1145. //==============================================================================
  1146. struct ObjectClass : public DynamicObject
  1147. {
  1148. ObjectClass()
  1149. {
  1150. setMethod ("dump", dump);
  1151. setMethod ("clone", clone);
  1152. }
  1153. static Identifier getClassName() { static const Identifier i ("Object"); return i; }
  1154. static var dump (Args a) { DBG (JSON::toString (a.thisObject)); (void) a; return var::undefined(); }
  1155. static var clone (Args a) { return a.thisObject.clone(); }
  1156. };
  1157. //==============================================================================
  1158. struct ArrayClass : public DynamicObject
  1159. {
  1160. ArrayClass()
  1161. {
  1162. setMethod ("contains", contains);
  1163. setMethod ("remove", remove);
  1164. setMethod ("join", join);
  1165. }
  1166. static Identifier getClassName() { static const Identifier i ("Array"); return i; }
  1167. static var contains (Args a)
  1168. {
  1169. if (const Array<var>* array = a.thisObject.getArray())
  1170. return array->contains (get (a, 0));
  1171. return false;
  1172. }
  1173. static var remove (Args a)
  1174. {
  1175. if (Array<var>* array = a.thisObject.getArray())
  1176. array->removeAllInstancesOf (get (a, 0));
  1177. return var::undefined();
  1178. }
  1179. static var join (Args a)
  1180. {
  1181. StringArray strings;
  1182. if (const Array<var>* array = a.thisObject.getArray())
  1183. for (int i = 0; i < array->size(); ++i)
  1184. strings.add (array->getReference(i).toString());
  1185. return strings.joinIntoString (getString (a, 0));
  1186. }
  1187. };
  1188. //==============================================================================
  1189. struct StringClass : public DynamicObject
  1190. {
  1191. StringClass()
  1192. {
  1193. setMethod ("substring", substring);
  1194. setMethod ("indexOf", indexOf);
  1195. setMethod ("charAt", charAt);
  1196. setMethod ("charCodeAt", charCodeAt);
  1197. setMethod ("fromCharCode", fromCharCode);
  1198. setMethod ("split", split);
  1199. }
  1200. static Identifier getClassName() { static const Identifier i ("String"); return i; }
  1201. static var fromCharCode (Args a) { return String::charToString (getInt (a, 0)); }
  1202. static var substring (Args a) { return a.thisObject.toString().substring (getInt (a, 0), getInt (a, 1)); }
  1203. static var indexOf (Args a) { return a.thisObject.toString().indexOf (getString (a, 0)); }
  1204. static var charCodeAt (Args a) { return (int) a.thisObject.toString() [getInt (a, 0)]; }
  1205. static var charAt (Args a) { int p = getInt (a, 0); return a.thisObject.toString().substring (p, p + 1); }
  1206. static var split (Args a)
  1207. {
  1208. const String str (a.thisObject.toString());
  1209. const String sep (getString (a, 0));
  1210. StringArray strings;
  1211. if (sep.isNotEmpty())
  1212. strings.addTokens (str, sep.substring (0, 1), "");
  1213. else // special-case for empty separator: split all chars separately
  1214. for (String::CharPointerType pos = str.getCharPointer(); ! pos.isEmpty(); ++pos)
  1215. strings.add (String::charToString (*pos));
  1216. var array;
  1217. for (int i = 0; i < strings.size(); ++i)
  1218. array.append (strings[i]);
  1219. return array;
  1220. }
  1221. };
  1222. //==============================================================================
  1223. struct MathClass : public DynamicObject
  1224. {
  1225. MathClass()
  1226. {
  1227. setMethod ("abs", Math_abs); setMethod ("round", Math_round);
  1228. setMethod ("random", Math_random); setMethod ("randInt", Math_randInt);
  1229. setMethod ("min", Math_min); setMethod ("max", Math_max);
  1230. setMethod ("range", Math_range); setMethod ("sign", Math_sign);
  1231. setMethod ("PI", Math_pi); setMethod ("E", Math_e);
  1232. setMethod ("toDegrees", Math_toDegrees); setMethod ("toRadians", Math_toRadians);
  1233. setMethod ("sin", Math_sin); setMethod ("asin", Math_asin);
  1234. setMethod ("sinh", Math_sinh); setMethod ("asinh", Math_asinh);
  1235. setMethod ("cos", Math_cos); setMethod ("acos", Math_acos);
  1236. setMethod ("cosh", Math_cosh); setMethod ("acosh", Math_acosh);
  1237. setMethod ("tan", Math_tan); setMethod ("atan", Math_atan);
  1238. setMethod ("tanh", Math_tanh); setMethod ("atanh", Math_atanh);
  1239. setMethod ("log", Math_log); setMethod ("log10", Math_log10);
  1240. setMethod ("exp", Math_exp); setMethod ("pow", Math_pow);
  1241. setMethod ("sqr", Math_sqr); setMethod ("sqrt", Math_sqrt);
  1242. }
  1243. static var Math_pi (Args) { return double_Pi; }
  1244. static var Math_e (Args) { return exp (1.0); }
  1245. static var Math_random (Args) { return Random::getSystemRandom().nextDouble(); }
  1246. static var Math_randInt (Args a) { return Random::getSystemRandom().nextInt (Range<int> (getInt (a, 0), getInt (a, 1))); }
  1247. static var Math_abs (Args a) { return isInt (a, 0) ? var (std::abs (getInt (a, 0))) : var (std::abs (getDouble (a, 0))); }
  1248. static var Math_round (Args a) { return isInt (a, 0) ? var (roundToInt (getInt (a, 0))) : var (roundToInt (getDouble (a, 0))); }
  1249. static var Math_sign (Args a) { return isInt (a, 0) ? var (sign (getInt (a, 0))) : var (sign (getDouble (a, 0))); }
  1250. static var Math_range (Args a) { return isInt (a, 0) ? var (jlimit (getInt (a, 1), getInt (a, 2), getInt (a, 0))) : var (jlimit (getDouble (a, 1), getDouble (a, 2), getDouble (a, 0))); }
  1251. static var Math_min (Args a) { return (isInt (a, 0) && isInt (a, 1)) ? var (jmin (getInt (a, 0), getInt (a, 1))) : var (jmin (getDouble (a, 0), getDouble (a, 1))); }
  1252. static var Math_max (Args a) { return (isInt (a, 0) && isInt (a, 1)) ? var (jmax (getInt (a, 0), getInt (a, 1))) : var (jmax (getDouble (a, 0), getDouble (a, 1))); }
  1253. static var Math_toDegrees (Args a) { return (180.0 / double_Pi) * getDouble (a, 0); }
  1254. static var Math_toRadians (Args a) { return (double_Pi / 180.0) * getDouble (a, 0); }
  1255. static var Math_sin (Args a) { return sin (getDouble (a, 0)); }
  1256. static var Math_asin (Args a) { return asin (getDouble (a, 0)); }
  1257. static var Math_cos (Args a) { return cos (getDouble (a, 0)); }
  1258. static var Math_acos (Args a) { return acos (getDouble (a, 0)); }
  1259. static var Math_sinh (Args a) { return sinh (getDouble (a, 0)); }
  1260. static var Math_asinh (Args a) { return asinh (getDouble (a, 0)); }
  1261. static var Math_cosh (Args a) { return cosh (getDouble (a, 0)); }
  1262. static var Math_acosh (Args a) { return acosh (getDouble (a, 0)); }
  1263. static var Math_tan (Args a) { return tan (getDouble (a, 0)); }
  1264. static var Math_tanh (Args a) { return tanh (getDouble (a, 0)); }
  1265. static var Math_atan (Args a) { return atan (getDouble (a, 0)); }
  1266. static var Math_atanh (Args a) { return atanh (getDouble (a, 0)); }
  1267. static var Math_log (Args a) { return log (getDouble (a, 0)); }
  1268. static var Math_log10 (Args a) { return log10 (getDouble (a, 0)); }
  1269. static var Math_exp (Args a) { return exp (getDouble (a, 0)); }
  1270. static var Math_pow (Args a) { return pow (getDouble (a, 0), getDouble (a, 1)); }
  1271. static var Math_sqr (Args a) { double x = getDouble (a, 0); return x * x; }
  1272. static var Math_sqrt (Args a) { return std::sqrt (getDouble (a, 0)); }
  1273. static Identifier getClassName() { static const Identifier i ("Math"); return i; }
  1274. template <typename Type> static Type sign (Type n) noexcept { return n > 0 ? (Type) 1 : (n < 0 ? (Type) -1 : 0); }
  1275. };
  1276. //==============================================================================
  1277. struct JSONClass : public DynamicObject
  1278. {
  1279. JSONClass() { setMethod ("stringify", stringify); }
  1280. static Identifier getClassName() { static const Identifier i ("JSON"); return i; }
  1281. static var stringify (Args a) { return JSON::toString (get (a, 0)); }
  1282. };
  1283. //==============================================================================
  1284. struct IntegerClass : public DynamicObject
  1285. {
  1286. IntegerClass() { setMethod ("parseInt", parseInt); }
  1287. static Identifier getClassName() { static const Identifier i ("Integer"); return i; }
  1288. static var parseInt (Args a)
  1289. {
  1290. const String s (getString (a, 0).trim());
  1291. return s[0] == '0' ? (s[1] == 'x' ? s.substring(2).getHexValue64() : getOctalValue (s))
  1292. : s.getLargeIntValue();
  1293. }
  1294. };
  1295. //==============================================================================
  1296. static var trace (Args a) { Logger::outputDebugString (JSON::toString (a.thisObject)); return var::undefined(); }
  1297. static var charToInt (Args a) { return (int) (getString (a, 0)[0]); }
  1298. static var exec (Args a)
  1299. {
  1300. if (RootObject* root = dynamic_cast<RootObject*> (a.thisObject.getObject()))
  1301. root->execute (getString (a, 0));
  1302. return var::undefined();
  1303. }
  1304. static var eval (Args a)
  1305. {
  1306. if (RootObject* root = dynamic_cast<RootObject*> (a.thisObject.getObject()))
  1307. return root->evaluate (getString (a, 0));
  1308. return var::undefined();
  1309. }
  1310. };
  1311. //==============================================================================
  1312. JavascriptEngine::JavascriptEngine() : maximumExecutionTime (15.0), root (new RootObject())
  1313. {
  1314. registerNativeObject (RootObject::ObjectClass ::getClassName(), new RootObject::ObjectClass());
  1315. registerNativeObject (RootObject::ArrayClass ::getClassName(), new RootObject::ArrayClass());
  1316. registerNativeObject (RootObject::StringClass ::getClassName(), new RootObject::StringClass());
  1317. registerNativeObject (RootObject::MathClass ::getClassName(), new RootObject::MathClass());
  1318. registerNativeObject (RootObject::JSONClass ::getClassName(), new RootObject::JSONClass());
  1319. registerNativeObject (RootObject::IntegerClass ::getClassName(), new RootObject::IntegerClass());
  1320. }
  1321. JavascriptEngine::~JavascriptEngine() {}
  1322. void JavascriptEngine::prepareTimeout() const { root->timeout = Time::getCurrentTime() + maximumExecutionTime; }
  1323. void JavascriptEngine::registerNativeObject (Identifier name, DynamicObject* object)
  1324. {
  1325. root->setProperty (name, object);
  1326. }
  1327. Result JavascriptEngine::execute (const String& code)
  1328. {
  1329. try
  1330. {
  1331. prepareTimeout();
  1332. root->execute (code);
  1333. }
  1334. catch (String& error)
  1335. {
  1336. return Result::fail (error);
  1337. }
  1338. return Result::ok();
  1339. }
  1340. var JavascriptEngine::evaluate (const String& code, Result* result)
  1341. {
  1342. try
  1343. {
  1344. prepareTimeout();
  1345. if (result != nullptr) *result = Result::ok();
  1346. return root->evaluate (code);
  1347. }
  1348. catch (String& error)
  1349. {
  1350. if (result != nullptr) *result = Result::fail (error);
  1351. }
  1352. return var::undefined();
  1353. }
  1354. var JavascriptEngine::callFunction (Identifier function, const var::NativeFunctionArgs& args, Result* result)
  1355. {
  1356. var returnVal (var::undefined());
  1357. try
  1358. {
  1359. prepareTimeout();
  1360. if (result != nullptr) *result = Result::ok();
  1361. RootObject::Scope (nullptr, root, root).findAndInvokeMethod (function, args, returnVal);
  1362. }
  1363. catch (String& error)
  1364. {
  1365. if (result != nullptr) *result = Result::fail (error);
  1366. }
  1367. return returnVal;
  1368. }
  1369. #if JUCE_MSVC
  1370. #pragma warning (pop)
  1371. #endif