26#define JUCE_JS_OPERATORS(X) \
27 X(semicolon, ";") X(dot, ".") X(comma, ",") \
28 X(openParen, "(") X(closeParen, ")") X(openBrace, "{") X(closeBrace, "}") \
29 X(openBracket, "[") X(closeBracket, "]") X(colon, ":") X(question, "?") \
30 X(typeEquals, "===") X(equals, "==") X(assign, "=") \
31 X(typeNotEquals, "!==") X(notEquals, "!=") X(logicalNot, "!") \
32 X(plusEquals, "+=") X(plusplus, "++") X(plus, "+") \
33 X(minusEquals, "-=") X(minusminus, "--") X(minus, "-") \
34 X(timesEquals, "*=") X(times, "*") X(divideEquals, "/=") X(divide, "/") \
35 X(moduloEquals, "%=") X(modulo, "%") X(xorEquals, "^=") X(bitwiseXor, "^") \
36 X(andEquals, "&=") X(logicalAnd, "&&") X(bitwiseAnd, "&") \
37 X(orEquals, "|=") X(logicalOr, "||") X(bitwiseOr, "|") \
38 X(leftShiftEquals, "<<=") X(lessThanOrEqual, "<=") X(leftShift, "<<") X(lessThan, "<") \
39 X(rightShiftUnsigned, ">>>") X(rightShiftEquals, ">>=") X(rightShift, ">>") X(greaterThanOrEqual, ">=") X(greaterThan, ">")
41#define JUCE_JS_KEYWORDS(X) \
42 X(var, "var") X(if_, "if") X(else_, "else") X(do_, "do") X(null_, "null") \
43 X(while_, "while") X(for_, "for") X(break_, "break") X(continue_, "continue") X(undefined, "undefined") \
44 X(function, "function") X(return_, "return") X(true_, "true") X(false_, "false") X(new_, "new") \
49 #define JUCE_DECLARE_JS_TOKEN(name, str) static const char* const name = str;
50 JUCE_JS_KEYWORDS (JUCE_DECLARE_JS_TOKEN)
51 JUCE_JS_OPERATORS (JUCE_DECLARE_JS_TOKEN)
52 JUCE_DECLARE_JS_TOKEN (eof,
"$eof")
53 JUCE_DECLARE_JS_TOKEN (literal, "$literal")
54 JUCE_DECLARE_JS_TOKEN (identifier, "$identifier")
58 #pragma warning (push)
59 #pragma warning (disable: 4702)
67 setMethod (
"exec", exec);
68 setMethod (
"eval", eval);
69 setMethod (
"trace", trace);
70 setMethod (
"charToInt", charToInt);
71 setMethod (
"parseInt", IntegerClass::parseInt);
72 setMethod (
"typeof", typeof_internal);
73 setMethod (
"parseFloat", parseFloat);
79 using TokenType =
const char*;
81 void execute (
const String& code)
84 std::unique_ptr<BlockStatement> (tb.parseStatementList())->perform (
Scope ({}, *
this, *
this),
nullptr);
90 return ExpPtr (tb.parseExpression())->getResult (
Scope ({}, *
this, *
this));
94 static bool areTypeEqual (
const var& a,
const var& b)
96 return a.
hasSameTypeAs (b) && isFunction (a) == isFunction (b)
97 && (((a.isUndefined() || a.isVoid()) && (b.isUndefined() || b.isVoid())) || a == b);
100 static String getTokenName (TokenType t) {
return t[0] ==
'$' ?
String (t + 1) : (
"'" +
String (t) +
"'"); }
101 static bool isFunction (
const var& v)
noexcept {
return dynamic_cast<FunctionObject*
> (v.getObject()) !=
nullptr; }
102 static bool isNumeric (
const var& v)
noexcept {
return v.isInt() || v.isDouble() || v.isInt64() || v.isBool(); }
103 static bool isNumericOrUndefined (
const var& v)
noexcept {
return isNumeric (v) || v.isUndefined(); }
105 static Identifier getPrototypeIdentifier() {
static const Identifier i (
"prototype");
return i; }
111 CodeLocation (
const String& code) noexcept : program (code), location (program.getCharPointer()) {}
114 void throwError (
const String& message)
const
116 int col = 1, line = 1;
118 for (
auto i = program.
getCharPointer(); i < location && ! i.isEmpty(); ++i)
121 if (*i ==
'\n') { col = 1; ++line; }
124 throw "Line " +
String (line) +
", column " +
String (col) +
" : " + message;
135 : parent (p), root (std::move (rt)),
136 scope (std::move (scp)) {}
138 const Scope*
const parent;
144 if (
auto* o = targetObject.getDynamicObject())
146 if (
auto* prop = getPropertyPointer (*o, functionName))
149 for (
auto* p = o->
getProperty (getPrototypeIdentifier()).getDynamicObject(); p !=
nullptr;
150 p = p->getProperty (getPrototypeIdentifier()).getDynamicObject())
152 if (
auto* prop = getPropertyPointer (*p, functionName))
161 if (targetObject.isString())
162 if (
auto* m = findRootClassProperty (StringClass::getClassName(), functionName))
165 if (targetObject.isArray())
166 if (
auto* m = findRootClassProperty (ArrayClass::getClassName(), functionName))
169 if (
auto* m = findRootClassProperty (ObjectClass::getClassName(), functionName))
172 location.throwError (
"Unknown function '" + functionName.
toString() +
"'");
178 if (
auto* cls = root->getProperty (className).getDynamicObject())
179 return getPropertyPointer (*cls, propName);
186 if (
auto v = getPropertyPointer (*scope, name))
189 return parent !=
nullptr ? parent->findSymbolInParentScopes (name)
195 auto* target = args.thisObject.getDynamicObject();
197 if (target ==
nullptr || target == scope.
get())
199 if (
auto* m = getPropertyPointer (*scope, function))
203 result = fo->
invoke (*
this, args);
211 for (
int i = 0; i < props.size(); ++i)
212 if (
auto* o = props.getValueAt (i).getDynamicObject())
213 if (
Scope (
this, *root, *o).findAndInvokeMethod (function, args, result))
223 auto* target = args.thisObject.getDynamicObject();
225 if (target ==
nullptr || target == scope.
get())
229 result = fo->
invoke (*
this, args);
240 if (Time::getCurrentTime() > root->timeout)
241 location.throwError (root->timeout ==
Time() ?
"Interrupted" :
"Execution timed-out");
244 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (
Scope)
253 enum ResultCode { ok = 0, returnWasHit, breakWasHit, continueWasHit };
254 virtual ResultCode perform (
const Scope&,
var*)
const {
return ok; }
257 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (
Statement)
264 virtual var getResult (
const Scope&)
const {
return var::undefined(); }
265 virtual void assign (
const Scope&,
const var&)
const { location.throwError (
"Cannot assign to this expression!"); }
267 ResultCode perform (
const Scope& s,
var*)
const override { getResult (s);
return ok; }
270 using ExpPtr = std::unique_ptr<Expression>;
276 ResultCode perform (
const Scope& s,
var* returnedValue)
const override
278 for (
auto* statement : statements)
279 if (
auto r = statement->perform (s, returnedValue))
292 ResultCode perform (
const Scope& s,
var* returnedValue)
const override
294 return (condition->getResult(s) ? trueBranch : falseBranch)->perform (s, returnedValue);
298 std::unique_ptr<Statement> trueBranch, falseBranch;
305 ResultCode perform (
const Scope& s,
var*)
const override
307 s.scope->
setProperty (name, initialiser->getResult (s));
319 ResultCode perform (
const Scope& s,
var* returnedValue)
const override
321 initialiser->perform (s,
nullptr);
323 while (isDoLoop || condition->getResult (s))
325 s.checkTimeOut (location);
326 auto r = body->perform (s, returnedValue);
328 if (r == returnWasHit)
return r;
329 if (r == breakWasHit)
break;
331 iterator->perform (s,
nullptr);
333 if (isDoLoop && r != continueWasHit && ! condition->getResult (s))
340 std::unique_ptr<Statement> initialiser, iterator, body;
349 ResultCode perform (
const Scope& s,
var* ret)
const override
351 if (ret !=
nullptr) *ret = returnValue->getResult (s);
361 ResultCode perform (
const Scope&,
var*)
const override {
return breakWasHit; }
367 ResultCode perform (
const Scope&,
var*)
const override {
return continueWasHit; }
373 var getResult (
const Scope&)
const override {
return value; }
381 var getResult (
const Scope& s)
const override {
return s.findSymbolInParentScopes (name); }
383 void assign (
const Scope& s,
const var& newValue)
const override
385 if (
auto* v = getPropertyPointer (*s.scope, name))
388 s.root->setProperty (name, newValue);
398 var getResult (
const Scope& s)
const override
400 auto p = parent->getResult (s);
403 if (child == lengthID)
405 if (
auto* array = p.getArray())
return array->size();
406 if (p.isString())
return p.toString().length();
409 if (
auto* o = p.getDynamicObject())
410 if (
auto* v = getPropertyPointer (*o, child))
413 return var::undefined();
416 void assign (
const Scope& s,
const var& newValue)
const override
418 if (
auto* o = parent->getResult (s).getDynamicObject())
421 Expression::assign (s, newValue);
432 var getResult (
const Scope& s)
const override
434 auto arrayVar =
object->getResult (s);
435 auto key = index->getResult (s);
437 if (
const auto* array = arrayVar.getArray())
438 if (key.isInt() || key.isInt64() || key.isDouble())
439 return (*array) [
static_cast<int> (key)];
441 if (
auto* o = arrayVar.getDynamicObject())
443 if (
auto* v = getPropertyPointer (*o,
Identifier (key)))
446 return var::undefined();
449 void assign (
const Scope& s,
const var& newValue)
const override
451 auto arrayVar =
object->getResult (s);
452 auto key = index->getResult (s);
454 if (
auto* array = arrayVar.getArray())
456 if (key.isInt() || key.isInt64() || key.isDouble())
459 while (array->size() < i)
460 array->add (var::undefined());
462 array->set (i, newValue);
467 if (
auto* o = arrayVar.getDynamicObject())
476 Expression::assign (s, newValue);
479 ExpPtr object, index;
485 :
Expression (l), lhs (a.release()), rhs (b.release()), operation (op) {}
496 virtual var getWithUndefinedArg()
const {
return var::undefined(); }
497 virtual var getWithDoubles (
double,
double)
const {
return throwError (
"Double"); }
498 virtual var getWithInts (int64, int64)
const {
return throwError (
"Integer"); }
499 virtual var getWithArrayOrObject (
const var& a,
const var&)
const {
return throwError (a.isArray() ?
"Array" :
"Object"); }
500 virtual var getWithStrings (
const String&,
const String&)
const {
return throwError (
"String"); }
502 var getResult (
const Scope& s)
const override
504 var a (lhs->getResult (s)), b (rhs->getResult (s));
506 if ((a.isUndefined() || a.isVoid()) && (b.isUndefined() || b.isVoid()))
507 return getWithUndefinedArg();
509 if (isNumericOrUndefined (a) && isNumericOrUndefined (b))
510 return (a.isDouble() || b.isDouble()) ? getWithDoubles (a, b) : getWithInts (a, b);
512 if (a.isArray() || a.isObject())
513 return getWithArrayOrObject (a, b);
515 return getWithStrings (a.toString(), b.toString());
518 var throwError (
const char* typeName)
const
519 { location.throwError (getTokenName (operation) +
" is not allowed on the " + typeName +
" type");
return {}; }
525 var getWithUndefinedArg()
const override {
return true; }
526 var getWithDoubles (
double a,
double b)
const override {
return a == b; }
527 var getWithInts (int64 a, int64 b)
const override {
return a == b; }
528 var getWithStrings (
const String& a,
const String& b)
const override {
return a == b; }
529 var getWithArrayOrObject (
const var& a,
const var& b)
const override {
return a == b; }
535 var getWithUndefinedArg()
const override {
return false; }
536 var getWithDoubles (
double a,
double b)
const override {
return a != b; }
537 var getWithInts (int64 a, int64 b)
const override {
return a != b; }
538 var getWithStrings (
const String& a,
const String& b)
const override {
return a != b; }
539 var getWithArrayOrObject (
const var& a,
const var& b)
const override {
return a != b; }
545 var getWithDoubles (
double a,
double b)
const override {
return a < b; }
546 var getWithInts (int64 a, int64 b)
const override {
return a < b; }
547 var getWithStrings (
const String& a,
const String& b)
const override {
return a < b; }
553 var getWithDoubles (
double a,
double b)
const override {
return a <= b; }
554 var getWithInts (int64 a, int64 b)
const override {
return a <= b; }
555 var getWithStrings (
const String& a,
const String& b)
const override {
return a <= b; }
561 var getWithDoubles (
double a,
double b)
const override {
return a > b; }
562 var getWithInts (int64 a, int64 b)
const override {
return a > b; }
563 var getWithStrings (
const String& a,
const String& b)
const override {
return a > b; }
569 var getWithDoubles (
double a,
double b)
const override {
return a >= b; }
570 var getWithInts (int64 a, int64 b)
const override {
return a >= b; }
571 var getWithStrings (
const String& a,
const String& b)
const override {
return a >= b; }
577 var getWithDoubles (
double a,
double b)
const override {
return a + b; }
578 var getWithInts (int64 a, int64 b)
const override {
return a + b; }
579 var getWithStrings (
const String& a,
const String& b)
const override {
return a + b; }
585 var getWithDoubles (
double a,
double b)
const override {
return a - b; }
586 var getWithInts (int64 a, int64 b)
const override {
return a - b; }
592 var getWithDoubles (
double a,
double b)
const override {
return a * b; }
593 var getWithInts (int64 a, int64 b)
const override {
return a * b; }
599 var getWithDoubles (
double a,
double b)
const override {
return b != 0 ? a / b : std::numeric_limits<double>::infinity(); }
600 var getWithInts (int64 a, int64 b)
const override {
return b != 0 ?
var (a / (
double) b) :
var (std::numeric_limits<double>::infinity()); }
606 var getWithDoubles (
double a,
double b)
const override {
return b != 0 ? fmod (a, b) : std::numeric_limits<double>::infinity(); }
607 var getWithInts (int64 a, int64 b)
const override {
return b != 0 ?
var (a % b) :
var (std::numeric_limits<double>::infinity()); }
613 var getWithInts (int64 a, int64 b)
const override {
return a | b; }
619 var getWithInts (int64 a, int64 b)
const override {
return a & b; }
625 var getWithInts (int64 a, int64 b)
const override {
return a ^ b; }
631 var getWithInts (int64 a, int64 b)
const override {
return ((
int) a) << (int) b; }
637 var getWithInts (int64 a, int64 b)
const override {
return ((
int) a) >> (int) b; }
643 var getWithInts (int64 a, int64 b)
const override {
return (
int) (((uint32) a) >> (int) b); }
649 var getResult (
const Scope& s)
const override {
return lhs->getResult (s) && rhs->getResult (s); }
655 var getResult (
const Scope& s)
const override {
return lhs->getResult (s) || rhs->getResult (s); }
661 var getResult (
const Scope& s)
const override {
return areTypeEqual (lhs->getResult (s), rhs->getResult (s)); }
667 var getResult (
const Scope& s)
const override {
return ! areTypeEqual (lhs->getResult (s), rhs->getResult (s)); }
674 var getResult (
const Scope& s)
const override {
return (condition->getResult (s) ? trueBranch : falseBranch)->getResult (s); }
675 void assign (
const Scope& s,
const var& v)
const override { (condition->getResult (s) ? trueBranch : falseBranch)->assign (s, v); }
677 ExpPtr condition, trueBranch, falseBranch;
684 var getResult (
const Scope& s)
const override
686 auto value = newValue->getResult (s);
687 target->assign (s, value);
691 ExpPtr target, newValue;
697 :
Expression (l), target (dest), newValue (source) {}
699 var getResult (
const Scope& s)
const override
701 auto value = newValue->getResult (s);
702 target->assign (s, value);
715 var getResult (
const Scope& s)
const override
717 auto oldValue = target->getResult (s);
718 target->assign (s, newValue->getResult (s));
727 var getResult (
const Scope& s)
const override
729 if (
auto* dot =
dynamic_cast<DotOperator*
> (
object.get()))
731 auto thisObject = dot->parent->getResult (s);
732 return invokeFunction (s, s.findFunctionCall (location, thisObject, dot->child), thisObject);
735 auto function =
object->getResult (s);
736 return invokeFunction (s, function,
var (s.scope.
get()));
739 var invokeFunction (
const Scope& s,
const var& function,
const var& thisObject)
const
741 s.checkTimeOut (location);
744 for (
auto* a : arguments)
745 argVars.
add (a->getResult (s));
749 if (var::NativeFunction nativeFunction = function.getNativeFunction())
750 return nativeFunction (args);
752 if (
auto* fo =
dynamic_cast<FunctionObject*
> (function.getObject()))
753 return fo->invoke (s, args);
755 if (
auto* dot =
dynamic_cast<DotOperator*
> (
object.get()))
756 if (
auto* o = thisObject.getDynamicObject())
760 location.throwError (
"This expression is not a function!");
return {};
771 var getResult (
const Scope& s)
const override
773 var classOrFunc =
object->getResult (s);
774 const bool isFunc = isFunction (classOrFunc);
776 if (! (isFunc || classOrFunc.getDynamicObject() !=
nullptr))
777 return var::undefined();
782 invokeFunction (s, classOrFunc, newObject.
get());
784 newObject->
setProperty (getPrototypeIdentifier(), classOrFunc);
786 return newObject.
get();
794 var getResult (
const Scope& s)
const override
798 for (
int i = 0; i < names.size(); ++i)
799 newObject->
setProperty (names.getUnchecked(i), initialisers.getUnchecked(i)->getResult (s));
801 return newObject.
get();
812 var getResult (
const Scope& s)
const override
816 for (
int i = 0; i < values.size(); ++i)
817 a.
add (values.getUnchecked(i)->getResult (s));
833 tb.parseFunctionParamsAndBody (*
this);
840 out <<
"function " << functionCode;
848 functionRoot->setProperty (thisIdent, args.thisObject);
850 for (
int i = 0; i < parameters.size(); ++i)
851 functionRoot->setProperty (parameters.getReference(i),
852 i < args.numArguments ? args.arguments[i] :
var::undefined());
855 body->perform (
Scope (&s, s.root, functionRoot), &result);
861 std::unique_ptr<Statement> body;
871 skipWhitespaceAndComments();
872 location.location = p;
873 currentType = matchNextToken();
876 void match (TokenType expected)
878 if (currentType != expected)
879 location.throwError (
"Found " + getTokenName (currentType) +
" when expecting " + getTokenName (expected));
884 bool matchIf (TokenType expected) {
if (currentType == expected) { skip();
return true; }
return false; }
885 bool matchesAny (TokenType t1, TokenType t2)
const {
return currentType == t1 || currentType == t2; }
886 bool matchesAny (TokenType t1, TokenType t2, TokenType t3)
const {
return matchesAny (t1, t2) || currentType == t3; }
889 TokenType currentType;
895 static bool isIdentifierStart (juce_wchar c)
noexcept {
return CharacterFunctions::isLetter (c) || c ==
'_'; }
896 static bool isIdentifierBody (juce_wchar c)
noexcept {
return CharacterFunctions::isLetterOrDigit (c) || c ==
'_'; }
898 TokenType matchNextToken()
900 if (isIdentifierStart (*p))
903 while (isIdentifierBody (*++end)) {}
905 auto len = (size_t) (end - p);
906 #define JUCE_JS_COMPARE_KEYWORD(name, str) if (len == sizeof (str) - 1 && matchToken (TokenTypes::name, len)) return TokenTypes::name;
907 JUCE_JS_KEYWORDS (JUCE_JS_COMPARE_KEYWORD)
909 currentValue =
String (p, end); p = end;
910 return TokenTypes::identifier;
915 if (parseHexLiteral() || parseFloatLiteral() || parseOctalLiteral() || parseDecimalLiteral())
916 return TokenTypes::literal;
918 location.throwError (
"Syntax error in numeric constant");
921 if (parseStringLiteral (*p) || (*p ==
'.' && parseFloatLiteral()))
922 return TokenTypes::literal;
924 #define JUCE_JS_COMPARE_OPERATOR(name, str) if (matchToken (TokenTypes::name, sizeof (str) - 1)) return TokenTypes::name;
925 JUCE_JS_OPERATORS (JUCE_JS_COMPARE_OPERATOR)
928 location.throwError (
"Unexpected character '" + String::charToString (*p) +
"' in source");
930 return TokenTypes::eof;
933 bool matchToken (TokenType name,
size_t len)
noexcept
936 p += (int) len;
return true;
939 void skipWhitespaceAndComments()
949 if (c2 ==
'/') { p = CharacterFunctions::find (p, (juce_wchar)
'\n');
continue; }
953 location.location = p;
955 if (p.
isEmpty()) location.throwError (
"Unterminated '/*' comment");
964 bool parseStringLiteral (juce_wchar quoteType)
966 if (quoteType !=
'"' && quoteType !=
'\'')
969 auto r = JSON::parseQuotedString (p, currentValue);
970 if (r.failed()) location.throwError (r.getErrorMessage());
974 bool parseHexLiteral()
976 if (*p !=
'0' || (p[1] !=
'x' && p[1] !=
'X'))
return false;
979 int64 v = CharacterFunctions::getHexDigitValue (*++t);
980 if (v < 0)
return false;
984 auto digit = CharacterFunctions::getHexDigitValue (*++t);
985 if (digit < 0)
break;
989 currentValue = v; p = t;
993 bool parseFloatLiteral()
997 while (t.isDigit()) { ++t; ++numDigits; }
999 const bool hasPoint = (*t ==
'.');
1002 while ((++t).isDigit()) ++numDigits;
1008 const bool hasExponent = (c ==
'e' || c ==
'E');
1013 if (c ==
'+' || c ==
'-') ++t;
1014 if (! t.isDigit())
return false;
1015 while ((++t).isDigit()) {}
1018 if (! (hasExponent || hasPoint))
return false;
1020 currentValue = CharacterFunctions::getDoubleValue (p); p = t;
1024 bool parseOctalLiteral()
1028 if (v != 0)
return false;
1032 auto digit = (int) (*++t -
'0');
1033 if (isPositiveAndBelow (digit, 8)) v = v * 8 + digit;
1034 else if (isPositiveAndBelow (digit, 10)) location.throwError (
"Decimal digit in octal constant");
1038 currentValue = v; p = t;
1042 bool parseDecimalLiteral()
1048 auto digit = (int) (*p -
'0');
1049 if (isPositiveAndBelow (digit, 10)) v = v * 10 + digit;
1065 std::unique_ptr<BlockStatement> b (
new BlockStatement (location));
1067 while (currentType != TokenTypes::closeBrace && currentType != TokenTypes::eof)
1068 b->statements.add (parseStatement());
1075 match (TokenTypes::openParen);
1077 while (currentType != TokenTypes::closeParen)
1079 auto paramName = currentValue.toString();
1080 match (TokenTypes::identifier);
1081 fo.parameters.add (paramName);
1083 if (currentType != TokenTypes::closeParen)
1084 match (TokenTypes::comma);
1087 match (TokenTypes::closeParen);
1088 fo.body.reset (parseBlock());
1093 ExpPtr lhs (parseLogicOperator());
1095 if (matchIf (TokenTypes::question))
return parseTernaryOperator (lhs);
1096 if (matchIf (TokenTypes::assign)) { ExpPtr rhs (parseExpression());
return new Assignment (location, lhs, rhs); }
1097 if (matchIf (TokenTypes::plusEquals))
return parseInPlaceOpExpression<AdditionOp> (lhs);
1098 if (matchIf (TokenTypes::minusEquals))
return parseInPlaceOpExpression<SubtractionOp> (lhs);
1099 if (matchIf (TokenTypes::timesEquals))
return parseInPlaceOpExpression<MultiplyOp> (lhs);
1100 if (matchIf (TokenTypes::divideEquals))
return parseInPlaceOpExpression<DivideOp> (lhs);
1101 if (matchIf (TokenTypes::moduloEquals))
return parseInPlaceOpExpression<ModuloOp> (lhs);
1102 if (matchIf (TokenTypes::leftShiftEquals))
return parseInPlaceOpExpression<LeftShiftOp> (lhs);
1103 if (matchIf (TokenTypes::rightShiftEquals))
return parseInPlaceOpExpression<RightShiftOp> (lhs);
1105 return lhs.release();
1109 void throwError (
const String& err)
const { location.throwError (err); }
1111 template <
typename OpType>
1112 Expression* parseInPlaceOpExpression (ExpPtr& lhs)
1114 ExpPtr rhs (parseExpression());
1116 return new SelfAssignment (location, bareLHS,
new OpType (location, lhs, rhs));
1121 match (TokenTypes::openBrace);
1122 std::unique_ptr<BlockStatement> b (parseStatementList());
1123 match (TokenTypes::closeBrace);
1129 if (currentType == TokenTypes::openBrace)
return parseBlock();
1130 if (matchIf (TokenTypes::var))
return parseVar();
1131 if (matchIf (TokenTypes::if_))
return parseIf();
1132 if (matchIf (TokenTypes::while_))
return parseDoOrWhileLoop (
false);
1133 if (matchIf (TokenTypes::do_))
return parseDoOrWhileLoop (
true);
1134 if (matchIf (TokenTypes::for_))
return parseForLoop();
1135 if (matchIf (TokenTypes::return_))
return parseReturn();
1136 if (matchIf (TokenTypes::break_))
return new BreakStatement (location);
1138 if (matchIf (TokenTypes::function))
return parseFunction();
1139 if (matchIf (TokenTypes::semicolon))
return new Statement (location);
1140 if (matchIf (TokenTypes::plusplus))
return parsePreIncDec<AdditionOp>();
1141 if (matchIf (TokenTypes::minusminus))
return parsePreIncDec<SubtractionOp>();
1143 if (matchesAny (TokenTypes::openParen, TokenTypes::openBracket))
1144 return matchEndOfStatement (parseFactor());
1146 if (matchesAny (TokenTypes::identifier, TokenTypes::literal, TokenTypes::minus))
1147 return matchEndOfStatement (parseExpression());
1149 throwError (
"Found " + getTokenName (currentType) +
" when expecting a statement");
1153 Expression* matchEndOfStatement (
Expression* ex) { ExpPtr e (ex);
if (currentType != TokenTypes::eof) match (TokenTypes::semicolon);
return e.release(); }
1154 Expression* matchCloseParen (
Expression* ex) { ExpPtr e (ex); match (TokenTypes::closeParen);
return e.release(); }
1158 std::unique_ptr<IfStatement> s (
new IfStatement (location));
1159 match (TokenTypes::openParen);
1160 s->condition.reset (parseExpression());
1161 match (TokenTypes::closeParen);
1162 s->trueBranch.reset (parseStatement());
1163 s->falseBranch.reset (matchIf (TokenTypes::else_) ? parseStatement() :
new Statement (location));
1169 if (matchIf (TokenTypes::semicolon))
1173 matchIf (TokenTypes::semicolon);
1179 std::unique_ptr<VarStatement> s (
new VarStatement (location));
1180 s->name = parseIdentifier();
1181 s->initialiser.reset (matchIf (TokenTypes::assign) ? parseExpression() :
new Expression (location));
1183 if (matchIf (TokenTypes::comma))
1185 std::unique_ptr<BlockStatement> block (
new BlockStatement (location));
1186 block->statements.add (s.release());
1187 block->statements.add (parseVar());
1188 return block.release();
1191 match (TokenTypes::semicolon);
1198 auto fn = parseFunctionDefinition (name);
1201 throwError (
"Functions defined at statement-level must have a name");
1209 std::unique_ptr<LoopStatement> s (
new LoopStatement (location,
false));
1210 match (TokenTypes::openParen);
1211 s->initialiser.reset (parseStatement());
1213 if (matchIf (TokenTypes::semicolon))
1214 s->condition.reset (
new LiteralValue (location,
true));
1217 s->condition.reset (parseExpression());
1218 match (TokenTypes::semicolon);
1221 if (matchIf (TokenTypes::closeParen))
1222 s->iterator.reset (
new Statement (location));
1225 s->iterator.reset (parseExpression());
1226 match (TokenTypes::closeParen);
1229 s->body.reset (parseStatement());
1233 Statement* parseDoOrWhileLoop (
bool isDoLoop)
1235 std::unique_ptr<LoopStatement> s (
new LoopStatement (location, isDoLoop));
1236 s->initialiser.reset (
new Statement (location));
1237 s->iterator.reset (
new Statement (location));
1241 s->body.reset (parseBlock());
1242 match (TokenTypes::while_);
1245 match (TokenTypes::openParen);
1246 s->condition.reset (parseExpression());
1247 match (TokenTypes::closeParen);
1250 s->body.reset (parseStatement());
1258 if (currentType == TokenTypes::identifier)
1261 match (TokenTypes::identifier);
1267 auto functionStart = location.location;
1269 if (currentType == TokenTypes::identifier)
1270 functionName = parseIdentifier();
1273 parseFunctionParamsAndBody (*fo);
1274 fo->functionCode =
String (functionStart, location.location);
1275 return var (fo.release());
1280 std::unique_ptr<FunctionCall> s (call);
1281 s->object.reset (function.release());
1282 match (TokenTypes::openParen);
1284 while (currentType != TokenTypes::closeParen)
1286 s->arguments.add (parseExpression());
1287 if (currentType != TokenTypes::closeParen)
1288 match (TokenTypes::comma);
1291 return matchCloseParen (s.release());
1298 if (matchIf (TokenTypes::dot))
1299 return parseSuffixes (
new DotOperator (location, input, parseIdentifier()));
1301 if (currentType == TokenTypes::openParen)
1302 return parseSuffixes (parseFunctionCall (
new FunctionCall (location), input));
1304 if (matchIf (TokenTypes::openBracket))
1306 std::unique_ptr<ArraySubscript> s (
new ArraySubscript (location));
1307 s->object.reset (input.release());
1308 s->index.reset (parseExpression());
1309 match (TokenTypes::closeBracket);
1310 return parseSuffixes (s.release());
1313 if (matchIf (TokenTypes::plusplus))
return parsePostIncDec<AdditionOp> (input);
1314 if (matchIf (TokenTypes::minusminus))
return parsePostIncDec<SubtractionOp> (input);
1316 return input.release();
1321 if (currentType == TokenTypes::identifier)
return parseSuffixes (
new UnqualifiedName (location, parseIdentifier()));
1322 if (matchIf (TokenTypes::openParen))
return parseSuffixes (matchCloseParen (parseExpression()));
1323 if (matchIf (TokenTypes::true_))
return parseSuffixes (
new LiteralValue (location, (
int) 1));
1324 if (matchIf (TokenTypes::false_))
return parseSuffixes (
new LiteralValue (location, (
int) 0));
1325 if (matchIf (TokenTypes::null_))
return parseSuffixes (
new LiteralValue (location,
var()));
1326 if (matchIf (TokenTypes::undefined))
return parseSuffixes (
new Expression (location));
1328 if (currentType == TokenTypes::literal)
1330 var v (currentValue); skip();
1334 if (matchIf (TokenTypes::openBrace))
1338 while (currentType != TokenTypes::closeBrace)
1340 auto memberName = currentValue.toString();
1341 match ((currentType == TokenTypes::literal && currentValue.isString())
1342 ? TokenTypes::literal : TokenTypes::identifier);
1343 match (TokenTypes::colon);
1345 e->names.add (memberName);
1346 e->initialisers.add (parseExpression());
1348 if (currentType != TokenTypes::closeBrace)
1349 match (TokenTypes::comma);
1352 match (TokenTypes::closeBrace);
1353 return parseSuffixes (e.release());
1356 if (matchIf (TokenTypes::openBracket))
1360 while (currentType != TokenTypes::closeBracket)
1362 e->values.add (parseExpression());
1364 if (currentType != TokenTypes::closeBracket)
1365 match (TokenTypes::comma);
1368 match (TokenTypes::closeBracket);
1369 return parseSuffixes (e.release());
1372 if (matchIf (TokenTypes::function))
1375 var fn = parseFunctionDefinition (name);
1378 throwError (
"Inline functions definitions cannot have a name");
1383 if (matchIf (TokenTypes::new_))
1387 while (matchIf (TokenTypes::dot))
1388 name.reset (
new DotOperator (location, name, parseIdentifier()));
1390 return parseFunctionCall (
new NewOperator (location), name);
1393 throwError (
"Found " + getTokenName (currentType) +
" when expecting an expression");
1397 template <
typename OpType>
1401 ExpPtr lhs (e), one (
new LiteralValue (location, (
int) 1));
1402 return new SelfAssignment (location, e,
new OpType (location, lhs, one));
1405 template <
typename OpType>
1409 ExpPtr lhs2 (e), one (
new LiteralValue (location, (
int) 1));
1410 return new PostAssignment (location, e,
new OpType (location, lhs2, one));
1415 std::unique_ptr<FunctionCall> f (
new FunctionCall (location));
1417 f->arguments.add (parseUnary());
1423 if (matchIf (TokenTypes::minus)) { ExpPtr a (
new LiteralValue (location, (
int) 0)), b (parseUnary());
return new SubtractionOp (location, a, b); }
1424 if (matchIf (TokenTypes::logicalNot)) { ExpPtr a (
new LiteralValue (location, (
int) 0)), b (parseUnary());
return new EqualsOp (location, a, b); }
1425 if (matchIf (TokenTypes::plusplus))
return parsePreIncDec<AdditionOp>();
1426 if (matchIf (TokenTypes::minusminus))
return parsePreIncDec<SubtractionOp>();
1427 if (matchIf (TokenTypes::typeof_))
return parseTypeof();
1429 return parseFactor();
1434 ExpPtr a (parseUnary());
1438 if (matchIf (TokenTypes::times)) { ExpPtr b (parseUnary()); a.reset (
new MultiplyOp (location, a, b)); }
1439 else if (matchIf (TokenTypes::divide)) { ExpPtr b (parseUnary()); a.reset (
new DivideOp (location, a, b)); }
1440 else if (matchIf (TokenTypes::modulo)) { ExpPtr b (parseUnary()); a.reset (
new ModuloOp (location, a, b)); }
1449 ExpPtr a (parseMultiplyDivide());
1453 if (matchIf (TokenTypes::plus)) { ExpPtr b (parseMultiplyDivide()); a.reset (
new AdditionOp (location, a, b)); }
1454 else if (matchIf (TokenTypes::minus)) { ExpPtr b (parseMultiplyDivide()); a.reset (
new SubtractionOp (location, a, b)); }
1463 ExpPtr a (parseAdditionSubtraction());
1467 if (matchIf (TokenTypes::leftShift)) { ExpPtr b (parseExpression()); a.reset (
new LeftShiftOp (location, a, b)); }
1468 else if (matchIf (TokenTypes::rightShift)) { ExpPtr b (parseExpression()); a.reset (
new RightShiftOp (location, a, b)); }
1469 else if (matchIf (TokenTypes::rightShiftUnsigned)) { ExpPtr b (parseExpression()); a.reset (
new RightShiftUnsignedOp (location, a, b)); }
1478 ExpPtr a (parseShiftOperator());
1482 if (matchIf (TokenTypes::equals)) { ExpPtr b (parseShiftOperator()); a.reset (
new EqualsOp (location, a, b)); }
1483 else if (matchIf (TokenTypes::notEquals)) { ExpPtr b (parseShiftOperator()); a.reset (
new NotEqualsOp (location, a, b)); }
1484 else if (matchIf (TokenTypes::typeEquals)) { ExpPtr b (parseShiftOperator()); a.reset (
new TypeEqualsOp (location, a, b)); }
1485 else if (matchIf (TokenTypes::typeNotEquals)) { ExpPtr b (parseShiftOperator()); a.reset (
new TypeNotEqualsOp (location, a, b)); }
1486 else if (matchIf (TokenTypes::lessThan)) { ExpPtr b (parseShiftOperator()); a.reset (
new LessThanOp (location, a, b)); }
1487 else if (matchIf (TokenTypes::lessThanOrEqual)) { ExpPtr b (parseShiftOperator()); a.reset (
new LessThanOrEqualOp (location, a, b)); }
1488 else if (matchIf (TokenTypes::greaterThan)) { ExpPtr b (parseShiftOperator()); a.reset (
new GreaterThanOp (location, a, b)); }
1489 else if (matchIf (TokenTypes::greaterThanOrEqual)) { ExpPtr b (parseShiftOperator()); a.reset (
new GreaterThanOrEqualOp (location, a, b)); }
1498 ExpPtr a (parseComparator());
1502 if (matchIf (TokenTypes::logicalAnd)) { ExpPtr b (parseComparator()); a.reset (
new LogicalAndOp (location, a, b)); }
1503 else if (matchIf (TokenTypes::logicalOr)) { ExpPtr b (parseComparator()); a.reset (
new LogicalOrOp (location, a, b)); }
1504 else if (matchIf (TokenTypes::bitwiseAnd)) { ExpPtr b (parseComparator()); a.reset (
new BitwiseAndOp (location, a, b)); }
1505 else if (matchIf (TokenTypes::bitwiseOr)) { ExpPtr b (parseComparator()); a.reset (
new BitwiseOrOp (location, a, b)); }
1506 else if (matchIf (TokenTypes::bitwiseXor)) { ExpPtr b (parseComparator()); a.reset (
new BitwiseXorOp (location, a, b)); }
1513 Expression* parseTernaryOperator (ExpPtr& condition)
1515 std::unique_ptr<ConditionalOp> e (
new ConditionalOp (location));
1516 e->condition.reset (condition.release());
1517 e->trueBranch.reset (parseExpression());
1518 match (TokenTypes::colon);
1519 e->falseBranch.reset (parseExpression());
1527 static var get (
Args a,
int index)
noexcept {
return index < a.numArguments ? a.arguments[index] :
var(); }
1528 static bool isInt (Args a,
int index)
noexcept {
return get (a, index).isInt() || get (a, index).isInt64(); }
1529 static int getInt (Args a,
int index)
noexcept {
return get (a, index); }
1530 static double getDouble (Args a,
int index)
noexcept {
return get (a, index); }
1531 static String getString (Args a,
int index)
noexcept {
return get (a, index).toString(); }
1538 setMethod (
"dump", dump);
1539 setMethod (
"clone", cloneFn);
1543 static var dump (
Args a) { DBG (JSON::toString (a.thisObject)); ignoreUnused (a);
return var::undefined(); }
1544 static var cloneFn (
Args a) {
return a.thisObject.
clone(); }
1552 setMethod (
"contains", contains);
1553 setMethod (
"remove", remove);
1554 setMethod (
"join", join);
1555 setMethod (
"push", push);
1556 setMethod (
"splice", splice);
1557 setMethod (
"indexOf", indexOf);
1564 if (
auto* array = a.thisObject.
getArray())
1565 return array->contains (get (a, 0));
1572 if (
auto* array = a.thisObject.
getArray())
1573 array->removeAllInstancesOf (get (a, 0));
1575 return var::undefined();
1582 if (
auto* array = a.thisObject.
getArray())
1583 for (
auto& v : *array)
1584 strings.
add (v.toString());
1591 if (
auto* array = a.thisObject.
getArray())
1593 for (
int i = 0; i < a.numArguments; ++i)
1594 array->add (a.arguments[i]);
1596 return array->
size();
1599 return var::undefined();
1604 if (
auto* array = a.thisObject.
getArray())
1606 auto arraySize = array->
size();
1607 int start = get (a, 0);
1610 start = jmax (0, arraySize + start);
1611 else if (start > arraySize)
1614 const int num = a.numArguments > 1 ? jlimit (0, arraySize - start, getInt (a, 1))
1615 : arraySize - start;
1620 for (
int i = 0; i < num; ++i)
1621 itemsRemoved.
add (array->getReference (start + i));
1623 array->removeRange (start, num);
1625 for (
int i = 2; i < a.numArguments; ++i)
1626 array->insert (start++, get (a, i));
1628 return itemsRemoved;
1631 return var::undefined();
1636 if (
auto* array = a.thisObject.
getArray())
1638 auto target = get (a, 0);
1640 for (
int i = (a.numArguments > 1 ? getInt (a, 1) : 0); i < array->size(); ++i)
1641 if (array->getReference(i) == target)
1654 setMethod (
"substring", substring);
1655 setMethod (
"indexOf", indexOf);
1656 setMethod (
"charAt", charAt);
1657 setMethod (
"charCodeAt", charCodeAt);
1658 setMethod (
"fromCharCode", fromCharCode);
1659 setMethod (
"split", split);
1664 static var fromCharCode (
Args a) {
return String::charToString (
static_cast<juce_wchar
> (getInt (a, 0))); }
1665 static var substring (
Args a) {
return a.thisObject.toString().
substring (getInt (a, 0), getInt (a, 1)); }
1666 static var indexOf (
Args a) {
return a.thisObject.toString().
indexOf (getString (a, 0)); }
1667 static var charCodeAt (
Args a) {
return (
int) a.thisObject.toString() [getInt (a, 0)]; }
1668 static var charAt (
Args a) {
int p = getInt (a, 0);
return a.thisObject.toString().
substring (p, p + 1); }
1672 auto str = a.thisObject.toString();
1673 auto sep = getString (a, 0);
1676 if (sep.isNotEmpty())
1677 strings.
addTokens (str, sep.substring (0, 1), {});
1679 for (
auto pos = str.getCharPointer(); ! pos.isEmpty(); ++pos)
1680 strings.
add (String::charToString (*pos));
1684 for (
auto& s : strings)
1696 setMethod (
"abs", Math_abs); setMethod (
"round", Math_round);
1697 setMethod (
"random", Math_random); setMethod (
"randInt", Math_randInt);
1698 setMethod (
"min", Math_min); setMethod (
"max", Math_max);
1699 setMethod (
"range", Math_range); setMethod (
"sign", Math_sign);
1700 setMethod (
"toDegrees", Math_toDegrees); setMethod (
"toRadians", Math_toRadians);
1701 setMethod (
"sin", Math_sin); setMethod (
"asin", Math_asin);
1702 setMethod (
"sinh", Math_sinh); setMethod (
"asinh", Math_asinh);
1703 setMethod (
"cos", Math_cos); setMethod (
"acos", Math_acos);
1704 setMethod (
"cosh", Math_cosh); setMethod (
"acosh", Math_acosh);
1705 setMethod (
"tan", Math_tan); setMethod (
"atan", Math_atan);
1706 setMethod (
"tanh", Math_tanh); setMethod (
"atanh", Math_atanh);
1707 setMethod (
"log", Math_log); setMethod (
"log10", Math_log10);
1708 setMethod (
"exp", Math_exp); setMethod (
"pow", Math_pow);
1709 setMethod (
"sqr", Math_sqr); setMethod (
"sqrt", Math_sqrt);
1710 setMethod (
"ceil", Math_ceil); setMethod (
"floor", Math_floor);
1715 setProperty (
"SQRT1_2", std::sqrt (0.5));
1716 setProperty (
"LN2", std::log (2.0));
1717 setProperty (
"LN10", std::log (10.0));
1722 static var Math_random (
Args) {
return Random::getSystemRandom().nextDouble(); }
1723 static var Math_randInt (
Args a) {
return Random::getSystemRandom().nextInt (
Range<int> (getInt (a, 0), getInt (a, 1))); }
1724 static var Math_abs (
Args a) {
return isInt (a, 0) ?
var (std::abs (getInt (a, 0))) :
var (std::abs (getDouble (a, 0))); }
1725 static var Math_round (
Args a) {
return isInt (a, 0) ?
var (roundToInt (getInt (a, 0))) :
var (roundToInt (getDouble (a, 0))); }
1726 static var Math_sign (
Args a) {
return isInt (a, 0) ?
var (sign (getInt (a, 0))) :
var (sign (getDouble (a, 0))); }
1727 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))); }
1728 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))); }
1729 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))); }
1730 static var Math_toDegrees (
Args a) {
return radiansToDegrees (getDouble (a, 0)); }
1731 static var Math_toRadians (
Args a) {
return degreesToRadians (getDouble (a, 0)); }
1732 static var Math_sin (
Args a) {
return std::sin (getDouble (a, 0)); }
1733 static var Math_asin (
Args a) {
return std::asin (getDouble (a, 0)); }
1734 static var Math_cos (
Args a) {
return std::cos (getDouble (a, 0)); }
1735 static var Math_acos (
Args a) {
return std::acos (getDouble (a, 0)); }
1736 static var Math_sinh (
Args a) {
return std::sinh (getDouble (a, 0)); }
1737 static var Math_cosh (
Args a) {
return std::cosh (getDouble (a, 0)); }
1738 static var Math_tan (
Args a) {
return std::tan (getDouble (a, 0)); }
1739 static var Math_tanh (
Args a) {
return std::tanh (getDouble (a, 0)); }
1740 static var Math_atan (
Args a) {
return std::atan (getDouble (a, 0)); }
1741 static var Math_log (
Args a) {
return std::log (getDouble (a, 0)); }
1742 static var Math_log10 (
Args a) {
return std::log10 (getDouble (a, 0)); }
1743 static var Math_exp (
Args a) {
return std::exp (getDouble (a, 0)); }
1744 static var Math_pow (
Args a) {
return std::pow (getDouble (a, 0), getDouble (a, 1)); }
1745 static var Math_sqr (
Args a) {
return square (getDouble (a, 0)); }
1746 static var Math_sqrt (
Args a) {
return std::sqrt (getDouble (a, 0)); }
1747 static var Math_ceil (
Args a) {
return std::ceil (getDouble (a, 0)); }
1748 static var Math_floor (
Args a) {
return std::floor (getDouble (a, 0)); }
1752 static var Math_asinh (
Args a) {
return asinh (getDouble (a, 0)); }
1753 static var Math_acosh (
Args a) {
return acosh (getDouble (a, 0)); }
1754 static var Math_atanh (
Args a) {
return atanh (getDouble (a, 0)); }
1757 template <
typename Type>
static Type sign (Type n)
noexcept {
return n > 0 ? (Type) 1 : (n < 0 ? (Type) -1 : 0); }
1763 JSONClass() { setMethod (
"stringify", stringify); }
1765 static var stringify (
Args a) {
return JSON::toString (get (a, 0)); }
1776 auto s = getString (a, 0).trim();
1778 return s[0] ==
'0' ? (s[1] ==
'x' ? s.substring(2).getHexValue64() : getOctalValue (s))
1779 : s.getLargeIntValue();
1784 static var trace (
Args a) { Logger::outputDebugString (JSON::toString (a.thisObject));
return var::undefined(); }
1785 static var charToInt (Args a) {
return (
int) (getString (a, 0)[0]); }
1786 static var parseFloat (Args a) {
return getDouble (a, 0); }
1788 static var typeof_internal (Args a)
1792 if (v.isVoid())
return "void";
1793 if (v.isString())
return "string";
1794 if (isNumeric (v))
return "number";
1795 if (isFunction (v) || v.isMethod())
return "function";
1796 if (v.isObject())
return "object";
1801 static var exec (Args a)
1803 if (
auto* root =
dynamic_cast<RootObject*
> (a.thisObject.getObject()))
1804 root->execute (getString (a, 0));
1806 return var::undefined();
1809 static var eval (Args a)
1811 if (
auto* root =
dynamic_cast<RootObject*
> (a.thisObject.getObject()))
1812 return root->evaluate (getString (a, 0));
1814 return var::undefined();
1836 root->setProperty (name,
object);
1844 root->execute (code);
1859 if (result !=
nullptr) *result =
Result::ok();
1860 return root->evaluate (code);
1877 if (result !=
nullptr) *result =
Result::ok();
1878 RootObject::Scope ({}, *root, *root).findAndInvokeMethod (function, args, returnVal);
1896 if (result !=
nullptr) *result =
Result::ok();
1899 .invokeMethod (functionObject, args, returnVal);
1911 return root->getProperties();
1915 #pragma warning (pop)
Holds a resizable array of primitive or copy-by-value objects.
void ensureStorageAllocated(int minNumElements)
Increases the array's internal storage to hold a minimum number of elements.
int size() const noexcept
Returns the current number of elements in the array.
ElementType * begin() const noexcept
Returns a pointer to the first element in the array.
void add(const ElementType &newElement)
Appends a new element at the end of the array.
An arbitrarily large integer class.
void parseString(StringRef text, int base)
Reads the numeric value from a string.
int64 toInt64() const noexcept
Attempts to get the lowest 64 bits of the value as an integer.
Wraps a pointer to a null-terminated ASCII character string, and provides various methods to operate ...
Wraps a pointer to a null-terminated UTF-8 character string, and provides various methods to operate ...
int compareUpTo(const CharPointer other, const int maxChars) const noexcept
Compares this string with another one, up to a specified number of characters.
bool isEmpty() const noexcept
Returns true if this pointer is pointing to a null character.
CharPointer_UTF8 findEndOfWhitespace() const noexcept
Returns the first non-whitespace character in the string.
bool isDigit() const noexcept
Returns true if the first character of this string is a digit.
Represents a dynamically implemented object.
NamedValueSet & getProperties() noexcept
Returns the NamedValueSet that holds the object's properties.
virtual var invokeMethod(Identifier methodName, const var::NativeFunctionArgs &args)
Invokes a named method on this object.
virtual bool hasMethod(const Identifier &methodName) const
Checks whether this object has the specified method.
virtual const var & getProperty(const Identifier &propertyName) const
Returns a named property.
virtual void setProperty(const Identifier &propertyName, const var &newValue)
Sets a named property.
Represents a string identifier, designed for accessing properties by name.
bool isNull() const noexcept
Returns true if this Identifier is null.
String::CharPointerType getCharPointer() const noexcept
Returns this identifier's raw string pointer.
bool isValid() const noexcept
Returns true if this Identifier is not null.
const String & toString() const noexcept
Returns this identifier as a string.
void stop() noexcept
When called from another thread, causes the interpreter to time-out as soon as possible.
const NamedValueSet & getRootObjectProperties() const noexcept
Provides access to the set of properties of the root namespace object.
Result execute(const String &javascriptCode)
Attempts to parse and run a block of javascript code.
var callFunction(const Identifier &function, const var::NativeFunctionArgs &args, Result *errorMessage=nullptr)
Calls a function in the root namespace, and returns the result.
var evaluate(const String &javascriptCode, Result *errorMessage=nullptr)
Attempts to parse and run a javascript expression, and returns the result.
void registerNativeObject(const Identifier &objectName, DynamicObject *object)
Adds a native object to the root namespace.
var callFunctionObject(DynamicObject *objectScope, const var &functionObject, const var::NativeFunctionArgs &args, Result *errorMessage=nullptr)
Calls a function object in the namespace of a dynamic object, and returns the result.
JavascriptEngine()
Creates an instance of the engine.
RelativeTime maximumExecutionTime
This value indicates how long a call to one of the evaluate methods is permitted to run before timing...
~JavascriptEngine()
Destructor.
Holds a set of named var objects.
var * getVarPointer(const Identifier &name) const noexcept
Returns a pointer to the var that holds a named value, or null if there is no value with this name.
The base class for streams that write data to some kind of destination.
An array designed for holding objects.
A general-purpose range object, that simply represents any linear range with a start and end point.
A smart-pointer class which points to a reference-counted object.
ReferencedType * get() const noexcept
Returns the object that this pointer references.
Represents the 'success' or 'failure' of an operation, and holds an associated error message to descr...
static Result fail(const String &errorMessage) noexcept
Creates a 'failure' result.
static Result ok() noexcept
Creates and returns a 'successful' result.
A special array for holding a list of strings.
String joinIntoString(StringRef separatorString, int startIndex=0, int numberOfElements=-1) const
Joins the strings in the array together into one string.
void add(String stringToAdd)
Appends a string at the end of the array.
int addTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
Breaks up a string into tokens and adds them to this array.
CharPointerType getCharPointer() const noexcept
Returns the character pointer currently being used to store this string.
int indexOf(StringRef textToLookFor) const noexcept
Searches for a substring within this string.
String initialSectionContainingOnly(StringRef permittedCharacters) const
Returns a section from the start of the string that only contains a certain set of characters.
String substring(int startIndex, int endIndex) const
Returns a subsection of the string.
Holds an absolute date and time.
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Returns a Time object that is set to the current system time.
A variant class, that can be used to hold a range of primitive values.
static var undefined() noexcept
Returns a var object that can be used where you need the javascript "undefined" value.
int size() const
If the var is an array, this returns the number of elements.
var invoke(const Identifier &method, const var *arguments, int numArguments) const
Invokes a named method call with a list of arguments.
Array< var > * getArray() const noexcept
If this variant holds an array, this provides access to it.
void append(const var &valueToAppend)
Appends an element to the var, converting it to an array if it isn't already one.
bool hasSameTypeAs(const var &other) const noexcept
Returns true if this var has the same type as the one supplied.
var clone() const noexcept
Returns a deep copy of this object.
void writeAsJSON(OutputStream &out, int, bool, int) override
Writes this object to a text stream in JSON format.
DynamicObject::Ptr clone() override
Returns a clone of this object.
Commonly used mathematical constants.
This structure is passed to a NativeFunction callback, and contains invocation details about the func...