source: XmlTools2/trunk/XmlTools/libs/TinyJS.h@ 906

Last change on this file since 906 was 905, checked in by s10k, 11 years ago

XmlTools v2

File size: 95.2 KB
Line 
1/*
2 * TinyJS
3 *
4 * A single-file Javascript-alike engine
5 *
6 * Authored By Gordon Williams <gw@pur3.co.uk>
7 *
8 * Copyright (C) 2009 Pur3 Ltd
9 *
10
11 * 42TinyJS
12 *
13 * A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine
14 *
15 * Authored / Changed By Armin Diedering <armin@diedering.de>
16 *
17 * Copyright (C) 2010-2013 ardisoft
18 *
19 *
20 * Permission is hereby granted, free of charge, to any person obtaining a copy of
21 * this software and associated documentation files (the "Software"), to deal in
22 * the Software without restriction, including without limitation the rights to
23 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
24 * of the Software, and to permit persons to whom the Software is furnished to do
25 * so, subject to the following conditions:
26
27 * The above copyright notice and this permission notice shall be included in all
28 * copies or substantial portions of the Software.
29
30 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36 * SOFTWARE.
37 */
38
39#ifndef TINYJS_H
40#define TINYJS_H
41
42#include <string>
43#include <vector>
44#include <map>
45#include <set>
46#include <stdint.h>
47#include <cassert>
48#include <limits>
49
50#include "config.h"
51
52#if __cplusplus >= 201103L
53# define MEMBER_DELETE =delete
54#else
55# define MEMBER_DELETE
56#endif
57
58#ifdef NO_POOL_ALLOCATOR
59 template<typename T, int num_objects=64>
60 class fixed_size_object {};
61#else
62# include "pool_allocator.h"
63#endif
64
65#ifdef _MSC_VER
66# if defined(_DEBUG) && defined(_DEBUG_NEW)
67# define _AFXDLL
68# include <afx.h> // MFC-Kern- und -Standardkomponenten
69# define new DEBUG_NEW
70# endif
71# define DEPRECATED(_Text) __declspec(deprecated(_Text))
72#elif defined(__GNUC__)
73# define DEPRECATED(_Text) __attribute__ ((deprecated))
74#else
75# define DEPRECATED(_Text)
76#endif
77
78#ifndef ASSERT
79# define ASSERT(X) assert(X)
80#endif
81
82#undef TRACE
83#ifndef TRACE
84#define TRACE printf
85#endif // TRACE
86
87enum LEX_TYPES {
88 LEX_EOF = 0,
89#define LEX_RELATIONS_1_BEGIN LEX_EQUAL
90 LEX_EQUAL = 256,
91 LEX_TYPEEQUAL,
92 LEX_NEQUAL,
93 LEX_NTYPEEQUAL,
94#define LEX_RELATIONS_1_END LEX_NTYPEEQUAL
95 LEX_LEQUAL,
96 LEX_GEQUAL,
97#define LEX_SHIFTS_BEGIN LEX_LSHIFT
98 LEX_LSHIFT,
99 LEX_RSHIFT,
100 LEX_RSHIFTU, // unsigned
101#define LEX_SHIFTS_END LEX_RSHIFTU
102 LEX_PLUSPLUS,
103 LEX_MINUSMINUS,
104 LEX_ANDAND,
105 LEX_OROR,
106 LEX_INT,
107
108#define LEX_ASSIGNMENTS_BEGIN LEX_PLUSEQUAL
109 LEX_PLUSEQUAL,
110 LEX_MINUSEQUAL,
111 LEX_ASTERISKEQUAL,
112 LEX_SLASHEQUAL,
113 LEX_PERCENTEQUAL,
114 LEX_LSHIFTEQUAL,
115 LEX_RSHIFTEQUAL,
116 LEX_RSHIFTUEQUAL, // unsigned
117 LEX_ANDEQUAL,
118 LEX_OREQUAL,
119 LEX_XOREQUAL,
120#define LEX_ASSIGNMENTS_END LEX_XOREQUAL
121
122#define LEX_TOKEN_NONSIMPLE_1_BEGIN LEX_TOKEN_STRING_BEGIN
123#define LEX_TOKEN_STRING_BEGIN LEX_ID
124 LEX_ID,
125 LEX_STR,
126 LEX_REGEXP,
127 LEX_T_LABEL,
128 LEX_T_DUMMY_LABEL,
129#define LEX_TOKEN_STRING_END LEX_T_DUMMY_LABEL
130
131 LEX_FLOAT,
132#define LEX_TOKEN_NONSIMPLE_1_END LEX_FLOAT
133
134 // reserved words
135 LEX_R_IF,
136 LEX_R_ELSE,
137 LEX_R_DO,
138 LEX_R_WHILE,
139 LEX_R_FOR,
140 LEX_R_IN,
141 LEX_T_OF,
142 LEX_R_BREAK,
143 LEX_R_CONTINUE,
144 LEX_R_RETURN,
145 LEX_R_VAR,
146 LEX_R_LET,
147 LEX_R_CONST,
148 LEX_R_WITH,
149 LEX_R_TRUE,
150 LEX_R_FALSE,
151 LEX_R_NULL,
152 LEX_R_NEW,
153 LEX_R_TRY,
154 LEX_R_CATCH,
155 LEX_R_FINALLY,
156 LEX_R_THROW,
157 LEX_R_TYPEOF,
158 LEX_R_VOID,
159 LEX_R_DELETE,
160 LEX_R_INSTANCEOF,
161 LEX_R_SWITCH,
162 LEX_R_CASE,
163 LEX_R_DEFAULT,
164
165 // special token
166// LEX_T_FILE,
167#define LEX_TOKEN_NONSIMPLE_2_BEGIN LEX_TOKEN_FOR_BEGIN
168#define LEX_TOKEN_FOR_BEGIN LEX_T_LOOP
169 LEX_T_LOOP,
170 LEX_T_FOR_IN,
171#define LEX_TOKEN_FOR_END LEX_T_FOR_IN
172#define LEX_TOKEN_FUNCTION_BEGIN LEX_R_FUNCTION
173 LEX_R_FUNCTION,
174 LEX_T_FUNCTION_PLACEHOLDER,
175 LEX_T_FUNCTION_OPERATOR,
176 LEX_T_GET,
177 LEX_T_SET,
178#define LEX_TOKEN_FUNCTION_END LEX_T_SET
179 LEX_T_TRY,
180 LEX_T_OBJECT_LITERAL,
181 LEX_T_DESTRUCTURING_VAR,
182 LEX_T_FORWARD,
183#define LEX_TOKEN_NONSIMPLE_2_END LEX_T_FORWARD
184
185 LEX_T_EXCEPTION_VAR,
186 LEX_T_SKIP,
187};
188#define LEX_TOKEN_DATA_STRING(tk) ((LEX_TOKEN_STRING_BEGIN<= tk && tk <= LEX_TOKEN_STRING_END))
189#define LEX_TOKEN_DATA_FLOAT(tk) (tk==LEX_FLOAT)
190#define LEX_TOKEN_DATA_LOOP(tk) (LEX_TOKEN_FOR_BEGIN <= tk && tk <= LEX_TOKEN_FOR_END)
191#define LEX_TOKEN_DATA_FUNCTION(tk) (LEX_TOKEN_FUNCTION_BEGIN <= tk && tk <= LEX_TOKEN_FUNCTION_END)
192#define LEX_TOKEN_DATA_TRY(tk) (tk == LEX_T_TRY)
193#define LEX_TOKEN_DATA_OBJECT_LITERAL(tk) (tk==LEX_T_OBJECT_LITERAL)
194#define LEX_TOKEN_DATA_DESTRUCTURING_VAR(tk) (tk==LEX_T_DESTRUCTURING_VAR)
195#define LEX_TOKEN_DATA_FORWARDER(tk) (tk==LEX_T_FORWARD)
196
197#define LEX_TOKEN_DATA_SIMPLE(tk) (!((LEX_TOKEN_NONSIMPLE_1_BEGIN <= tk && tk <= LEX_TOKEN_NONSIMPLE_1_END) || (LEX_TOKEN_NONSIMPLE_2_BEGIN <= tk && tk <= LEX_TOKEN_NONSIMPLE_2_END)))
198
199enum SCRIPTVARLINK_FLAGS {
200 SCRIPTVARLINK_WRITABLE = 1<<0,
201 SCRIPTVARLINK_CONFIGURABLE = 1<<1,
202 SCRIPTVARLINK_ENUMERABLE = 1<<2,
203 SCRIPTVARLINK_DEFAULT = SCRIPTVARLINK_WRITABLE | SCRIPTVARLINK_CONFIGURABLE | SCRIPTVARLINK_ENUMERABLE,
204 SCRIPTVARLINK_VARDEFAULT = SCRIPTVARLINK_WRITABLE | SCRIPTVARLINK_ENUMERABLE,
205 SCRIPTVARLINK_CONSTDEFAULT = SCRIPTVARLINK_ENUMERABLE,
206 SCRIPTVARLINK_BUILDINDEFAULT = SCRIPTVARLINK_WRITABLE | SCRIPTVARLINK_CONFIGURABLE,
207 SCRIPTVARLINK_READONLY = SCRIPTVARLINK_CONFIGURABLE,
208 SCRIPTVARLINK_READONLY_ENUM = SCRIPTVARLINK_CONFIGURABLE | SCRIPTVARLINK_ENUMERABLE,
209 SCRIPTVARLINK_CONSTANT = 0,
210};
211
212enum ERROR_TYPES {
213 Error = 0,
214 EvalError,
215 RangeError,
216 ReferenceError,
217 SyntaxError,
218 TypeError
219};
220#define ERROR_MAX TypeError
221#define ERROR_COUNT (ERROR_MAX+1)
222extern const char *ERROR_NAME[];
223
224
225#define TINYJS_RETURN_VAR "return"
226#define TINYJS_LOKALE_VAR "__locale__"
227#define TINYJS_ANONYMOUS_VAR "__anonymous__"
228#define TINYJS_ARGUMENTS_VAR "arguments"
229#define TINYJS___PROTO___VAR "__proto__"
230#define TINYJS_PROTOTYPE_CLASS "prototype"
231#define TINYJS_FUNCTION_CLOSURE_VAR "__function_closure__"
232#define TINYJS_SCOPE_PARENT_VAR "__scope_parent__"
233#define TINYJS_SCOPE_WITH_VAR "__scope_with__"
234#define TINYJS_ACCESSOR_GET_VAR "__accessor_get__"
235#define TINYJS_ACCESSOR_SET_VAR "__accessor_set__"
236#define TINYJS_TEMP_NAME ""
237#define TINYJS_BLANK_DATA ""
238
239typedef std::vector<std::string> STRING_VECTOR_t;
240typedef STRING_VECTOR_t::iterator STRING_VECTOR_it;
241
242typedef std::set<std::string> STRING_SET_t;
243typedef STRING_SET_t::iterator STRING_SET_it;
244
245/// convert the given string into a quoted string suitable for javascript
246std::string getJSString(const std::string &str);
247/// convert the given int into a string
248std::string int2string(int32_t intData);
249std::string int2string(uint32_t intData);
250/// convert the given double into a string
251std::string float2string(const double &floatData);
252
253
254//////////////////////////////////////////////////////////////////////////
255/// CScriptException
256//////////////////////////////////////////////////////////////////////////
257
258class CScriptException {
259public:
260 ERROR_TYPES errorType;
261 std::string message;
262 std::string fileName;
263 int lineNumber;
264 int column;
265 CScriptException(const std::string &Message, const std::string &File, int Line=-1, int Column=-1) :
266 errorType(Error), message(Message), fileName(File), lineNumber(Line), column(Column){}
267 CScriptException(ERROR_TYPES ErrorType, const std::string &Message, const std::string &File, int Line=-1, int Column=-1) :
268 errorType(ErrorType), message(Message), fileName(File), lineNumber(Line), column(Column){}
269 CScriptException(const std::string &Message, const char *File="", int Line=-1, int Column=-1) :
270 errorType(Error), message(Message), fileName(File), lineNumber(Line), column(Column){}
271 CScriptException(ERROR_TYPES ErrorType, const std::string &Message, const char *File="", int Line=-1, int Column=-1) :
272 errorType(ErrorType), message(Message), fileName(File), lineNumber(Line), column(Column){}
273 std::string toString();
274};
275
276
277//////////////////////////////////////////////////////////////////////////
278/// CScriptLex
279//////////////////////////////////////////////////////////////////////////
280
281class CScriptLex
282{
283public:
284 CScriptLex(const char *Code, const std::string &File="", int Line=0, int Column=0);
285 struct POS;
286 int tk; ///< The type of the token that we have
287 int last_tk; ///< The type of the last token that we have
288 std::string tkStr; ///< Data contained in the token we have here
289
290 void check(int expected_tk, int alternate_tk=-1); ///< Lexical check wotsit
291 void match(int expected_tk, int alternate_tk=-1); ///< Lexical match wotsit
292 void reset(const POS &toPos); ///< Reset this lex so we can start again
293
294 std::string currentFile;
295 struct POS {
296 const char *tokenStart;
297 int currentLine;
298 const char *currentLineStart;
299 } pos;
300 int currentLine() { return pos.currentLine; }
301 int currentColumn() { return pos.tokenStart-pos.currentLineStart; }
302 bool lineBreakBeforeToken;
303private:
304 const char *data;
305 const char *dataPos;
306 char currCh, nextCh;
307
308 void getNextCh();
309 void getNextToken(); ///< Get the text token from our text string
310};
311
312
313//////////////////////////////////////////////////////////////////////////
314/// CScriptTokenData
315//////////////////////////////////////////////////////////////////////////
316
317class CScriptToken;
318typedef std::vector<CScriptToken> TOKEN_VECT;
319typedef std::vector<CScriptToken>::iterator TOKEN_VECT_it;
320typedef std::vector<CScriptToken>::const_iterator TOKEN_VECT_cit;
321class CScriptTokenData
322{
323protected:
324 CScriptTokenData() : refs(0){}
325 virtual ~CScriptTokenData() {}
326private:
327// CScriptTokenData(const CScriptTokenData &noCopy);
328// CScriptTokenData &operator=(const CScriptTokenData &noCopy);
329public:
330 void ref() { refs++; }
331 void unref() { if(--refs == 0) delete this; }
332private:
333 int refs;
334};
335template<typename C>
336class CScriptTokenDataPtr {
337public:
338 CScriptTokenDataPtr() : ptr(0) {}
339 CScriptTokenDataPtr(const CScriptTokenDataPtr &Copy) : ptr(0) { *this=Copy; }
340 CScriptTokenDataPtr &operator=(const CScriptTokenDataPtr &Copy) {
341 if(ptr != Copy.ptr) {
342 if(ptr) ptr->unref();
343 if((ptr = Copy.ptr)) ptr->ref();
344 }
345 return *this;
346 }
347 CScriptTokenDataPtr(C &Init) { (ptr=&Init)->ref(); }
348 ~CScriptTokenDataPtr() { if(ptr) ptr->unref(); }
349 C *operator->() { return ptr; }
350 C &operator*() { return *ptr; }
351 operator bool() { return ptr!=0; }
352 bool operator==(const CScriptTokenDataPtr& rhs) { return ptr==rhs.ptr; }
353private:
354 C *ptr;
355};
356
357class CScriptTokenDataString : public fixed_size_object<CScriptTokenDataString>, public CScriptTokenData {
358public:
359 CScriptTokenDataString(const std::string &String) : tokenStr(String) {}
360 std::string tokenStr;
361private:
362};
363
364class CScriptTokenDataFnc : public fixed_size_object<CScriptTokenDataFnc>, public CScriptTokenData {
365public:
366 std::string file;
367 int line;
368 std::string name;
369 TOKEN_VECT arguments;
370 TOKEN_VECT body;
371 std::string getArgumentsString();
372};
373
374class CScriptTokenDataForwards : public fixed_size_object<CScriptTokenDataForwards>, public CScriptTokenData {
375public:
376 CScriptTokenDataForwards() {}
377 enum {
378 LETS = 0,
379 VARS,
380 CONSTS,
381 END
382 };
383 STRING_SET_t varNames[END];
384 STRING_SET_t vars_in_letscope;
385 class compare_fnc_token_by_name {
386 public:
387 bool operator()(const CScriptToken& lhs, const CScriptToken& rhs) const;
388 };
389 typedef std::set<CScriptToken, compare_fnc_token_by_name> FNC_SET_t;
390 typedef FNC_SET_t::iterator FNC_SET_it;
391 FNC_SET_t functions;
392 bool checkRedefinition(const std::string &Str, bool checkVars);
393 void addVars( STRING_VECTOR_t &Vars );
394 void addConsts( STRING_VECTOR_t &Vars );
395 std::string addVarsInLetscope(STRING_VECTOR_t &Vars);
396 std::string addLets(STRING_VECTOR_t &Lets);
397 bool empty() { return varNames[LETS].empty() && varNames[VARS].empty() && varNames[CONSTS].empty() && functions.empty(); }
398private:
399};
400class CScriptTokenDataForwardsPtr {
401public:
402 CScriptTokenDataForwardsPtr() : ptr(0) {}
403 CScriptTokenDataForwardsPtr(const CScriptTokenDataForwardsPtr &Copy) : ptr(0) { *this=Copy; }
404 CScriptTokenDataForwardsPtr &operator=(const CScriptTokenDataForwardsPtr &Copy) {
405 if(ptr != Copy.ptr) {
406 if(ptr) ptr->unref();
407 if((ptr = Copy.ptr)) ptr->ref();
408 }
409 return *this;
410 }
411 CScriptTokenDataForwardsPtr(CScriptTokenDataForwards &Init) { (ptr=&Init)->ref(); }
412 ~CScriptTokenDataForwardsPtr() { if(ptr) ptr->unref(); }
413 CScriptTokenDataForwards *operator->() { return ptr; }
414 operator bool() { return ptr!=0; }
415 bool operator==(const CScriptTokenDataForwardsPtr& rhs) { return ptr==rhs.ptr; }
416private:
417 CScriptTokenDataForwards *ptr;
418};
419typedef std::vector<CScriptTokenDataForwardsPtr> FORWARDER_VECTOR_t;
420
421class CScriptTokenDataLoop : public fixed_size_object<CScriptTokenDataLoop>, public CScriptTokenData {
422public:
423 CScriptTokenDataLoop() { type=FOR; }
424 enum {FOR_EACH=0, FOR_IN, FOR_OF, FOR, WHILE, DO} type; // do not change the order
425 STRING_VECTOR_t labels;
426 TOKEN_VECT init;
427 TOKEN_VECT condition;
428 TOKEN_VECT iter;
429 TOKEN_VECT body;
430 std::string getParsableString(const std::string &IndentString="", const std::string &Indent="");
431};
432
433typedef std::pair<std::string, std::string> DESTRUCTURING_VAR_t;
434typedef std::vector<DESTRUCTURING_VAR_t> DESTRUCTURING_VARS_t;
435typedef DESTRUCTURING_VARS_t::iterator DESTRUCTURING_VARS_it;
436typedef DESTRUCTURING_VARS_t::const_iterator DESTRUCTURING_VARS_cit;
437class CScriptTokenDataDestructuringVar : public fixed_size_object<CScriptTokenDataDestructuringVar>, public CScriptTokenData {
438public:
439 DESTRUCTURING_VARS_t vars;
440 void getVarNames(STRING_VECTOR_t Name);
441 std::string getParsableString();
442private:
443};
444
445class CScriptTokenDataObjectLiteral : public fixed_size_object<CScriptTokenDataObjectLiteral>, public CScriptTokenData {
446public:
447 enum {ARRAY, OBJECT} type;
448 int flags;
449 struct ELEMENT {
450 std::string id;
451 TOKEN_VECT value;
452 };
453 bool destructuring;
454 bool structuring;
455 std::vector<ELEMENT> elements;
456 void setMode(bool Destructuring);
457 std::string getParsableString();
458private:
459};
460
461class CScriptTokenDataTry : public fixed_size_object<CScriptTokenDataTry>, public CScriptTokenData {
462public:
463 TOKEN_VECT tryBlock;
464 struct CatchBlock {
465 CScriptTokenDataPtr<CScriptTokenDataDestructuringVar> indentifiers;
466 TOKEN_VECT condition;
467 TOKEN_VECT block;
468 };
469 std::vector<CatchBlock> catchBlocks;
470 typedef std::vector<CatchBlock>::iterator CatchBlock_it;
471 TOKEN_VECT finallyBlock;
472 std::string getParsableString(const std::string &IndentString="", const std::string &Indent="");
473};
474
475
476//////////////////////////////////////////////////////////////////////////
477/// CScriptToken
478//////////////////////////////////////////////////////////////////////////
479
480class CScriptTokenizer;
481/*
482 a Token needs 8 Byte
483 2 Bytes for the Row-Position of the Token
484 2 Bytes for the Token self
485 and
486 4 Bytes for special Datas in an union
487 e.g. an int for interger-literals
488 or pointer for double-literals,
489 for string-literals or for functions
490*/
491class CScriptToken : public fixed_size_object<CScriptToken>
492{
493public:
494 CScriptToken() : line(0), column(0), token(0), intData(0) {}
495 CScriptToken(CScriptLex *l, int Match=-1, int Alternate=-1);
496 CScriptToken(uint16_t Tk, int IntData=0);
497 CScriptToken(uint16_t Tk, const std::string &TkStr);
498 CScriptToken(const CScriptToken &Copy) : token(0) { *this = Copy; }
499 CScriptToken &operator =(const CScriptToken &Copy);
500 ~CScriptToken() { clear(); }
501
502 int &Int() { ASSERT(LEX_TOKEN_DATA_SIMPLE(token)); return intData; }
503 std::string &String() { ASSERT(LEX_TOKEN_DATA_STRING(token)); return dynamic_cast<CScriptTokenDataString*>(tokenData)->tokenStr; }
504 double &Float() { ASSERT(LEX_TOKEN_DATA_FLOAT(token)); return *floatData; }
505 CScriptTokenDataFnc &Fnc() { ASSERT(LEX_TOKEN_DATA_FUNCTION(token)); return *dynamic_cast<CScriptTokenDataFnc*>(tokenData); }
506 const CScriptTokenDataFnc &Fnc() const { ASSERT(LEX_TOKEN_DATA_FUNCTION(token)); return *dynamic_cast<CScriptTokenDataFnc*>(tokenData); }
507 CScriptTokenDataObjectLiteral &Object() { ASSERT(LEX_TOKEN_DATA_OBJECT_LITERAL(token)); return *dynamic_cast<CScriptTokenDataObjectLiteral*>(tokenData); }
508 CScriptTokenDataDestructuringVar &DestructuringVar() { ASSERT(LEX_TOKEN_DATA_DESTRUCTURING_VAR(token)); return *dynamic_cast<CScriptTokenDataDestructuringVar*>(tokenData); }
509 CScriptTokenDataLoop &Loop() { ASSERT(LEX_TOKEN_DATA_LOOP(token)); return *dynamic_cast<CScriptTokenDataLoop*>(tokenData); }
510 CScriptTokenDataTry &Try() { ASSERT(LEX_TOKEN_DATA_TRY(token)); return *dynamic_cast<CScriptTokenDataTry*>(tokenData); }
511 CScriptTokenDataForwards &Forwarder() { ASSERT(LEX_TOKEN_DATA_FORWARDER(token)); return *dynamic_cast<CScriptTokenDataForwards*>(tokenData); }
512#ifdef _DEBUG
513 std::string token_str;
514#endif
515 uint16_t line;
516 uint16_t column;
517 uint16_t token;
518
519 static std::string getParsableString(TOKEN_VECT &Tokens, const std::string &IndentString="", const std::string &Indent="");
520 static std::string getParsableString(TOKEN_VECT_it Begin, TOKEN_VECT_it End, const std::string &IndentString="", const std::string &Indent="");
521 static std::string getTokenStr( int token, bool *need_space=0 );
522 static const char *isReservedWord(int Token);
523 static int isReservedWord(const std::string &Str);
524private:
525
526 void clear();
527 union {
528 int intData;
529 double *floatData;
530 CScriptTokenData *tokenData;
531 };
532};
533
534
535//////////////////////////////////////////////////////////////////////////
536/// CScriptTokenizer - converts the code in a vector with tokens
537//////////////////////////////////////////////////////////////////////////
538
539class CScriptTokenizer
540{
541public:
542 struct ScriptTokenPosition {
543 ScriptTokenPosition(TOKEN_VECT *Tokens) : tokens(Tokens), pos(tokens->begin())/*, currentLine(0)*//*, currentColumn(0)*/ {}
544 bool operator ==(const ScriptTokenPosition &eq) { return pos == eq.pos; }
545 ScriptTokenPosition &operator =(const ScriptTokenPosition &copy) {
546 tokens=copy.tokens; pos=copy.pos;
547// currentLine=copy.currentLine;
548 return *this;
549 }
550 TOKEN_VECT *tokens;
551 TOKEN_VECT_it pos;
552 int currentLine() { return pos->line; }
553 int currentColumn() { return pos->column; }
554 };
555 struct ScriptTokenState {
556 TOKEN_VECT Tokens;
557 FORWARDER_VECTOR_t Forwarders;
558 std::vector<int> Marks;
559 STRING_VECTOR_t Labels;
560 STRING_VECTOR_t LoopLabels;
561 bool LeftHand;
562 void pushLeftHandState() { States.push_back(LeftHand); }
563 void popLeftHandeState() { LeftHand = States.back(); States.pop_back(); }
564 std::vector<bool> States;
565 };
566 CScriptTokenizer();
567 CScriptTokenizer(CScriptLex &Lexer);
568 CScriptTokenizer(const char *Code, const std::string &File="", int Line=0, int Column=0);
569 void tokenizeCode(CScriptLex &Lexer);
570
571 CScriptToken &getToken() { return *(tokenScopeStack.back().pos); }
572 void getNextToken();
573 bool check(int ExpectedToken, int AlternateToken=-1);
574 void match(int ExpectedToken, int AlternateToken=-1);
575 void pushTokenScope(TOKEN_VECT &Tokens);
576 ScriptTokenPosition &getPos() { return tokenScopeStack.back(); }
577 void setPos(ScriptTokenPosition &TokenPos);
578 ScriptTokenPosition &getPrevPos() { return prevPos; }
579 void skip(int Tokens);
580 int tk; // current Token
581 std::string currentFile;
582 int currentLine() { return getPos().currentLine();}
583 int currentColumn() { return getPos().currentColumn();}
584 const std::string &tkStr() { static std::string empty; return LEX_TOKEN_DATA_STRING(getToken().token)?getToken().String():empty; }
585private:
586 void tokenizeTry(ScriptTokenState &State, int Flags);
587 void tokenizeSwitch(ScriptTokenState &State, int Flags);
588 void tokenizeWith(ScriptTokenState &State, int Flags);
589 void tokenizeWhileAndDo(ScriptTokenState &State, int Flags);
590 void tokenizeIf(ScriptTokenState &State, int Flags);
591 void tokenizeFor(ScriptTokenState &State, int Flags);
592 CScriptToken tokenizeVarIdentifier(STRING_VECTOR_t *VarNames=0, bool *NeedAssignment=0);
593 void tokenizeFunction(ScriptTokenState &State, int Flags, bool noLetDef=false);
594 void tokenizeLet(ScriptTokenState &State, int Flags, bool noLetDef=false);
595 void tokenizeVarNoConst(ScriptTokenState &State, int Flags);
596 void tokenizeVarAndConst(ScriptTokenState &State, int Flags);
597 void _tokenizeLiteralObject(ScriptTokenState &State, int Flags);
598 void _tokenizeLiteralArray(ScriptTokenState &State, int Flags);
599
600 void tokenizeLiteral(ScriptTokenState &State, int Flags);
601 void tokenizeMember(ScriptTokenState &State, int Flags);
602 void tokenizeFunctionCall(ScriptTokenState &State, int Flags);
603 void tokenizeSubExpression(ScriptTokenState &State, int Flags);
604 void tokenizeLogic(ScriptTokenState &State, int Flags, int op= LEX_OROR, int op_n=LEX_ANDAND);
605 void tokenizeCondition(ScriptTokenState &State, int Flags);
606 void tokenizeAssignment(ScriptTokenState &State, int Flags);
607 void tokenizeExpression(ScriptTokenState &State, int Flags);
608 void tokenizeBlock(ScriptTokenState &State, int Flags);
609 void tokenizeStatementNoLet(ScriptTokenState &State, int Flags);
610 void tokenizeStatement(ScriptTokenState &State, int Flags);
611
612 int pushToken(TOKEN_VECT &Tokens, int Match=-1, int Alternate=-1);
613 int pushToken(TOKEN_VECT &Tokens, const CScriptToken &Token);
614 void pushForwarder(ScriptTokenState &State, bool noMarks=false);
615 void removeEmptyForwarder(ScriptTokenState &State);
616 void pushForwarder(TOKEN_VECT &Tokens, FORWARDER_VECTOR_t &Forwarders, std::vector<int> &Marks);
617 void removeEmptyForwarder(TOKEN_VECT &Tokens, FORWARDER_VECTOR_t &Forwarders, std::vector<int> &Marks);
618 void throwTokenNotExpected();
619 CScriptLex *l;
620 TOKEN_VECT tokens;
621 ScriptTokenPosition prevPos;
622 std::vector<ScriptTokenPosition> tokenScopeStack;
623};
624
625
626//////////////////////////////////////////////////////////////////////////
627/// forward-declaration
628//////////////////////////////////////////////////////////////////////////
629
630class CNumber;
631class CScriptVar;
632class CScriptVarPtr;
633template<typename C> class CScriptVarPointer;
634class CScriptVarLink;
635class CScriptVarLinkPtr;
636class CScriptVarLinkWorkPtr;
637
638class CScriptVarPrimitive;
639typedef CScriptVarPointer<CScriptVarPrimitive> CScriptVarPrimitivePtr;
640
641class CScriptVarScopeFnc;
642typedef CScriptVarPointer<CScriptVarScopeFnc> CFunctionsScopePtr;
643typedef void (*JSCallback)(const CFunctionsScopePtr &var, void *userdata);
644
645class CTinyJS;
646class CScriptResult;
647
648//////////////////////////////////////////////////////////////////////////
649/// CScriptVar
650//////////////////////////////////////////////////////////////////////////
651
652typedef std::vector<class CScriptVarLinkPtr> SCRIPTVAR_CHILDS_t;
653typedef SCRIPTVAR_CHILDS_t::iterator SCRIPTVAR_CHILDS_it;
654typedef SCRIPTVAR_CHILDS_t::const_iterator SCRIPTVAR_CHILDS_cit;
655
656class CScriptVar : public fixed_size_object<CScriptVar> {
657protected:
658 CScriptVar(CTinyJS *Context, const CScriptVarPtr &Prototype); ///< Create
659 CScriptVar(const CScriptVar &Copy); ///< Copy protected -> use clone for public
660private:
661 CScriptVar & operator=(const CScriptVar &Copy) MEMBER_DELETE; ///< private -> no assignment-Copy
662public:
663 virtual ~CScriptVar();
664 virtual CScriptVarPtr clone()=0;
665
666 /// Type
667 virtual bool isObject(); ///< is an Object
668 virtual bool isArray(); ///< is an Array
669 virtual bool isError(); ///< is an ErrorObject
670 virtual bool isRegExp(); ///< is a RegExpObject
671 virtual bool isAccessor(); ///< is an Accessor
672 virtual bool isNull(); ///< is Null
673 virtual bool isUndefined();///< is Undefined
674 virtual bool isNaN(); ///< is NaN
675 virtual bool isString(); ///< is String
676 virtual bool isInt(); ///< is Integer
677 virtual bool isBool(); ///< is Bool
678 virtual int isInfinity(); ///< is Infinity ///< +1==POSITIVE_INFINITY, -1==NEGATIVE_INFINITY, 0==is not an InfinityVar
679 virtual bool isDouble(); ///< is Double
680
681 virtual bool isRealNumber(); ///< is isInt | isDouble
682 virtual bool isNumber(); ///< is isNaN | isInt | isDouble | isInfinity
683 virtual bool isPrimitive();///< isNull | isUndefined | isNaN | isString | isInt | isDouble | isInfinity
684
685 virtual bool isFunction(); ///< is CScriptVarFunction / CScriptVarFunctionNativeCallback / CScriptVarFunctionNativeClass
686 virtual bool isNative(); ///< is CScriptVarFunctionNativeCallback / CScriptVarFunctionNativeClass
687 virtual bool isBounded(); ///< is CScriptVarFunctionBounded
688
689 virtual bool isIterator();
690
691 bool isBasic() { return Childs.empty(); } ///< Is this *not* an array/object/etc
692
693
694 //////////////////////////////////////////////////////////////////////////
695 /// Value
696 //////////////////////////////////////////////////////////////////////////
697
698 virtual CScriptVarPrimitivePtr getRawPrimitive()=0; ///< is Var==Primitive -> return this isObject return Value
699 CScriptVarPrimitivePtr toPrimitive(); ///< by default call getDefaultValue_hintNumber by a Date-object calls getDefaultValue_hintString
700 virtual CScriptVarPrimitivePtr toPrimitive(CScriptResult &execute); ///< if the var an ObjectType gets the valueOf; if valueOf of an ObjectType gets toString / otherwise gets the Var itself
701 CScriptVarPrimitivePtr toPrimitive_hintString(int32_t radix=0); ///< if the var an ObjectType gets the valueOf; if valueOf of an ObjectType gets toString / otherwise gets the Var itself
702 CScriptVarPrimitivePtr toPrimitive_hintString(CScriptResult &execute, int32_t radix=0); ///< if the var an ObjectType gets the valueOf; if valueOf of an ObjectType gets toString / otherwise gets the Var itself
703 CScriptVarPrimitivePtr toPrimitive_hintNumber(); ///< if the var an ObjectType gets the valueOf; if valueOf of an ObjectType gets toString / otherwise gets the Var itself
704 CScriptVarPrimitivePtr toPrimitive_hintNumber(CScriptResult &execute); ///< if the var an ObjectType gets the valueOf; if valueOf of an ObjectType gets toString / otherwise gets the Var itself
705
706 CScriptVarPtr callJS_toString(CScriptResult &execute, int radix=0);
707 virtual CScriptVarPtr toString_CallBack(CScriptResult &execute, int radix=0);
708 CScriptVarPtr callJS_valueOf(CScriptResult &execute);
709 virtual CScriptVarPtr valueOf_CallBack();
710
711 CNumber toNumber();
712 CNumber toNumber(CScriptResult &execute);
713 virtual bool toBoolean();
714 std::string toString(int32_t radix=0); ///< shortcut for this->toPrimitive_hintString()->toCString();
715 std::string toString(CScriptResult &execute, int32_t radix=0); ///< shortcut for this->toPrimitive_hintString(execute)->toCString();
716#define WARN_DEPRECATED
717#ifdef WARN_DEPRECATED
718 int DEPRECATED("getInt() is deprecated use toNumber().toInt32 instead") getInt();
719 bool DEPRECATED("getBool() is deprecated use toBoolean() instead") getBool();
720 double DEPRECATED("getDouble() is deprecated use toNumber().toDouble() instead") getDouble();
721 std::string DEPRECATED("getString() is deprecated use toString() instead") getString();
722#else
723 int getInt();
724 bool getBool();
725 double getDouble();
726 std::string getString();
727#endif
728 virtual CScriptTokenDataFnc *getFunctionData(); ///< { return 0; }
729
730 virtual CScriptVarPtr toObject()=0;
731
732 CScriptVarPtr toIterator(int Mode=3);
733 CScriptVarPtr toIterator(CScriptResult &execute, int Mode=3);
734
735
736// virtual std::string getParsableString(const std::string &indentString, const std::string &indent, bool &hasRecursion); ///< get Data as a parsable javascript string
737#define getParsableStringRecursionsCheck() do{ \
738 if(uniqueID && uniqueID==temporaryID) { hasRecursion=true; return "recursion"; } \
739 temporaryID = uniqueID; \
740 } while(0)
741 virtual std::string getParsableString(const std::string &indentString, const std::string &indent, uint32_t uniqueID, bool &hasRecursion); ///< get Data as a parsable javascript string
742 virtual std::string getVarType()=0;
743
744#ifdef WARN_DEPRECATED
745 CScriptVarPtr DEPRECATED("getNumericVar() is deprecated use toNumber() instead") getNumericVar(); ///< returns an Integer, a Double, an Infinity or a NaN
746#else
747 CScriptVarPtr getNumericVar(); ///< returns an Integer, a Double, an Infinity or a NaN
748#endif
749
750 //////////////////////////////////////////////////////////////////////////
751 /// Childs
752 //////////////////////////////////////////////////////////////////////////
753
754
755 CScriptVarPtr getOwnPropertyDescriptor(const std::string &Name);
756 const char *defineProperty(const std::string &Name, CScriptVarPtr Attributes);
757
758 /// flags
759 void setExtensible(bool On=true) { extensible=On; }
760 void preventExtensions() { extensible=false; }
761 bool isExtensible() const { return extensible; }
762 void seal();
763 bool isSealed() const;
764 void freeze();
765 bool isFrozen() const;
766
767 /// find
768 CScriptVarLinkPtr findChild(const std::string &childName); ///< Tries to find a child with the given name, may return 0
769 CScriptVarLinkWorkPtr findChildWithStringChars(const std::string &childName);
770 CScriptVarLinkPtr findChildInPrototypeChain(const std::string &childName);
771 CScriptVarLinkWorkPtr findChildWithPrototypeChain(const std::string &childName);
772 CScriptVarLinkPtr findChildByPath(const std::string &path); ///< Tries to find a child with the given path (separated by dots)
773 CScriptVarLinkPtr findChildOrCreate(const std::string &childName/*, int varFlags=SCRIPTVAR_UNDEFINED*/); ///< Tries to find a child with the given name, or will create it with the given flags
774 CScriptVarLinkPtr findChildOrCreateByPath(const std::string &path); ///< Tries to find a child with the given path (separated by dots)
775 void keys(STRING_SET_t &Keys, bool OnlyEnumerable=true, uint32_t ID=0);
776 /// add & remove
777 CScriptVarLinkPtr addChild(const std::string &childName, const CScriptVarPtr &child, int linkFlags = SCRIPTVARLINK_DEFAULT);
778 CScriptVarLinkPtr DEPRECATED("addChildNoDup is deprecated use addChildOrReplace instead!") addChildNoDup(const std::string &childName, const CScriptVarPtr &child, int linkFlags = SCRIPTVARLINK_DEFAULT);
779 CScriptVarLinkPtr addChildOrReplace(const std::string &childName, const CScriptVarPtr &child, int linkFlags = SCRIPTVARLINK_DEFAULT); ///< add a child overwriting any with the same name
780 bool removeLink(CScriptVarLinkPtr &link); ///< Remove a specific link (this is faster than finding via a child)
781 void removeAllChildren();
782
783 /// ARRAY
784 CScriptVarPtr getArrayIndex(uint32_t idx); ///< The the value at an array index
785 void setArrayIndex(uint32_t idx, const CScriptVarPtr &value); ///< Set the value at an array index
786 uint32_t getArrayLength(); ///< If this is an array, return the number of items in it (else 0)
787
788 //////////////////////////////////////////////////////////////////////////
789 int getChildren() { return Childs.size(); } ///< Get the number of children
790 CTinyJS *getContext() { return context; }
791 CScriptVarPtr mathsOp(const CScriptVarPtr &b, int op); ///< do a maths op with another script variable
792
793 void trace(const std::string &name = ""); ///< Dump out the contents of this using trace
794 void trace(std::string &indentStr, uint32_t uniqueID, const std::string &name = ""); ///< Dump out the contents of this using trace
795 std::string getFlagsAsString(); ///< For debugging - just dump a string version of the flags
796// void getJSON(std::ostringstream &destination, const std::string linePrefix=""); ///< Write out all the JS code needed to recreate this script variable to the stream (as JSON)
797
798 SCRIPTVAR_CHILDS_t Childs;
799
800 /// For memory management/garbage collection
801private:
802 CScriptVar *ref(); ///< Add reference to this variable
803 void unref(); ///< Remove a reference, and delete this variable if required
804public:
805 int getRefs(); ///< Get the number of references to this script variable
806 template<class T>
807 operator T *(){ T *ret = dynamic_cast<T*>(this); ASSERT(ret!=0); return ret; }
808 template<class T>
809 T *get(){ T *ret = dynamic_cast<T*>(this); ASSERT(ret!=0); return ret; }
810
811 //CScriptVarPtr newScriptVar(const CNumber &t); // { return ::newScriptVar(context, t); }
812 template<typename T> CScriptVarPtr newScriptVar(T t); // { return ::newScriptVar(context, t); }
813 template<typename T1, typename T2> CScriptVarPtr newScriptVar(T1 t1, T2 t2); // { return ::newScriptVar(context, t); }
814 template<typename T> const CScriptVarPtr &constScriptVar(T t); // { return ::newScriptVar(context, t); }
815 void setTemporaryID(uint32_t ID) { temporaryID = ID; }
816 virtual void setTemporaryID_recursive(uint32_t ID);
817 uint32_t getTempraryID() { return temporaryID; }
818protected:
819 bool extensible;
820 CTinyJS *context;
821 int refs; ///< The number of references held to this - used for garbage collection
822 CScriptVar *prev;
823public:
824 CScriptVar *next;
825 uint32_t temporaryID;
826
827 friend class CScriptVarPtr;
828};
829
830
831//////////////////////////////////////////////////////////////////////////
832/// CScriptVarPtr
833//////////////////////////////////////////////////////////////////////////
834
835class CScriptVarPtr {
836public:
837 // construct
838 CScriptVarPtr() : var(0) {} ///< 0-Pointer
839 CScriptVarPtr(CScriptVar *Var) : var(Var) { if(var) var->ref(); } // creates a new CScriptVar (from new);
840
841 // copy
842 CScriptVarPtr(const CScriptVarPtr &Copy) : var(Copy.var) { if(var) var->ref(); }
843 CScriptVarPtr& operator=(const CScriptVarPtr &Copy) {
844 if(var != Copy.var) {
845 if(var) var->unref();
846 var = Copy.var; if(var) var->ref();
847 }
848 return *this;
849 }
850 // deconstruct
851 ~CScriptVarPtr() { if(var) var->unref(); }
852
853 // if
854 operator bool() const { return var!=0; }
855
856 bool operator ==(const CScriptVarPtr &Other) const { return var == Other.var; }
857 bool operator !=(const CScriptVarPtr &Other) const { return var != Other.var; }
858
859 // access
860 CScriptVar * operator ->() const { return var; }
861 CScriptVar *getVar() const { return var; }
862
863 void clear() { if(var) var->unref(); var=0; }
864protected:
865 CScriptVar *var;
866};
867
868//////////////////////////////////////////////////////////////////////////
869/// CScriptVarPointer - template
870//////////////////////////////////////////////////////////////////////////
871
872template<typename C>
873class CScriptVarPointer : public CScriptVarPtr {
874public:
875 CScriptVarPointer() {}
876 CScriptVarPointer(CScriptVar *Var) : CScriptVarPtr(dynamic_cast<C*>(Var)) {}
877 CScriptVarPointer(const CScriptVarPtr &Copy) : CScriptVarPtr(dynamic_cast<C*>(Copy.getVar())) {}
878 CScriptVarPointer<C> &operator=(const CScriptVarPtr &Copy) { CScriptVarPtr::operator=(dynamic_cast<C*>(Copy.getVar())); return *this; }
879 C * operator ->() const { C *Var = dynamic_cast<C*>(var); ASSERT(var && Var); return Var; }
880};
881
882
883//////////////////////////////////////////////////////////////////////////
884/// CScriptVarLink
885//////////////////////////////////////////////////////////////////////////
886class CScriptVarLink : public fixed_size_object<CScriptVarLink>
887{
888private: // prevent gloabal creating
889 CScriptVarLink(const CScriptVarPtr &var, const std::string &name = TINYJS_TEMP_NAME, int flags = SCRIPTVARLINK_DEFAULT);
890private: // prevent Copy
891 CScriptVarLink(const CScriptVarLink &link) MEMBER_DELETE; ///< Copy constructor
892public:
893 ~CScriptVarLink();
894
895 const std::string &getName() const { return name; }
896
897 int getFlags() { return flags; }
898 const CScriptVarPtr &getVarPtr() const { return var; }
899 const CScriptVarPtr &setVarPtr(const CScriptVarPtr &Var) { return var = Var; } ///< simple Replace the Variable pointed to
900
901
902 bool isOwned() const { return owner!=0; }
903
904 bool isWritable() const { return (flags & SCRIPTVARLINK_WRITABLE) != 0; }
905 void setWritable(bool On) { On ? (flags |= SCRIPTVARLINK_WRITABLE) : (flags &= ~SCRIPTVARLINK_WRITABLE); }
906 bool isConfigurable() const { return (flags & SCRIPTVARLINK_CONFIGURABLE) != 0; }
907 void setConfigurable(bool On) { On ? (flags |= SCRIPTVARLINK_CONFIGURABLE) : (flags &= ~SCRIPTVARLINK_CONFIGURABLE); }
908 bool isEnumerable() const { return (flags & SCRIPTVARLINK_ENUMERABLE) != 0; }
909 void setEnumerable(bool On) { On ? (flags |= SCRIPTVARLINK_ENUMERABLE) : (flags &= ~SCRIPTVARLINK_ENUMERABLE); }
910
911 CScriptVar *getOwner() { return owner; };
912 void setOwner(CScriptVar *Owner) { owner = Owner; }
913
914 /// forward to ScriptVar
915
916 CScriptVarPrimitivePtr toPrimitive() { ///< by default call getDefaultValue_hintNumber by a Date-object calls getDefaultValue_hintString
917 return var->toPrimitive(); }
918 CScriptVarPrimitivePtr toPrimitive(CScriptResult &execute) { ///< if the var an ObjectType gets the valueOf; if valueOf of an ObjectType gets toString / otherwise gets the Var itself
919 return var->toPrimitive(execute); }
920 CScriptVarPrimitivePtr toPrimitive_hintString(int32_t radix=0) { ///< if the var an ObjectType gets the valueOf; if valueOf of an ObjectType gets toString / otherwise gets the Var itself
921 return var->toPrimitive_hintString(radix); }
922 CScriptVarPrimitivePtr toPrimitive_hintString(CScriptResult &execute, int32_t radix=0) { ///< if the var an ObjectType gets the valueOf; if valueOf of an ObjectType gets toString / otherwise gets the Var itself
923 return var->toPrimitive_hintString(execute, radix); }
924 CScriptVarPrimitivePtr toPrimitive_hintNumber() { ///< if the var an ObjectType gets the valueOf; if valueOf of an ObjectType gets toString / otherwise gets the Var itself
925 return var->toPrimitive_hintNumber(); }
926 CScriptVarPrimitivePtr toPrimitive_hintNumber(CScriptResult &execute) { ///< if the var an ObjectType gets the valueOf; if valueOf of an ObjectType gets toString / otherwise gets the Var itself
927 return var->toPrimitive_hintNumber(execute); }
928
929 CNumber toNumber(); // { return var->toNumber(); }
930 CNumber toNumber(CScriptResult &execute); // { return var->toNumber(execute); }
931 bool toBoolean() { return var->toBoolean(); }
932 std::string toString(int32_t radix=0) { ///< shortcut for this->toPrimitive_hintString()->toCString();
933 return var->toString(radix); }
934 std::string toString(CScriptResult &execute, int32_t radix=0) { ///< shortcut for this->toPrimitive_hintString(execute)->toCString();
935 return var->toString(execute, radix); }
936 CScriptVarPtr toObject() { return var->toObject(); };
937
938private:
939 std::string name;
940 CScriptVar *owner; // pointer to the owner CScriptVar
941 uint32_t flags;
942 CScriptVarPtr var;
943#ifdef _DEBUG
944 char dummy[24];
945#endif
946 CScriptVarLink *ref();
947 void unref();
948private:
949 int refs;
950 friend class CScriptVarLinkPtr;
951};
952
953
954//////////////////////////////////////////////////////////////////////////
955/// CScriptVarLinkPtr
956//////////////////////////////////////////////////////////////////////////
957
958class CScriptVarLinkPtr {
959public:
960 // construct
961 CScriptVarLinkPtr() : link(0) {} ///< 0-Pointer
962 CScriptVarLinkPtr(const CScriptVarPtr &var, const std::string &name = TINYJS_TEMP_NAME, int flags = SCRIPTVARLINK_DEFAULT) { link=(new CScriptVarLink(var, name, flags))->ref(); }
963 CScriptVarLinkPtr(CScriptVarLink *Link) : link(Link) { if(link) link->ref(); } // creates a new CScriptVarLink (from new);
964
965 // reconstruct
966 CScriptVarLinkPtr &operator()(const CScriptVarPtr &var, const std::string &name = TINYJS_TEMP_NAME, int flags = SCRIPTVARLINK_DEFAULT);
967 CScriptVarLinkPtr &operator=(const CScriptVarPtr &var) { return operator()(var); }
968 // deconstruct
969 ~CScriptVarLinkPtr() { if(link) link->unref(); }
970
971 // copy
972 CScriptVarLinkPtr(const CScriptVarLinkPtr &Copy) : link(Copy.link) { if(link) link->ref(); }
973 CScriptVarLinkPtr &operator=(const CScriptVarLinkPtr &Copy) {
974 if(link != Copy.link) {
975 if(link) link->unref();
976 link = Copy.link; if(link) link->ref();
977 }
978 return *this;
979 }
980
981 // getter & setter
982 CScriptVarLinkWorkPtr getter();
983 CScriptVarLinkWorkPtr getter(CScriptResult &execute);
984 CScriptVarLinkWorkPtr setter(const CScriptVarPtr &Var);
985 CScriptVarLinkWorkPtr setter(CScriptResult &execute, const CScriptVarPtr &Var);
986
987 // if
988 operator bool() const { return link!=0; }
989
990 // for sorting in child-list
991 bool operator <(const std::string &rhs) const;
992 bool operator ==(const CScriptVarLinkPtr &rhs) const { return link==rhs.link; }
993 // access to CScriptVarLink
994 CScriptVarLink *operator ->() const { return link; }
995
996 operator const CScriptVarPtr &() const { static CScriptVarPtr NullPtr; return link?link->getVarPtr():NullPtr; }
997
998 void clear() { if(link) link->unref(); link=0; }
999protected:
1000 CScriptVarLink *link;
1001};
1002
1003
1004//////////////////////////////////////////////////////////////////////////
1005/// CScriptVarLinkWorkPtr
1006//////////////////////////////////////////////////////////////////////////
1007
1008class CScriptVarLinkWorkPtr : public CScriptVarLinkPtr {
1009public:
1010 // construct
1011 CScriptVarLinkWorkPtr() {}
1012 CScriptVarLinkWorkPtr(const CScriptVarPtr &var, const std::string &name = TINYJS_TEMP_NAME, int flags = SCRIPTVARLINK_DEFAULT) : CScriptVarLinkPtr(var, name, flags) {}
1013 CScriptVarLinkWorkPtr(CScriptVarLink *Link) : CScriptVarLinkPtr(Link) { if(link) referencedOwner = link->getOwner(); } // creates a new CScriptVarLink (from new);
1014 CScriptVarLinkWorkPtr(const CScriptVarLinkPtr &Copy) : CScriptVarLinkPtr(Copy) { if(link) referencedOwner = link->getOwner(); }
1015
1016 // reconstruct
1017 CScriptVarLinkWorkPtr &operator()(const CScriptVarPtr &var, const std::string &name = TINYJS_TEMP_NAME, int flags = SCRIPTVARLINK_DEFAULT) {CScriptVarLinkPtr::operator()(var, name, flags); referencedOwner.clear(); return *this; }
1018
1019 // copy
1020 CScriptVarLinkWorkPtr(const CScriptVarLinkWorkPtr &Copy) : CScriptVarLinkPtr(Copy), referencedOwner(Copy.referencedOwner) {}
1021 CScriptVarLinkWorkPtr &operator=(const CScriptVarLinkWorkPtr &Copy) { CScriptVarLinkPtr::operator=(Copy); referencedOwner = Copy.referencedOwner; return *this; }
1022
1023 // getter & setter
1024 CScriptVarLinkWorkPtr getter();
1025 CScriptVarLinkWorkPtr getter(CScriptResult &execute);
1026 CScriptVarLinkWorkPtr setter(const CScriptVarPtr &Var);
1027 CScriptVarLinkWorkPtr setter(CScriptResult &execute, const CScriptVarPtr &Var);
1028
1029
1030 void swap(CScriptVarLinkWorkPtr &Link) {
1031 CScriptVarPtr _referencedOwner = referencedOwner; referencedOwner = Link.referencedOwner; Link.referencedOwner = _referencedOwner;
1032 CScriptVarLink *_link=link; link=Link.link; Link.link=_link;
1033 }
1034
1035 void clear() { CScriptVarLinkPtr::clear(); referencedOwner.clear(); }
1036 void setReferencedOwner(const CScriptVarPtr &Owner) { referencedOwner = Owner; }
1037 const CScriptVarPtr &getReferencedOwner() const { return referencedOwner; }
1038 bool hasReferencedOwner() const { return referencedOwner; }
1039private:
1040 CScriptVarPtr referencedOwner;
1041};
1042
1043
1044//////////////////////////////////////////////////////////////////////////
1045#define define_dummy_t(t1) struct t1##_t{}; extern t1##_t t1
1046#define declare_dummy_t(t1) t1##_t t1
1047#define define_newScriptVar_Fnc(t1, ...) CScriptVarPtr newScriptVar(__VA_ARGS__)
1048#define define_newScriptVar_NamedFnc(t1, ...) CScriptVarPtr newScriptVar##t1(__VA_ARGS__)
1049#define define_ScriptVarPtr_Type(t1) class CScriptVar##t1; typedef CScriptVarPointer<CScriptVar##t1> CScriptVar##t1##Ptr
1050
1051#define define_DEPRECATED_newScriptVar_Fnc(t1, ...) CScriptVarPtr DEPRECATED("newScriptVar("#__VA_ARGS__") is deprecated use constScriptVar("#__VA_ARGS__") instead") newScriptVar(__VA_ARGS__)
1052
1053
1054//////////////////////////////////////////////////////////////////////////
1055/// CScriptVarPrimitive
1056//////////////////////////////////////////////////////////////////////////
1057
1058define_ScriptVarPtr_Type(Primitive);
1059class CScriptVarPrimitive : public CScriptVar {
1060protected:
1061 CScriptVarPrimitive(CTinyJS *Context, const CScriptVarPtr &Prototype) : CScriptVar(Context, Prototype) { setExtensible(false); }
1062 CScriptVarPrimitive(const CScriptVarPrimitive &Copy) : CScriptVar(Copy) { } ///< Copy protected -> use clone for public
1063public:
1064 virtual ~CScriptVarPrimitive();
1065
1066 virtual bool isPrimitive(); ///< return true;
1067
1068 virtual CScriptVarPrimitivePtr getRawPrimitive();
1069 virtual bool toBoolean(); /// false by default
1070 virtual CNumber toNumber_Callback()=0;
1071 virtual std::string toCString(int radix=0)=0;
1072
1073 virtual CScriptVarPtr toObject();
1074 virtual CScriptVarPtr toString_CallBack(CScriptResult &execute, int radix=0);
1075protected:
1076};
1077
1078
1079//////////////////////////////////////////////////////////////////////////
1080/// CScriptVarUndefined
1081//////////////////////////////////////////////////////////////////////////
1082
1083define_dummy_t(Undefined);
1084define_ScriptVarPtr_Type(Undefined);
1085class CScriptVarUndefined : public CScriptVarPrimitive {
1086protected:
1087 CScriptVarUndefined(CTinyJS *Context);
1088 CScriptVarUndefined(const CScriptVarUndefined &Copy) : CScriptVarPrimitive(Copy) {} ///< Copy protected -> use clone for public
1089public:
1090 virtual ~CScriptVarUndefined();
1091 virtual CScriptVarPtr clone();
1092
1093 virtual bool isUndefined(); // { return true; }
1094
1095 virtual CNumber toNumber_Callback(); // { return NaN; }
1096 virtual std::string toCString(int radix=0);// { return "undefined"; }
1097
1098 virtual std::string getVarType(); // { return "undefined"; }
1099 friend define_DEPRECATED_newScriptVar_Fnc(Undefined, CTinyJS *, Undefined_t);
1100 friend define_newScriptVar_NamedFnc(Undefined, CTinyJS *Context);
1101};
1102inline define_DEPRECATED_newScriptVar_Fnc(Undefined, CTinyJS *Context, Undefined_t) { return new CScriptVarUndefined(Context); }
1103inline define_newScriptVar_NamedFnc(Undefined, CTinyJS *Context) { return new CScriptVarUndefined(Context); }
1104
1105
1106//////////////////////////////////////////////////////////////////////////
1107/// CScriptVarNull
1108//////////////////////////////////////////////////////////////////////////
1109
1110define_dummy_t(Null);
1111define_ScriptVarPtr_Type(Null);
1112class CScriptVarNull : public CScriptVarPrimitive {
1113protected:
1114 CScriptVarNull(CTinyJS *Context);
1115 CScriptVarNull(const CScriptVarNull &Copy) : CScriptVarPrimitive(Copy) {} ///< Copy protected -> use clone for public
1116public:
1117 virtual ~CScriptVarNull();
1118 virtual CScriptVarPtr clone();
1119
1120 virtual bool isNull(); // { return true; }
1121
1122 virtual CNumber toNumber_Callback(); // { return 0; }
1123 virtual std::string toCString(int radix=0);// { return "null"; }
1124
1125 virtual std::string getVarType(); // { return "null"; }
1126
1127 friend define_DEPRECATED_newScriptVar_Fnc(Null, CTinyJS *Context, Null_t);
1128 friend define_newScriptVar_NamedFnc(Null, CTinyJS *Context);
1129};
1130inline define_DEPRECATED_newScriptVar_Fnc(Null, CTinyJS *Context, Null_t) { return new CScriptVarNull(Context); }
1131inline define_newScriptVar_NamedFnc(Null, CTinyJS *Context) { return new CScriptVarNull(Context); }
1132
1133
1134//////////////////////////////////////////////////////////////////////////
1135/// CScriptVarString
1136//////////////////////////////////////////////////////////////////////////
1137
1138define_ScriptVarPtr_Type(String);
1139class CScriptVarString : public CScriptVarPrimitive {
1140protected:
1141 CScriptVarString(CTinyJS *Context, const std::string &Data);
1142 CScriptVarString(const CScriptVarString &Copy) : CScriptVarPrimitive(Copy), data(Copy.data) {} ///< Copy protected -> use clone for public
1143public:
1144 virtual ~CScriptVarString();
1145 virtual CScriptVarPtr clone();
1146 virtual bool isString(); // { return true; }
1147
1148 virtual bool toBoolean();
1149 virtual CNumber toNumber_Callback();
1150 virtual std::string toCString(int radix=0);
1151
1152 virtual std::string getParsableString(const std::string &indentString, const std::string &indent, uint32_t uniqueID, bool &hasRecursion); // { return getJSString(data); }
1153 virtual std::string getVarType(); // { return "string"; }
1154
1155 virtual CScriptVarPtr toObject();
1156 virtual CScriptVarPtr toString_CallBack(CScriptResult &execute, int radix=0);
1157
1158 uint32_t stringLength() { return data.size(); }
1159 int getChar(uint32_t Idx);
1160protected:
1161 std::string data;
1162private:
1163 friend define_newScriptVar_Fnc(String, CTinyJS *Context, const std::string &);
1164 friend define_newScriptVar_Fnc(String, CTinyJS *Context, const char *);
1165 friend define_newScriptVar_Fnc(String, CTinyJS *Context, char *);
1166};
1167inline define_newScriptVar_Fnc(String, CTinyJS *Context, const std::string &Obj) { return new CScriptVarString(Context, Obj); }
1168inline define_newScriptVar_Fnc(String, CTinyJS *Context, const char *Obj) { return new CScriptVarString(Context, Obj); }
1169inline define_newScriptVar_Fnc(String, CTinyJS *Context, char *Obj) { return new CScriptVarString(Context, Obj); }
1170
1171
1172//////////////////////////////////////////////////////////////////////////
1173/// CNumber
1174//////////////////////////////////////////////////////////////////////////
1175define_dummy_t(NegativeZero);
1176define_dummy_t(NaN);
1177class Infinity{public:Infinity(int Sig=1):sig(Sig){} int Sig(){return sig;} private:int sig; } ;
1178extern Infinity InfinityPositive;
1179extern Infinity InfinityNegative;
1180
1181class CNumber {
1182private:
1183 enum NType {
1184 tnNULL, tInt32, tDouble, tNaN, tInfinity
1185 };
1186 CNumber(NType Type, int32_t InfinitySign=0) : type(Type) { Int32 = InfinitySign; }
1187public:
1188
1189 CNumber(const CNumber &Copy) { *this=Copy; }
1190
1191 CNumber(int32_t Value=0) : type(tInt32) { Int32=Value; }
1192#if 1
1193 template<typename T>CNumber(T Value) { *this = Value; }
1194#else
1195 CNumber(negativeZero_t Value) { *this = Value; }
1196 CNumber(NaN_t Value) { *this = Value; }
1197 CNumber(Infinity Value) { *this = Value; }
1198 CNumber(uint32_t Value) { *this = Value; }
1199 CNumber(double Value) { *this = Value; }
1200 CNumber(unsigned char Value) { *this = Value; }
1201 CNumber(const char *Value) { *this = Value; }
1202 CNumber(const std::string &Value) { *this = Value; }
1203#endif
1204 CNumber &operator=(NegativeZero_t) { type=tnNULL; Int32=0; return *this; }
1205 CNumber &operator=(NaN_t) { type=tNaN; Int32=0; return *this; }
1206 CNumber &operator=(Infinity v) { type=tInfinity; Int32=v.Sig(); return *this; }
1207 CNumber &operator=(int32_t Value) { type=tInt32; Int32=Value; return *this; }
1208 CNumber &operator=(uint32_t Value) {
1209 if(Value<=(uint32_t)std::numeric_limits<int32_t>::max())
1210 type=tInt32, Int32=int32_t(Value);
1211 else
1212 type=tDouble, Double=Value;
1213 return *this;
1214 }
1215 CNumber &operator=(double Value);
1216 CNumber &operator=(unsigned char Value) { type=tInt32; Int32=Value; return *this; }
1217 CNumber &operator=(const char *Value);
1218 CNumber &operator=(const std::string &Value) { return operator=(Value.c_str());}
1219
1220 int32_t parseInt(const char *str, int32_t radix=0, const char **endptr=0);
1221 void parseInt(const std::string &str, int32_t radix=0) { parseInt(str.c_str(), radix); }
1222 void parseFloat(const char *str, const char **endptr=0);
1223 void parseFloat(const std::string &str) { parseFloat(str.c_str()); }
1224
1225 CNumber add(const CNumber &Value) const;
1226 CNumber operator-() const;
1227 CNumber operator~() const { if(type==tNaN) return *this; else return ~toInt32(); }
1228 bool operator!() const { return isZero(); }
1229 CNumber multi(const CNumber &Value) const;
1230 CNumber div(const CNumber &Value) const;
1231 CNumber modulo(const CNumber &Value) const;
1232
1233 CNumber round() const;
1234 CNumber floor() const;
1235 CNumber ceil() const;
1236 CNumber abs() const;
1237
1238 CNumber shift(const CNumber &Value, bool right) const;
1239 CNumber ushift(const CNumber &Value, bool right=true) const;
1240
1241 CNumber binary(const CNumber &Value, char Mode) const;
1242
1243
1244 int less(const CNumber &Value) const;
1245 bool equal(const CNumber &Value) const;
1246
1247
1248 bool isInt32() const { return type == tInt32; }
1249 bool isDouble() const { return type == tDouble; }
1250
1251 bool isNaN() const { return type == tNaN; }
1252 int isInfinity() const { return type == tInfinity ? Int32 : 0; }
1253 bool isFinite() const { return type == tInt32 || type == tDouble || type == tnNULL; }
1254 bool isNegativeZero() const { return type==tnNULL; }
1255 bool isZero() const; ///< is 0, -0
1256 bool isInteger() const;
1257 int sign() const;
1258
1259 int32_t toInt32() const { return cast<int32_t>(); }
1260 uint32_t toUInt32() const { return cast<uint32_t>(); }
1261 double toDouble() const;
1262 bool toBoolean() const { return !isZero() && type!=tNaN; }
1263 std::string toString(uint32_t Radix=10) const;
1264private:
1265 template<typename T> T cast() const {
1266 switch(type) {
1267 case tInt32:
1268 return T(Int32);
1269 case tDouble:
1270 return T(Double);
1271 default:
1272 return T(0);
1273 }
1274 }
1275 NType type;
1276 union {
1277 int32_t Int32;
1278 double Double;
1279 };
1280};
1281inline CNumber operator+(const CNumber &lhs, const CNumber &rhs) { return lhs.add(rhs); }
1282inline CNumber &operator+=(CNumber &lhs, const CNumber &rhs) { return lhs=lhs.add(rhs); }
1283inline CNumber operator-(const CNumber &lhs, const CNumber &rhs) { return lhs.add(-rhs); }
1284inline CNumber &operator-=(CNumber &lhs, const CNumber &rhs) { return lhs=lhs.add(-rhs); }
1285inline CNumber operator*(const CNumber &lhs, const CNumber &rhs) { return lhs.multi(rhs); }
1286inline CNumber &operator*=(CNumber &lhs, const CNumber &rhs) { return lhs=lhs.multi(rhs); }
1287inline CNumber operator/(const CNumber &lhs, const CNumber &rhs) { return lhs.div(rhs); }
1288inline CNumber &operator/=(CNumber &lhs, const CNumber &rhs) { return lhs=lhs.div(rhs); }
1289inline CNumber operator%(const CNumber &lhs, const CNumber &rhs) { return lhs.modulo(rhs); }
1290inline CNumber &operator%=(CNumber &lhs, const CNumber &rhs) { return lhs=lhs.modulo(rhs); }
1291inline CNumber operator>>(const CNumber &lhs, const CNumber &rhs) { return lhs.shift(rhs, true); }
1292inline CNumber &operator>>=(CNumber &lhs, const CNumber &rhs) { return lhs=lhs.shift(rhs, true); }
1293inline CNumber operator<<(const CNumber &lhs, const CNumber &rhs) { return lhs.shift(rhs, false); }
1294inline CNumber &operator<<=(CNumber &lhs, const CNumber &rhs) { return lhs=lhs.shift(rhs, false); }
1295
1296inline bool operator==(const CNumber &lhs, const CNumber &rhs) { return lhs.equal(rhs); }
1297inline bool operator!=(const CNumber &lhs, const CNumber &rhs) { return !lhs.equal(rhs); }
1298inline bool operator<(const CNumber &lhs, const CNumber &rhs) { return lhs.less(rhs)>0; }
1299inline bool operator<=(const CNumber &lhs, const CNumber &rhs) { return rhs.less(lhs)<0; }
1300inline bool operator>(const CNumber &lhs, const CNumber &rhs) { return rhs.less(lhs)>0; }
1301inline bool operator>=(const CNumber &lhs, const CNumber &rhs) { return lhs.less(rhs)<0; }
1302
1303inline CNumber round(const CNumber &lhs) { return lhs.round(); }
1304inline CNumber floor(const CNumber &lhs) { return lhs.floor(); }
1305inline CNumber ceil(const CNumber &lhs) { return lhs.ceil(); }
1306inline CNumber abs(const CNumber &lhs) { return lhs.abs(); }
1307
1308//////////////////////////////////////////////////////////////////////////
1309/// CScriptVarNumber
1310//////////////////////////////////////////////////////////////////////////
1311
1312define_ScriptVarPtr_Type(Number);
1313class CScriptVarNumber : public CScriptVarPrimitive {
1314protected:
1315 CScriptVarNumber(CTinyJS *Context, const CNumber &Data);
1316 CScriptVarNumber(const CScriptVarNumber &Copy) : CScriptVarPrimitive(Copy), data(Copy.data) {} ///< Copy protected -> use clone for public
1317public:
1318 virtual ~CScriptVarNumber();
1319 virtual CScriptVarPtr clone();
1320 virtual bool isNumber(); // { return true; }
1321 virtual bool isInt(); // { return true; }
1322 virtual bool isDouble(); // { return true; }
1323 virtual bool isRealNumber(); // { return true; }
1324 virtual int isInfinity(); // { return data; }
1325 virtual bool isNaN();// { return true; }
1326
1327 virtual bool toBoolean();
1328 virtual CNumber toNumber_Callback();
1329 virtual std::string toCString(int radix=0);
1330
1331 virtual std::string getVarType(); // { return "number"; }
1332
1333 virtual CScriptVarPtr toObject();
1334private:
1335 CNumber data;
1336 friend define_newScriptVar_Fnc(Number, CTinyJS *Context, const CNumber &);
1337 friend define_newScriptVar_NamedFnc(Number, CTinyJS *Context, const CNumber &);
1338};
1339define_newScriptVar_Fnc(Number, CTinyJS *Context, const CNumber &Obj);
1340inline define_newScriptVar_NamedFnc(Number, CTinyJS *Context, const CNumber &Obj) { return new CScriptVarNumber(Context, Obj); }
1341inline define_newScriptVar_Fnc(Number, CTinyJS *Context, unsigned int Obj) { return newScriptVarNumber(Context, CNumber(Obj)); }
1342inline define_newScriptVar_Fnc(Number, CTinyJS *Context, int Obj) { return newScriptVarNumber(Context, CNumber(Obj)); }
1343inline define_newScriptVar_Fnc(Number, CTinyJS *Context, double Obj) { return newScriptVarNumber(Context, CNumber(Obj)); }
1344inline define_DEPRECATED_newScriptVar_Fnc(NaN, CTinyJS *Context, NaN_t) { return newScriptVarNumber(Context, CNumber(NaN)); }
1345inline define_DEPRECATED_newScriptVar_Fnc(Infinity, CTinyJS *Context, Infinity Obj) { return newScriptVarNumber(Context, CNumber(Obj)); }
1346
1347
1348//////////////////////////////////////////////////////////////////////////
1349/// CScriptVarBool
1350//////////////////////////////////////////////////////////////////////////
1351
1352define_ScriptVarPtr_Type(Bool);
1353class CScriptVarBool : public CScriptVarPrimitive {
1354protected:
1355 CScriptVarBool(CTinyJS *Context, bool Data);
1356 CScriptVarBool(const CScriptVarBool &Copy) : CScriptVarPrimitive(Copy), data(Copy.data) {} ///< Copy protected -> use clone for public
1357public:
1358 virtual ~CScriptVarBool();
1359 virtual CScriptVarPtr clone();
1360 virtual bool isBool(); // { return true; }
1361
1362 virtual bool toBoolean();
1363 virtual CNumber toNumber_Callback();
1364 virtual std::string toCString(int radix=0);
1365
1366 virtual std::string getVarType(); // { return "boolean"; }
1367
1368 virtual CScriptVarPtr toObject();
1369protected:
1370 bool data;
1371
1372 friend define_DEPRECATED_newScriptVar_Fnc(Bool, CTinyJS *, bool);
1373 friend define_newScriptVar_NamedFnc(Bool, CTinyJS *Context, bool);
1374};
1375inline define_DEPRECATED_newScriptVar_Fnc(Bool, CTinyJS *Context, bool Obj) { return new CScriptVarBool(Context, Obj); }
1376inline define_newScriptVar_NamedFnc(Bool, CTinyJS *Context, bool Obj) { return new CScriptVarBool(Context, Obj); }
1377
1378
1379//////////////////////////////////////////////////////////////////////////
1380/// CScriptVarObject
1381//////////////////////////////////////////////////////////////////////////
1382
1383define_dummy_t(StopIteration);
1384define_dummy_t(Object);
1385define_ScriptVarPtr_Type(Object);
1386
1387class CScriptVarObject : public CScriptVar {
1388protected:
1389 CScriptVarObject(CTinyJS *Context);
1390 CScriptVarObject(CTinyJS *Context, const CScriptVarPtr &Prototype) : CScriptVar(Context, Prototype) {}
1391 CScriptVarObject(CTinyJS *Context, const CScriptVarPrimitivePtr &Value, const CScriptVarPtr &Prototype) : CScriptVar(Context, Prototype), value(Value) {}
1392 CScriptVarObject(const CScriptVarObject &Copy) : CScriptVar(Copy) {} ///< Copy protected -> use clone for public
1393public:
1394 virtual ~CScriptVarObject();
1395 virtual CScriptVarPtr clone();
1396
1397 virtual CScriptVarPrimitivePtr getRawPrimitive();
1398 virtual bool isObject(); // { return true; }
1399
1400 virtual std::string getParsableString(const std::string &indentString, const std::string &indent, uint32_t uniqueID, bool &hasRecursion);
1401 virtual std::string getVarType(); ///< always "object"
1402 virtual CScriptVarPtr toObject();
1403
1404 virtual CScriptVarPtr valueOf_CallBack();
1405 virtual CScriptVarPtr toString_CallBack(CScriptResult &execute, int radix=0);
1406 virtual void setTemporaryID_recursive(uint32_t ID);
1407protected:
1408private:
1409 CScriptVarPrimitivePtr value;
1410 friend define_newScriptVar_Fnc(Object, CTinyJS *Context, Object_t);
1411 friend define_newScriptVar_Fnc(Object, CTinyJS *Context, Object_t, const CScriptVarPtr &);
1412 friend define_newScriptVar_Fnc(Object, CTinyJS *Context, const CScriptVarPtr &);
1413 friend define_newScriptVar_Fnc(Object, CTinyJS *Context, const CScriptVarPrimitivePtr &, const CScriptVarPtr &);
1414};
1415inline define_newScriptVar_Fnc(Object, CTinyJS *Context, Object_t) { return new CScriptVarObject(Context); }
1416inline define_newScriptVar_Fnc(Object, CTinyJS *Context, Object_t, const CScriptVarPtr &Prototype) { return new CScriptVarObject(Context, Prototype); }
1417inline define_newScriptVar_Fnc(Object, CTinyJS *Context, const CScriptVarPtr &Prototype) { return new CScriptVarObject(Context, Prototype); }
1418inline define_newScriptVar_Fnc(Object, CTinyJS *Context, const CScriptVarPrimitivePtr &Value, const CScriptVarPtr &Prototype) { return new CScriptVarObject(Context, Value, Prototype); }
1419
1420
1421//////////////////////////////////////////////////////////////////////////
1422/// CScriptVarError
1423//////////////////////////////////////////////////////////////////////////
1424
1425define_ScriptVarPtr_Type(Error);
1426
1427class CScriptVarError : public CScriptVarObject {
1428protected:
1429 CScriptVarError(CTinyJS *Context, ERROR_TYPES type, const char *message, const char *file, int line, int column);// : CScriptVarObject(Context), value(Value) {}
1430 CScriptVarError(const CScriptVarError &Copy) : CScriptVarObject(Copy) {} ///< Copy protected -> use clone for public
1431public:
1432 virtual ~CScriptVarError();
1433 virtual CScriptVarPtr clone();
1434 virtual bool isError(); // { return true; }
1435
1436// virtual std::string getParsableString(const std::string &indentString, const std::string &indent); ///< get Data as a parsable javascript string
1437
1438 virtual CScriptVarPtr toString_CallBack(CScriptResult &execute, int radix=0);
1439 CScriptException *toCScriptException();
1440private:
1441 friend define_newScriptVar_NamedFnc(Error, CTinyJS *Context, ERROR_TYPES type, const char *message, const char *file, int line, int column);
1442 friend define_newScriptVar_NamedFnc(Error, CTinyJS *Context, const CScriptException &Exception);
1443};
1444inline define_newScriptVar_NamedFnc(Error, CTinyJS *Context, ERROR_TYPES type, const char *message=0, const char *file=0, int line=-1, int column=-1) { return new CScriptVarError(Context, type, message, file, line, column); }
1445inline define_newScriptVar_NamedFnc(Error, CTinyJS *Context, const CScriptException &Exception) { return new CScriptVarError(Context, Exception.errorType, Exception.message.c_str(), Exception.fileName.c_str(), Exception.lineNumber, Exception.column); }
1446
1447//////////////////////////////////////////////////////////////////////////
1448/// CScriptVarArray
1449//////////////////////////////////////////////////////////////////////////
1450
1451define_dummy_t(Array);
1452define_ScriptVarPtr_Type(Array);
1453class CScriptVarArray : public CScriptVarObject {
1454protected:
1455 CScriptVarArray(CTinyJS *Context);
1456 CScriptVarArray(const CScriptVarArray &Copy) : CScriptVarObject(Copy) {} ///< Copy protected -> use clone for public
1457public:
1458 virtual ~CScriptVarArray();
1459 virtual CScriptVarPtr clone();
1460 virtual bool isArray(); // { return true; }
1461
1462 virtual std::string getParsableString(const std::string &indentString, const std::string &indent, uint32_t uniqueID, bool &hasRecursion);
1463
1464 virtual CScriptVarPtr toString_CallBack(CScriptResult &execute, int radix=0);
1465
1466 friend define_newScriptVar_Fnc(Array, CTinyJS *Context, Array_t);
1467private:
1468 void native_Length(const CFunctionsScopePtr &c, void *data);
1469};
1470inline define_newScriptVar_Fnc(Array, CTinyJS *Context, Array_t) { return new CScriptVarArray(Context); }
1471
1472
1473//////////////////////////////////////////////////////////////////////////
1474/// CScriptVarRegExp
1475//////////////////////////////////////////////////////////////////////////
1476#ifndef NO_REGEXP
1477
1478define_ScriptVarPtr_Type(RegExp);
1479class CScriptVarRegExp : public CScriptVarObject {
1480protected:
1481 CScriptVarRegExp(CTinyJS *Context, const std::string &Source, const std::string &Flags);
1482 CScriptVarRegExp(const CScriptVarRegExp &Copy) : CScriptVarObject(Copy), regexp(Copy.regexp), flags(Copy.flags) {} ///< Copy protected -> use clone for public
1483public:
1484 virtual ~CScriptVarRegExp();
1485 virtual CScriptVarPtr clone();
1486 virtual bool isRegExp(); // { return true; }
1487 virtual CScriptVarPtr toString_CallBack(CScriptResult &execute, int radix=0);
1488
1489 CScriptVarPtr exec(const std::string &Input, bool Test=false);
1490
1491 bool Global() { return flags.find('g')!=std::string::npos; }
1492 bool IgnoreCase() { return flags.find('i')!=std::string::npos; }
1493 bool Multiline() { return true; /* currently always true -- flags.find('m')!=std::string::npos;*/ }
1494 bool Sticky() { return flags.find('y')!=std::string::npos; }
1495 const std::string &Regexp() { return regexp; }
1496 unsigned int LastIndex();
1497 void LastIndex(unsigned int Idx);
1498
1499 static const char *ErrorStr(int Error);
1500protected:
1501 std::string regexp;
1502 std::string flags;
1503private:
1504 void native_Global(const CFunctionsScopePtr &c, void *data);
1505 void native_IgnoreCase(const CFunctionsScopePtr &c, void *data);
1506 void native_Multiline(const CFunctionsScopePtr &c, void *data);
1507 void native_Sticky(const CFunctionsScopePtr &c, void *data);
1508 void native_Source(const CFunctionsScopePtr &c, void *data);
1509
1510 friend define_newScriptVar_Fnc(RegExp, CTinyJS *Context, const std::string &, const std::string &);
1511
1512};
1513inline define_newScriptVar_Fnc(RegExp, CTinyJS *Context, const std::string &Obj, const std::string &Flags) { return new CScriptVarRegExp(Context, Obj, Flags); }
1514
1515#endif /* NO_REGEXP */
1516
1517
1518//////////////////////////////////////////////////////////////////////////
1519/// CScriptVarDefaultIterator
1520//////////////////////////////////////////////////////////////////////////
1521
1522define_dummy_t(DefaultIterator);
1523define_ScriptVarPtr_Type(DefaultIterator);
1524
1525class CScriptVarDefaultIterator : public CScriptVarObject {
1526protected:
1527 CScriptVarDefaultIterator(CTinyJS *Context, const CScriptVarPtr &Object, int Mode);
1528 CScriptVarDefaultIterator(const CScriptVarDefaultIterator &Copy)
1529 :
1530 CScriptVarObject(Copy), mode(Copy.mode), object(Copy.object),
1531 keys(Copy.keys), pos(keys.begin()){} ///< Copy protected -> use clone for public
1532public:
1533 virtual ~CScriptVarDefaultIterator();
1534 virtual CScriptVarPtr clone();
1535 virtual bool isIterator();
1536
1537 void native_next(const CFunctionsScopePtr &c, void *data);
1538private:
1539 int mode;
1540 CScriptVarPtr object;
1541 STRING_SET_t keys;
1542 STRING_SET_it pos;
1543 friend define_newScriptVar_NamedFnc(DefaultIterator, CTinyJS *, const CScriptVarPtr &, int);
1544
1545};
1546inline define_newScriptVar_NamedFnc(DefaultIterator, CTinyJS *Context, const CScriptVarPtr &Object, int Mode) { return new CScriptVarDefaultIterator(Context, Object, Mode); }
1547
1548
1549//////////////////////////////////////////////////////////////////////////
1550/// CScriptVarFunction
1551//////////////////////////////////////////////////////////////////////////
1552
1553define_ScriptVarPtr_Type(Function);
1554class CScriptVarFunction : public CScriptVarObject {
1555protected:
1556 CScriptVarFunction(CTinyJS *Context, CScriptTokenDataFnc *Data);
1557 CScriptVarFunction(const CScriptVarFunction &Copy) : CScriptVarObject(Copy), data(Copy.data) { data->ref(); } ///< Copy protected -> use clone for public
1558public:
1559 virtual ~CScriptVarFunction();
1560 virtual CScriptVarPtr clone();
1561 virtual bool isObject(); // { return true; }
1562 virtual bool isFunction(); // { return true; }
1563 virtual bool isPrimitive(); // { return false; }
1564
1565 virtual std::string getVarType(); // { return "function"; }
1566 virtual std::string getParsableString(const std::string &indentString, const std::string &indent, uint32_t uniqueID, bool &hasRecursion);
1567 virtual CScriptVarPtr toString_CallBack(CScriptResult &execute, int radix=0);
1568 virtual CScriptTokenDataFnc *getFunctionData();
1569 void setFunctionData(CScriptTokenDataFnc *Data);
1570private:
1571 CScriptTokenDataFnc *data;
1572
1573 friend define_newScriptVar_Fnc(Function, CTinyJS *Context, CScriptTokenDataFnc *);
1574};
1575inline define_newScriptVar_Fnc(Function, CTinyJS *Context, CScriptTokenDataFnc *Obj) { return new CScriptVarFunction(Context, Obj); }
1576
1577
1578//////////////////////////////////////////////////////////////////////////
1579/// CScriptVarFunctionBounded
1580//////////////////////////////////////////////////////////////////////////
1581
1582define_ScriptVarPtr_Type(FunctionBounded);
1583class CScriptVarFunctionBounded : public CScriptVarFunction {
1584protected:
1585 CScriptVarFunctionBounded(CScriptVarFunctionPtr BoundedFunction, CScriptVarPtr BoundedThis, const std::vector<CScriptVarPtr> &BoundedArguments);
1586 CScriptVarFunctionBounded(const CScriptVarFunctionBounded &Copy) : CScriptVarFunction(Copy), boundedThis(Copy.boundedThis), boundedArguments(Copy.boundedArguments) { } ///< Copy protected -> use clone for public
1587public:
1588 virtual ~CScriptVarFunctionBounded();
1589 virtual CScriptVarPtr clone();
1590 virtual bool isBounded(); ///< is CScriptVarFunctionBounded
1591 virtual void setTemporaryID_recursive(uint32_t ID);
1592 CScriptVarPtr callFunction(CScriptResult &execute, std::vector<CScriptVarPtr> &Arguments, const CScriptVarPtr &This, CScriptVarPtr *newThis=0);
1593protected:
1594private:
1595 CScriptVarFunctionPtr boundedFunction;
1596 CScriptVarPtr boundedThis;
1597 std::vector<CScriptVarPtr> boundedArguments;
1598
1599 friend define_newScriptVar_NamedFnc(FunctionBounded, CScriptVarFunctionPtr BoundedFunction, CScriptVarPtr BoundedThis, const std::vector<CScriptVarPtr> &BoundedArguments);
1600};
1601inline define_newScriptVar_NamedFnc(FunctionBounded, CScriptVarFunctionPtr BoundedFunction, CScriptVarPtr BoundedThis, const std::vector<CScriptVarPtr> &BoundedArguments) { return new CScriptVarFunctionBounded(BoundedFunction, BoundedThis, BoundedArguments); }
1602
1603
1604//////////////////////////////////////////////////////////////////////////
1605/// CScriptVarFunctionNative
1606//////////////////////////////////////////////////////////////////////////
1607
1608define_ScriptVarPtr_Type(FunctionNative);
1609class CScriptVarFunctionNative : public CScriptVarFunction {
1610protected:
1611 CScriptVarFunctionNative(CTinyJS *Context, void *Userdata) : CScriptVarFunction(Context, new CScriptTokenDataFnc), jsUserData(Userdata) { }
1612 CScriptVarFunctionNative(const CScriptVarFunctionNative &Copy) : CScriptVarFunction(Copy), jsUserData(Copy.jsUserData) { } ///< Copy protected -> use clone for public
1613public:
1614 virtual ~CScriptVarFunctionNative();
1615 virtual CScriptVarPtr clone()=0;
1616 virtual bool isNative(); // { return true; }
1617
1618 virtual void callFunction(const CFunctionsScopePtr &c)=0;// { jsCallback(c, jsCallbackUserData); }
1619protected:
1620 void *jsUserData; ///< user data passed as second argument to native functions
1621};
1622
1623
1624//////////////////////////////////////////////////////////////////////////
1625/// CScriptVarFunctionNativeCallback
1626//////////////////////////////////////////////////////////////////////////
1627
1628define_ScriptVarPtr_Type(FunctionNativeCallback);
1629class CScriptVarFunctionNativeCallback : public CScriptVarFunctionNative {
1630protected:
1631 CScriptVarFunctionNativeCallback(CTinyJS *Context, JSCallback Callback, void *Userdata) : CScriptVarFunctionNative(Context, Userdata), jsCallback(Callback) { }
1632 CScriptVarFunctionNativeCallback(const CScriptVarFunctionNativeCallback &Copy) : CScriptVarFunctionNative(Copy), jsCallback(Copy.jsCallback) { } ///< Copy protected -> use clone for public
1633public:
1634 virtual ~CScriptVarFunctionNativeCallback();
1635 virtual CScriptVarPtr clone();
1636 virtual void callFunction(const CFunctionsScopePtr &c);
1637private:
1638 JSCallback jsCallback; ///< Callback for native functions
1639 friend define_newScriptVar_Fnc(FunctionNativeCallback, CTinyJS *Context, JSCallback Callback, void*);
1640};
1641inline define_newScriptVar_Fnc(FunctionNativeCallback, CTinyJS *Context, JSCallback Callback, void *Userdata) { return new CScriptVarFunctionNativeCallback(Context, Callback, Userdata); }
1642
1643
1644//////////////////////////////////////////////////////////////////////////
1645/// CScriptVarFunctionNativeClass
1646//////////////////////////////////////////////////////////////////////////
1647
1648template<class native>
1649class CScriptVarFunctionNativeClass : public CScriptVarFunctionNative {
1650protected:
1651 CScriptVarFunctionNativeClass(CTinyJS *Context, native *ClassPtr, void (native::*ClassFnc)(const CFunctionsScopePtr &, void *), void *Userdata) : CScriptVarFunctionNative(Context, Userdata), classPtr(ClassPtr), classFnc(ClassFnc) { }
1652 CScriptVarFunctionNativeClass(const CScriptVarFunctionNativeClass &Copy) : CScriptVarFunctionNative(Copy), classPtr(Copy.classPtr), classFnc(Copy.classFnc) { } ///< Copy protected -> use clone for public
1653public:
1654 virtual CScriptVarPtr clone() { return new CScriptVarFunctionNativeClass(*this); }
1655
1656 virtual void callFunction(const CFunctionsScopePtr &c) { (classPtr->*classFnc)(c, jsUserData); }
1657private:
1658 native *classPtr;
1659 void (native::*classFnc)(const CFunctionsScopePtr &c, void *userdata);
1660 template<typename native2>
1661 friend define_newScriptVar_Fnc(FunctionNativeCallback, CTinyJS*, native2 *, void (native2::*)(const CFunctionsScopePtr &, void *), void *);
1662};
1663template<typename native>
1664define_newScriptVar_Fnc(FunctionNativeCallback, CTinyJS *Context, native *ClassPtr, void (native::*ClassFnc)(const CFunctionsScopePtr &, void *), void *Userdata) { return new CScriptVarFunctionNativeClass<native>(Context, ClassPtr, ClassFnc, Userdata); }
1665
1666
1667//////////////////////////////////////////////////////////////////////////
1668/// CScriptVarAccessor
1669//////////////////////////////////////////////////////////////////////////
1670
1671define_dummy_t(Accessor);
1672define_ScriptVarPtr_Type(Accessor);
1673
1674class CScriptVarAccessor : public CScriptVarObject {
1675protected:
1676 CScriptVarAccessor(CTinyJS *Context);
1677 CScriptVarAccessor(CTinyJS *Context, JSCallback getter, void *getterdata, JSCallback setter, void *setterdata);
1678 template<class C> CScriptVarAccessor(CTinyJS *Context, C *class_ptr, void(C::*getterFnc)(const CFunctionsScopePtr &, void *), void *getterData, void(C::*setterFnc)(const CFunctionsScopePtr &, void *), void *setterData) : CScriptVarObject(Context) {
1679 if(getterFnc)
1680 addChild(TINYJS_ACCESSOR_GET_VAR, ::newScriptVar(Context, class_ptr, getterFnc, getterData), 0);
1681 if(setterFnc)
1682 addChild(TINYJS_ACCESSOR_SET_VAR, ::newScriptVar(Context, class_ptr, setterFnc, setterData), 0);
1683 }
1684 CScriptVarAccessor(CTinyJS *Context, const CScriptVarFunctionPtr &getter, const CScriptVarFunctionPtr &setter);
1685
1686 CScriptVarAccessor(const CScriptVarAccessor &Copy) : CScriptVarObject(Copy) {} ///< Copy protected -> use clone for public
1687public:
1688 virtual ~CScriptVarAccessor();
1689 virtual CScriptVarPtr clone();
1690 virtual bool isAccessor(); // { return true; }
1691 virtual bool isPrimitive(); // { return false; }
1692
1693 virtual std::string getParsableString(const std::string &indentString, const std::string &indent, uint32_t uniqueID, bool &hasRecursion);
1694 virtual std::string getVarType(); // { return "object"; }
1695
1696 CScriptVarPtr getValue();
1697
1698 friend define_newScriptVar_Fnc(Accessor, CTinyJS *Context, Accessor_t);
1699 friend define_newScriptVar_NamedFnc(Accessor, CTinyJS *Context, JSCallback getter, void *getterdata, JSCallback setter, void *setterdata);
1700 template<class C> friend define_newScriptVar_NamedFnc(Accessor, CTinyJS *Context, C *class_ptr, void(C::*getterFnc)(const CFunctionsScopePtr &, void *), void *getterData, void(C::*setterFnc)(const CFunctionsScopePtr &, void *), void *setterData);
1701 friend define_newScriptVar_NamedFnc(Accessor, CTinyJS *Context, const CScriptVarFunctionPtr &, const CScriptVarFunctionPtr &);
1702};
1703inline define_newScriptVar_Fnc(Accessor, CTinyJS *Context, Accessor_t) { return new CScriptVarAccessor(Context); }
1704inline define_newScriptVar_NamedFnc(Accessor, CTinyJS *Context, JSCallback getter, void *getterdata, JSCallback setter, void *setterdata) { return new CScriptVarAccessor(Context, getter, getterdata, setter, setterdata); }
1705template<class C> define_newScriptVar_NamedFnc(Accessor, CTinyJS *Context, C *class_ptr, void(C::*getterFnc)(const CFunctionsScopePtr &, void *), void *getterData, void(C::*setterFnc)(const CFunctionsScopePtr &, void *), void *setterData) { return new CScriptVarAccessor(Context, class_ptr, getterFnc, getterData, setterFnc, setterData); }
1706inline define_newScriptVar_NamedFnc(Accessor, CTinyJS *Context, const CScriptVarFunctionPtr &getter, const CScriptVarFunctionPtr &setter) { return new CScriptVarAccessor(Context, getter, setter); }
1707
1708
1709//////////////////////////////////////////////////////////////////////////
1710/// CScriptVarDestructuring
1711//////////////////////////////////////////////////////////////////////////
1712
1713class CScriptVarDestructuring : public CScriptVarObject {
1714protected: // only derived classes or friends can be created
1715 CScriptVarDestructuring(CTinyJS *Context) // constructor for rootScope
1716 : CScriptVarObject(Context) {}
1717 virtual CScriptVarPtr clone();
1718public:
1719 virtual ~CScriptVarDestructuring();
1720};
1721
1722//////////////////////////////////////////////////////////////////////////
1723/// CScriptVarScope
1724//////////////////////////////////////////////////////////////////////////
1725
1726define_dummy_t(Scope);
1727define_ScriptVarPtr_Type(Scope);
1728class CScriptVarScope : public CScriptVarObject {
1729protected: // only derived classes or friends can be created
1730 CScriptVarScope(CTinyJS *Context) // constructor for rootScope
1731 : CScriptVarObject(Context) {}
1732 virtual CScriptVarPtr clone();
1733 virtual bool isObject(); // { return false; }
1734public:
1735 virtual ~CScriptVarScope();
1736 virtual CScriptVarPtr scopeVar(); ///< to create var like: var a = ...
1737 virtual CScriptVarPtr scopeLet(); ///< to create var like: let a = ...
1738 virtual CScriptVarLinkWorkPtr findInScopes(const std::string &childName);
1739 virtual CScriptVarScopePtr getParent();
1740 friend define_newScriptVar_Fnc(Scope, CTinyJS *Context, Scope_t);
1741};
1742inline define_newScriptVar_Fnc(Scope, CTinyJS *Context, Scope_t) { return new CScriptVarScope(Context); }
1743
1744
1745//////////////////////////////////////////////////////////////////////////
1746/// CScriptVarScopeFnc
1747//////////////////////////////////////////////////////////////////////////
1748
1749define_dummy_t(ScopeFnc);
1750define_ScriptVarPtr_Type(ScopeFnc);
1751class CScriptVarScopeFnc : public CScriptVarScope {
1752protected: // only derived classes or friends can be created
1753 CScriptVarScopeFnc(CTinyJS *Context, const CScriptVarScopePtr &Closure) // constructor for FncScope
1754 : CScriptVarScope(Context), closure(Closure ? addChild(TINYJS_FUNCTION_CLOSURE_VAR, Closure, 0) : CScriptVarLinkPtr()) {}
1755public:
1756 virtual ~CScriptVarScopeFnc();
1757 virtual CScriptVarLinkWorkPtr findInScopes(const std::string &childName);
1758
1759 void setReturnVar(const CScriptVarPtr &var); ///< Set the result value. Use this when setting complex return data as it avoids a deepCopy()
1760
1761 #define DEPRECATED_getParameter DEPRECATED("getParameter is deprecated use getArgument instead")
1762 DEPRECATED_getParameter CScriptVarPtr getParameter(const std::string &name);
1763 DEPRECATED_getParameter CScriptVarPtr getParameter(int Idx);
1764 CScriptVarPtr getArgument(const std::string &name); ///< If this is a function, get the parameter with the given name (for use by native functions)
1765 CScriptVarPtr getArgument(int Idx); ///< If this is a function, get the parameter with the given index (for use by native functions)
1766 DEPRECATED("getParameterLength is deprecated use getArgumentsLength instead") int getParameterLength(); ///< If this is a function, get the count of parameters
1767 int getArgumentsLength(); ///< If this is a function, get the count of parameters
1768
1769 void throwError(ERROR_TYPES ErrorType, const std::string &message);
1770
1771protected:
1772 CScriptVarLinkPtr closure;
1773 friend define_newScriptVar_Fnc(ScopeFnc, CTinyJS *Context, ScopeFnc_t, const CScriptVarScopePtr &Closure);
1774};
1775inline define_newScriptVar_Fnc(ScopeFnc, CTinyJS *Context, ScopeFnc_t, const CScriptVarScopePtr &Closure) { return new CScriptVarScopeFnc(Context, Closure); }
1776
1777
1778//////////////////////////////////////////////////////////////////////////
1779/// CScriptVarScopeLet
1780//////////////////////////////////////////////////////////////////////////
1781
1782define_dummy_t(ScopeLet);
1783define_ScriptVarPtr_Type(ScopeLet);
1784class CScriptVarScopeLet : public CScriptVarScope {
1785protected: // only derived classes or friends can be created
1786 CScriptVarScopeLet(const CScriptVarScopePtr &Parent); // constructor for LetScope
1787// : CScriptVarScope(Parent->getContext()), parent( context->getRoot() != Parent ? addChild(TINYJS_SCOPE_PARENT_VAR, Parent, 0) : 0) {}
1788public:
1789 virtual ~CScriptVarScopeLet();
1790 virtual CScriptVarLinkWorkPtr findInScopes(const std::string &childName);
1791 virtual CScriptVarPtr scopeVar(); ///< to create var like: var a = ...
1792 virtual CScriptVarScopePtr getParent();
1793 void setletExpressionInitMode(bool Mode) { letExpressionInitMode = Mode; }
1794protected:
1795 CScriptVarLinkPtr parent;
1796 bool letExpressionInitMode;
1797 friend define_newScriptVar_Fnc(ScopeLet, CTinyJS *Context, ScopeLet_t, const CScriptVarScopePtr &Parent);
1798};
1799inline define_newScriptVar_Fnc(ScopeLet, CTinyJS *, ScopeLet_t, const CScriptVarScopePtr &Parent) { return new CScriptVarScopeLet(Parent); }
1800
1801
1802//////////////////////////////////////////////////////////////////////////
1803/// CScriptVarScopeWith
1804//////////////////////////////////////////////////////////////////////////
1805
1806define_dummy_t(ScopeWith);
1807define_ScriptVarPtr_Type(ScopeWith);
1808class CScriptVarScopeWith : public CScriptVarScopeLet {
1809protected:
1810 CScriptVarScopeWith(const CScriptVarScopePtr &Parent, const CScriptVarPtr &With)
1811 : CScriptVarScopeLet(Parent), with(addChild(TINYJS_SCOPE_WITH_VAR, With, 0)) {}
1812
1813public:
1814 virtual ~CScriptVarScopeWith();
1815 virtual CScriptVarPtr scopeLet(); ///< to create var like: let a = ...
1816 virtual CScriptVarLinkWorkPtr findInScopes(const std::string &childName);
1817private:
1818 CScriptVarLinkPtr with;
1819 friend define_newScriptVar_Fnc(ScopeWith, CTinyJS *Context, ScopeWith_t, const CScriptVarScopePtr &Parent, const CScriptVarPtr &With);
1820};
1821inline define_newScriptVar_Fnc(ScopeWith, CTinyJS *, ScopeWith_t, const CScriptVarScopePtr &Parent, const CScriptVarPtr &With) { return new CScriptVarScopeWith(Parent, With); }
1822
1823
1824//////////////////////////////////////////////////////////////////////////
1825template<typename T>
1826inline CScriptVarPtr CScriptVar::newScriptVar(T t) { return ::newScriptVar(context, t); }
1827template<typename T1, typename T2>
1828inline CScriptVarPtr CScriptVar::newScriptVar(T1 t1, T2 t2) { return ::newScriptVar(context, t1, t2); }
1829//inline CScriptVarPtr newScriptVar(const CNumber &t) { return ::newScriptVar(context, t); }
1830//////////////////////////////////////////////////////////////////////////
1831
1832
1833class CScriptResult {
1834public:
1835 enum TYPE {
1836 Normal,
1837 Break,
1838 Continue,
1839 Return,
1840 Throw,
1841 noExecute
1842 };
1843 CScriptResult() : type(Normal) {}
1844 CScriptResult(TYPE Type) : type(Type) {}
1845// ~RESULT() { if(type==Throw) throw value; }
1846 bool isNormal() { return type==Normal; }
1847 bool isBreak() { return type==Break; }
1848 bool isContinue() { return type==Continue; }
1849 bool isBreakContinue() { return type==Break || type==Continue; }
1850 bool isReturn() { return type==Return; }
1851 bool isReturnNormal() { return type==Return || type==Normal; }
1852 bool isThrow() { return type==Throw; }
1853
1854 operator bool() const { return type==Normal; }
1855 void set(TYPE Type, bool Clear=true) { type=Type; if(Clear) value.clear(), target.clear(); }
1856 void set(TYPE Type, const CScriptVarPtr &Value) { type=Type; value=Value; }
1857 void set(TYPE Type, const std::string &Target) { type=Type; target=Target; }
1858
1859 void cThrow() { if(type==Throw) throw value; }
1860
1861 CScriptResult &operator()(const CScriptResult &rhs) { if(type!=Normal) *this=rhs; return *this; }
1862
1863 enum TYPE type;
1864 CScriptVarPtr value;
1865 std::string target;
1866};
1867
1868
1869
1870//////////////////////////////////////////////////////////////////////////
1871/// CTinyJS
1872//////////////////////////////////////////////////////////////////////////
1873
1874class CTinyJS {
1875public:
1876 CTinyJS();
1877 ~CTinyJS();
1878
1879 void execute(CScriptTokenizer &Tokenizer);
1880 void execute(const char *Code, const std::string &File="", int Line=0, int Column=0);
1881 void execute(const std::string &Code, const std::string &File="", int Line=0, int Column=0);
1882 /** Evaluate the given code and return a link to a javascript object,
1883 * useful for (dangerous) JSON parsing. If nothing to return, will return
1884 * 'undefined' variable type. CScriptVarLink is returned as this will
1885 * automatically unref the result as it goes out of scope. If you want to
1886 * keep it, you must use ref() and unref() */
1887 CScriptVarLinkPtr evaluateComplex(CScriptTokenizer &Tokenizer);
1888 /** Evaluate the given code and return a link to a javascript object,
1889 * useful for (dangerous) JSON parsing. If nothing to return, will return
1890 * 'undefined' variable type. CScriptVarLink is returned as this will
1891 * automatically unref the result as it goes out of scope. If you want to
1892 * keep it, you must use ref() and unref() */
1893 CScriptVarLinkPtr evaluateComplex(const char *code, const std::string &File="", int Line=0, int Column=0);
1894 /** Evaluate the given code and return a link to a javascript object,
1895 * useful for (dangerous) JSON parsing. If nothing to return, will return
1896 * 'undefined' variable type. CScriptVarLink is returned as this will
1897 * automatically unref the result as it goes out of scope. If you want to
1898 * keep it, you must use ref() and unref() */
1899 CScriptVarLinkPtr evaluateComplex(const std::string &code, const std::string &File="", int Line=0, int Column=0);
1900 /** Evaluate the given code and return a string. If nothing to return, will return
1901 * 'undefined' */
1902 std::string evaluate(CScriptTokenizer &Tokenizer);
1903 /** Evaluate the given code and return a string. If nothing to return, will return
1904 * 'undefined' */
1905 std::string evaluate(const char *code, const std::string &File="", int Line=0, int Column=0);
1906 /** Evaluate the given code and return a string. If nothing to return, will return
1907 * 'undefined' */
1908 std::string evaluate(const std::string &code, const std::string &File="", int Line=0, int Column=0);
1909
1910 /// add a native function to be called from TinyJS
1911 /** example:
1912 \code
1913 void scRandInt(const CFunctionsScopePtr &c, void *userdata) { ... }
1914 tinyJS->addNative("function randInt(min, max)", scRandInt, 0);
1915 \endcode
1916
1917 or
1918
1919 \code
1920 void scSubstring(const CFunctionsScopePtr &c, void *userdata) { ... }
1921 tinyJS->addNative("function String.substring(lo, hi)", scSubstring, 0);
1922 \endcode
1923 or
1924
1925 \code
1926 class Class
1927 {
1928 public:
1929 void scSubstring(const CFunctionsScopePtr &c, void *userdata) { ... }
1930 };
1931 Class Instanz;
1932 tinyJS->addNative("function String.substring(lo, hi)", &Instanz, &Class::*scSubstring, 0);
1933 \endcode
1934 */
1935
1936 CScriptVarFunctionNativePtr addNative(const std::string &funcDesc, JSCallback ptr, void *userdata=0, int LinkFlags=SCRIPTVARLINK_BUILDINDEFAULT);
1937 template<class C>
1938 CScriptVarFunctionNativePtr addNative(const std::string &funcDesc, C *class_ptr, void(C::*class_fnc)(const CFunctionsScopePtr &, void *), void *userdata=0, int LinkFlags=SCRIPTVARLINK_BUILDINDEFAULT)
1939 {
1940 return addNative(funcDesc, ::newScriptVar<C>(this, class_ptr, class_fnc, userdata), LinkFlags);
1941 }
1942
1943 /// Send all variables to stdout
1944 void trace();
1945
1946 const CScriptVarScopePtr &getRoot() { return root; }; /// gets the root of symbol table
1947 // CScriptVar *root; /// root of symbol table
1948
1949 /// newVars & constVars
1950 //CScriptVarPtr newScriptVar(const CNumber &t) { return ::newScriptVar(this, t); }
1951 template<typename T> CScriptVarPtr newScriptVar(T t) { return ::newScriptVar(this, t); }
1952 template<typename T1, typename T2> CScriptVarPtr newScriptVar(T1 t1, T2 t2) { return ::newScriptVar(this, t1, t2); }
1953 const CScriptVarPtr &constScriptVar(Undefined_t) { return constUndefined; }
1954 const CScriptVarPtr &constScriptVar(Null_t) { return constNull; }
1955 const CScriptVarPtr &constScriptVar(NaN_t) { return constNaN; }
1956 const CScriptVarPtr &constScriptVar(Infinity t) { return t.Sig()<0 ? constInfinityNegative : constInfinityPositive; }
1957 const CScriptVarPtr &constScriptVar(bool Val) { return Val?constTrue:constFalse; }
1958 const CScriptVarPtr &constScriptVar(NegativeZero_t) { return constNegativZero; }
1959 const CScriptVarPtr &constScriptVar(StopIteration_t) { return constStopIteration; }
1960
1961private:
1962 CScriptTokenizer *t; /// current tokenizer
1963 bool haveTry;
1964 std::vector<CScriptVarScopePtr>scopes;
1965 CScriptVarScopePtr root;
1966 const CScriptVarScopePtr &scope() { return scopes.back(); }
1967
1968 class CScopeControl { // helper-class to manage scopes
1969 private:
1970 CScopeControl(const CScopeControl& Copy) MEMBER_DELETE; // no copy
1971 CScopeControl& operator =(const CScopeControl& Copy) MEMBER_DELETE;
1972 public:
1973 CScopeControl(CTinyJS *Context) : context(Context), count(0) {}
1974 ~CScopeControl() { while(count--) {CScriptVarScopePtr parent = context->scopes.back()->getParent(); if(parent) context->scopes.back() = parent; else context->scopes.pop_back() ;} }
1975 void addFncScope(const CScriptVarScopePtr &Scope) { context->scopes.push_back(Scope); count++; }
1976 CScriptVarScopeLetPtr addLetScope() { count++; return context->scopes.back() = ::newScriptVar(context, ScopeLet, context->scopes.back()); }
1977 void addWithScope(const CScriptVarPtr &With) { context->scopes.back() = ::newScriptVar(context, ScopeWith, context->scopes.back(), With); count++; }
1978 private:
1979 CTinyJS *context;
1980 int count;
1981 };
1982 friend class CScopeControl;
1983public:
1984 CScriptVarPtr objectPrototype; /// Built in object class
1985 CScriptVarPtr objectPrototype_valueOf; /// Built in object class
1986 CScriptVarPtr objectPrototype_toString; /// Built in object class
1987 CScriptVarPtr arrayPrototype; /// Built in array class
1988 CScriptVarPtr stringPrototype; /// Built in string class
1989 CScriptVarPtr regexpPrototype; /// Built in string class
1990 CScriptVarPtr numberPrototype; /// Built in number class
1991 CScriptVarPtr booleanPrototype; /// Built in boolean class
1992 CScriptVarPtr iteratorPrototype; /// Built in boolean class
1993 CScriptVarPtr functionPrototype; /// Built in function class
1994 const CScriptVarPtr &getErrorPrototype(ERROR_TYPES Type) { return errorPrototypes[Type]; }
1995private:
1996 CScriptVarPtr errorPrototypes[ERROR_COUNT]; /// Built in error class
1997 CScriptVarPtr constUndefined;
1998 CScriptVarPtr constNull;
1999 CScriptVarPtr constNaN;
2000 CScriptVarPtr constInfinityPositive;
2001 CScriptVarPtr constInfinityNegative;
2002 CScriptVarPtr constNegativZero;
2003 CScriptVarPtr constTrue;
2004 CScriptVarPtr constFalse;
2005 CScriptVarPtr constStopIteration;
2006
2007 std::vector<CScriptVarPtr *> pseudo_refered;
2008
2009 void CheckRightHandVar(CScriptResult &execute, CScriptVarLinkWorkPtr &link)
2010 {
2011 if(execute && link && !link->isOwned() && !link.hasReferencedOwner() && !link->getName().empty())
2012 throwError(execute, ReferenceError, link->getName() + " is not defined", t->getPrevPos());
2013 }
2014
2015 void CheckRightHandVar(CScriptResult &execute, CScriptVarLinkWorkPtr &link, CScriptTokenizer::ScriptTokenPosition &Pos)
2016 {
2017 if(execute && link && !link->isOwned() && !link.hasReferencedOwner() && !link->getName().empty())
2018 throwError(execute, ReferenceError, link->getName() + " is not defined", Pos);
2019 }
2020
2021public:
2022 // function call
2023 CScriptVarPtr callFunction(const CScriptVarFunctionPtr &Function, std::vector<CScriptVarPtr> &Arguments, const CScriptVarPtr &This, CScriptVarPtr *newThis=0);
2024 CScriptVarPtr callFunction(CScriptResult &execute, const CScriptVarFunctionPtr &Function, std::vector<CScriptVarPtr> &Arguments, const CScriptVarPtr &This, CScriptVarPtr *newThis=0);
2025
2026 // parsing - in order of precedence
2027 CScriptVarPtr mathsOp(CScriptResult &execute, const CScriptVarPtr &a, const CScriptVarPtr &b, int op);
2028private:
2029 void assign_destructuring_var(const CScriptVarPtr &Scope, const CScriptTokenDataDestructuringVar &Objc, const CScriptVarPtr &Val, CScriptResult &execute);
2030 void execute_var_init(bool hideLetScope, CScriptResult &execute);
2031 void execute_destructuring(CScriptTokenDataObjectLiteral &Objc, const CScriptVarPtr &Val, CScriptResult &execute);
2032 CScriptVarLinkWorkPtr execute_literals(CScriptResult &execute);
2033 CScriptVarLinkWorkPtr execute_member(CScriptVarLinkWorkPtr &parent, CScriptResult &execute);
2034 CScriptVarLinkWorkPtr execute_function_call(CScriptResult &execute);
2035 bool execute_unary_rhs(CScriptResult &execute, CScriptVarLinkWorkPtr& a);
2036 CScriptVarLinkWorkPtr execute_unary(CScriptResult &execute);
2037 CScriptVarLinkWorkPtr execute_term(CScriptResult &execute);
2038 CScriptVarLinkWorkPtr execute_expression(CScriptResult &execute);
2039 CScriptVarLinkWorkPtr execute_binary_shift(CScriptResult &execute);
2040 CScriptVarLinkWorkPtr execute_relation(CScriptResult &execute, int set=LEX_EQUAL, int set_n='<');
2041 CScriptVarLinkWorkPtr execute_binary_logic(CScriptResult &execute, int op='|', int op_n1='^', int op_n2='&');
2042 CScriptVarLinkWorkPtr execute_logic(CScriptResult &execute, int op=LEX_OROR, int op_n=LEX_ANDAND);
2043 CScriptVarLinkWorkPtr execute_condition(CScriptResult &execute);
2044 CScriptVarLinkPtr execute_assignment(CScriptVarLinkWorkPtr Lhs, CScriptResult &execute);
2045 CScriptVarLinkPtr execute_assignment(CScriptResult &execute);
2046 CScriptVarLinkPtr execute_base(CScriptResult &execute);
2047 void execute_block(CScriptResult &execute);
2048 void execute_statement(CScriptResult &execute);
2049 // parsing utility functions
2050 CScriptVarLinkWorkPtr parseFunctionDefinition(const CScriptToken &FncToken);
2051 CScriptVarLinkWorkPtr parseFunctionsBodyFromString(const std::string &ArgumentList, const std::string &FncBody);
2052public:
2053 CScriptVarLinkPtr findInScopes(const std::string &childName); ///< Finds a child, looking recursively up the scopes
2054private:
2055 //////////////////////////////////////////////////////////////////////////
2056 /// addNative-helper
2057 CScriptVarFunctionNativePtr addNative(const std::string &funcDesc, CScriptVarFunctionNativePtr Var, int LinkFlags);
2058
2059 //////////////////////////////////////////////////////////////////////////
2060 /// throws an Error & Exception
2061public:
2062 void throwError(CScriptResult &execute, ERROR_TYPES ErrorType, const std::string &message);
2063 void throwException(ERROR_TYPES ErrorType, const std::string &message);
2064 void throwError(CScriptResult &execute, ERROR_TYPES ErrorType, const std::string &message, CScriptTokenizer::ScriptTokenPosition &Pos);
2065 void throwException(ERROR_TYPES ErrorType, const std::string &message, CScriptTokenizer::ScriptTokenPosition &Pos);
2066private:
2067 //////////////////////////////////////////////////////////////////////////
2068 /// native Object-Constructors & prototype-functions
2069
2070 void native_Object(const CFunctionsScopePtr &c, void *data);
2071 void native_Object_getPrototypeOf(const CFunctionsScopePtr &c, void *data);
2072 /* Userdate for set-/isObjectState
2073 * 0 - preventExtensions / isExtensible
2074 * 1 - seal / isSealed
2075 * 2 - freeze / isFrozen
2076 */
2077 void native_Object_setObjectSecure(const CFunctionsScopePtr &c, void *data);
2078 void native_Object_isSecureObject(const CFunctionsScopePtr &c, void *data);
2079 void native_Object_keys(const CFunctionsScopePtr &c, void *data);
2080 void native_Object_getOwnPropertyDescriptor(const CFunctionsScopePtr &c, void *data);
2081 void native_Object_defineProperty(const CFunctionsScopePtr &c, void *data);
2082 void native_Object_defineProperties(const CFunctionsScopePtr &c, void *data);
2083
2084 void native_Object_prototype_hasOwnProperty(const CFunctionsScopePtr &c, void *data);
2085 void native_Object_prototype_valueOf(const CFunctionsScopePtr &c, void *data);
2086 void native_Object_prototype_toString(const CFunctionsScopePtr &c, void *data);
2087
2088 void native_Array(const CFunctionsScopePtr &c, void *data);
2089
2090 void native_String(const CFunctionsScopePtr &c, void *data);
2091
2092 void native_RegExp(const CFunctionsScopePtr &c, void *data);
2093
2094 void native_Number(const CFunctionsScopePtr &c, void *data);
2095
2096 void native_Boolean(const CFunctionsScopePtr &c, void *data);
2097
2098 void native_Iterator(const CFunctionsScopePtr &c, void *data);
2099
2100 void native_Function(const CFunctionsScopePtr &c, void *data);
2101 void native_Function_prototype_call(const CFunctionsScopePtr &c, void *data);
2102 void native_Function_prototype_apply(const CFunctionsScopePtr &c, void *data);
2103 void native_Function_prototype_bind(const CFunctionsScopePtr &c, void *data);
2104
2105 void native_Error(const CFunctionsScopePtr &c, void *data);
2106 void native_EvalError(const CFunctionsScopePtr &c, void *data);
2107 void native_RangeError(const CFunctionsScopePtr &c, void *data);
2108 void native_ReferenceError(const CFunctionsScopePtr &c, void *data);
2109 void native_SyntaxError(const CFunctionsScopePtr &c, void *data);
2110 void native_TypeError(const CFunctionsScopePtr &c, void *data);
2111
2112
2113 //////////////////////////////////////////////////////////////////////////
2114 /// global function
2115
2116 void native_eval(const CFunctionsScopePtr &c, void *data);
2117 void native_isNAN(const CFunctionsScopePtr &c, void *data);
2118 void native_isFinite(const CFunctionsScopePtr &c, void *data);
2119 void native_parseInt(const CFunctionsScopePtr &c, void *data);
2120 void native_parseFloat(const CFunctionsScopePtr &c, void *data);
2121
2122
2123
2124 void native_JSON_parse(const CFunctionsScopePtr &c, void *data);
2125
2126
2127 uint32_t uniqueID;
2128public:
2129 uint32_t getUniqueID() { return ++uniqueID; }
2130 CScriptVar *first;
2131 void setTemporaryID_recursive(uint32_t ID);
2132 void ClearUnreferedVars(const CScriptVarPtr &extra=CScriptVarPtr());
2133};
2134
2135
2136//////////////////////////////////////////////////////////////////////////
2137template<typename T>
2138inline const CScriptVarPtr &CScriptVar::constScriptVar(T t) { return context->constScriptVar(t); }
2139//////////////////////////////////////////////////////////////////////////
2140inline CNumber CScriptVarLink::toNumber() { return var->toNumber(); }
2141inline CNumber CScriptVarLink::toNumber(CScriptResult &execute) { return var->toNumber(execute); }
2142
2143#endif
2144
2145
Note: See TracBrowser for help on using the repository browser.