1 /*
2  *  This file is part of the KDE libraries
3  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
4  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
5  *  Copyright (C) 2003 Apple Computer, Inc.
6  *  Copyright (C) 2008, 2009 Maksim Orlovich (maksim@kde.org)
7  *
8  *  This library is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU Library General Public
10  *  License as published by the Free Software Foundation; either
11  *  version 2 of the License, or (at your option) any later version.
12  *
13  *  This library is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *  Library General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Library General Public License
19  *  along with this library; see the file COPYING.LIB.  If not, write to
20  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  *  Boston, MA 02110-1301, USA.
22  *
23  */
24 
25 #include "interpreter.h"
26 
27 #include "SavedBuiltins.h"
28 #include "array_object.h"
29 #include "bool_object.h"
30 #include "collector.h"
31 #include "date_object.h"
32 #include "debugger.h"
33 #include "error_object.h"
34 #include "function_object.h"
35 #include "internal.h"
36 #include "math_object.h"
37 #include "nodes.h"
38 #include "number_object.h"
39 #include "object.h"
40 #include "object_object.h"
41 #include "operations.h"
42 #include "regexp_object.h"
43 #include "string_object.h"
44 #include "lexer.h"
45 #include "json_object.h"
46 
47 #if USE(BINDINGS)
48 #include "runtime.h"
49 #endif
50 
51 #if defined _WIN32 || defined _WIN64
52 #undef HAVE_SYS_TIME_H // no setitimer in kdewin32
53 #endif
54 #if HAVE_SYS_TIME_H
55 #include <sys/time.h>
56 #endif
57 
58 #include <assert.h>
59 #include <cstdlib>
60 #include <math.h>
61 #include <signal.h>
62 #include <stdio.h>
63 #if HAVE_UNISTD_H
64 #include <unistd.h>
65 #endif
66 
67 namespace KJS
68 {
69 
70 class TimeoutChecker
71 {
72 public:
73     void startTimeoutCheck(Interpreter *);
74     void stopTimeoutCheck(Interpreter *);
75     void pauseTimeoutCheck(Interpreter *);
76     void resumeTimeoutCheck(Interpreter *);
77 
78 private:
79 #if HAVE_SYS_TIME_H
80     static Interpreter *s_executingInterpreter;
81     static void alarmHandler(int);
82 
83     Interpreter *m_oldInterpreter;
84     itimerval m_oldtv;
85     itimerval m_pausetv;
86     void (*m_oldAlarmHandler)(int);
87 #endif
88 };
89 
90 #if HAVE_SYS_TIME_H
91 Interpreter *TimeoutChecker::s_executingInterpreter = nullptr;
92 #endif
93 
startTimeoutCheck(Interpreter * interpreter)94 void TimeoutChecker::startTimeoutCheck(Interpreter *interpreter)
95 {
96     if (!interpreter->m_timeoutTime) {
97         return;
98     }
99 
100     interpreter->m_startTimeoutCheckCount++;
101 
102 #if HAVE_SYS_TIME_H
103     if (s_executingInterpreter == interpreter) {
104         return;
105     }
106 
107     // Block signals
108     m_oldAlarmHandler = signal(SIGALRM, SIG_IGN);
109 
110     m_oldInterpreter = s_executingInterpreter;
111     s_executingInterpreter = interpreter;
112 
113     itimerval tv = {
114         { time_t(interpreter->m_timeoutTime / 1000),
115           suseconds_t((interpreter->m_timeoutTime % 1000) * 1000) },
116         { time_t(interpreter->m_timeoutTime / 1000),
117           suseconds_t((interpreter->m_timeoutTime % 1000) * 1000) }
118     };
119     setitimer(ITIMER_REAL, &tv, &m_oldtv);
120 
121     // Unblock signals
122     signal(SIGALRM, alarmHandler);
123 #endif
124 }
125 
stopTimeoutCheck(Interpreter * interpreter)126 void TimeoutChecker::stopTimeoutCheck(Interpreter *interpreter)
127 {
128     if (!interpreter->m_timeoutTime) {
129         return;
130     }
131 
132     ASSERT(interpreter->m_startTimeoutCheckCount > 0);
133 
134     interpreter->m_startTimeoutCheckCount--;
135 
136     if (interpreter->m_startTimeoutCheckCount != 0) {
137         return;
138     }
139 
140 #if HAVE_SYS_TIME_H
141     signal(SIGALRM, SIG_IGN);
142 
143     s_executingInterpreter = m_oldInterpreter;
144 
145     setitimer(ITIMER_REAL, &m_oldtv, nullptr);
146     signal(SIGALRM, m_oldAlarmHandler);
147 #endif
148 }
149 
150 #if HAVE_SYS_TIME_H
alarmHandler(int)151 void TimeoutChecker::alarmHandler(int)
152 {
153     s_executingInterpreter->m_timedOut = true;
154 }
155 #endif
156 
pauseTimeoutCheck(Interpreter * interpreter)157 void TimeoutChecker::pauseTimeoutCheck(Interpreter *interpreter)
158 {
159     if (interpreter->m_startTimeoutCheckCount == 0) {
160         return;
161     }
162 
163 #if HAVE_SYS_TIME_H
164     ASSERT(interpreter == s_executingInterpreter);
165 
166     void (*currentSignalHandler)(int);
167 
168     // Block signal
169     currentSignalHandler = signal(SIGALRM, SIG_IGN);
170 
171     if (currentSignalHandler != alarmHandler) {
172         signal(SIGALRM, currentSignalHandler);
173         return;
174     }
175 
176     setitimer(ITIMER_REAL, nullptr, &m_pausetv);
177 #endif
178 
179     interpreter->m_pauseTimeoutCheckCount++;
180 }
181 
resumeTimeoutCheck(Interpreter * interpreter)182 void TimeoutChecker::resumeTimeoutCheck(Interpreter *interpreter)
183 {
184     if (interpreter->m_startTimeoutCheckCount == 0) {
185         return;
186     }
187 
188 #if HAVE_SYS_TIME_H
189     ASSERT(interpreter == s_executingInterpreter);
190 #endif
191 
192     interpreter->m_pauseTimeoutCheckCount--;
193 
194     if (interpreter->m_pauseTimeoutCheckCount != 0) {
195         return;
196     }
197 
198 #if HAVE_SYS_TIME_H
199     void (*currentSignalHandler)(int);
200 
201     // Check so we have the right handler
202     currentSignalHandler = signal(SIGALRM, SIG_IGN);
203 
204     if (currentSignalHandler != SIG_IGN) {
205         signal(SIGALRM, currentSignalHandler);
206         return;
207     }
208 
209     setitimer(ITIMER_REAL, &m_pausetv, nullptr);
210 
211     // Unblock signal
212     currentSignalHandler = signal(SIGALRM, alarmHandler);
213 #endif
214 }
215 
216 Interpreter *Interpreter::s_hook = nullptr;
217 
Interpreter(JSGlobalObject * globalObject)218 Interpreter::Interpreter(JSGlobalObject *globalObject)
219     : m_globalObject(globalObject),
220       m_globalExec(this, globalObject),
221       globPkg(nullptr)
222 {
223     init();
224 }
225 
Interpreter()226 Interpreter::Interpreter()
227     : m_globalObject(new JSGlobalObject()),
228       m_globalExec(this, m_globalObject),
229       globPkg(nullptr)
230 {
231     init();
232 }
233 
init()234 void Interpreter::init()
235 {
236     JSLock lock;
237 
238     initInternedStringsTable();
239 
240     m_refCount = 0;
241     m_timeoutTime = 0;
242     m_recursion = 0;
243     m_debugger = nullptr;
244     m_execState = nullptr;
245     m_timedOut = false;
246     m_timeoutChecker = nullptr;
247     m_startTimeoutCheckCount = 0;
248     m_pauseTimeoutCheckCount = 0;
249     m_compatMode = NativeMode;
250 
251     const int initialStackSize = 8192;
252     stackBase = (unsigned char *)std::malloc(initialStackSize);
253     stackPtr  = stackBase;
254     stackEnd  = stackBase + initialStackSize;
255 
256     m_numCachedActivations = 0;
257 
258     m_globalObject->setInterpreter(this);
259 
260     if (s_hook) {
261         prev = s_hook;
262         next = s_hook->next;
263         s_hook->next->prev = this;
264         s_hook->next = this;
265     } else {
266         // This is the first interpreter
267         s_hook = next = prev = this;
268     }
269 
270     initGlobalObject();
271 }
272 
~Interpreter()273 Interpreter::~Interpreter()
274 {
275     JSLock lock;
276 
277     ASSERT(m_startTimeoutCheckCount == 0);
278     ASSERT(m_pauseTimeoutCheckCount == 0);
279 
280     delete m_timeoutChecker;
281 
282     if (m_debugger) {
283         m_debugger->detach(this);
284     }
285 
286     std::free(stackBase);
287 
288     next->prev = prev;
289     prev->next = next;
290     s_hook = next;
291     if (s_hook == this) {
292         // This was the last interpreter
293         s_hook = nullptr;
294     }
295 
296     m_globalObject->setInterpreter(nullptr);
297 }
298 
extendStack(size_t needed)299 unsigned char *Interpreter::extendStack(size_t needed)
300 {
301     unsigned char *oldBase = stackBase; // needed for fixing up localStores
302 
303     size_t curSize = stackEnd - stackBase;
304     size_t avail = stackEnd - stackPtr;
305     size_t extra = needed - avail;
306 
307     if (extra < 8192) {
308         extra = 8192;
309     }
310     size_t newSize = curSize + extra;
311 
312     //printf("Grow stack:%d -> %d\n", curSize, newSize);
313 
314     stackBase = (unsigned char *)std::malloc(newSize); // Not realloc since we need the old stuff
315     // ### seems optimizeable
316     std::memcpy(stackBase, oldBase, curSize);
317     stackPtr  = stackBase + (stackPtr - oldBase);
318     stackEnd  = stackBase + newSize;
319 
320     // Now go through and fix up activations..
321     ExecState *e = m_execState;
322     while (e) {
323         if (e->codeType() == FunctionCode) {
324             ActivationImp *act = static_cast<ActivationImp *>(e->activationObject());
325             if (act->localStorage) {
326                 act->localStorage = (LocalStorageEntry *)
327                                     (stackBase + ((unsigned char *)act->localStorage - oldBase));
328                 e->updateLocalStorage(act->localStorage);
329             }
330         }
331 
332         e = e->savedExecState();
333     }
334 
335     std::free(oldBase);
336 
337     return stackAlloc(needed);
338 }
339 
recycleActivation(ActivationImp * act)340 void Interpreter::recycleActivation(ActivationImp *act)
341 {
342     ASSERT(act->localStorage == nullptr); // Should not refer to anything by now
343     if (m_numCachedActivations >= MaxCachedActivations) {
344         return;
345     }
346 
347     act->clearProperties();
348     m_cachedActivations[m_numCachedActivations] = act;
349     ++m_numCachedActivations;
350 }
351 
globalObject() const352 JSGlobalObject *Interpreter::globalObject() const
353 {
354     return m_globalObject;
355 }
356 
putNamedConstructor(const char * name,JSObject * value)357 void Interpreter::putNamedConstructor(const char *name, JSObject *value)
358 {
359     assert(value->implementsCall());
360     Identifier i(name);
361     m_globalObject->put(&m_globalExec, i, value, DontEnum);
362     static_cast<InternalFunctionImp *>(value)->setFunctionName(i);
363 }
364 
initGlobalObject()365 void Interpreter::initGlobalObject()
366 {
367     FunctionPrototype *funcProto = new FunctionPrototype(&m_globalExec);
368     m_FunctionPrototype = funcProto;
369     ObjectPrototype *objProto = new ObjectPrototype(&m_globalExec, funcProto);
370     m_ObjectPrototype = objProto;
371     funcProto->setPrototype(m_ObjectPrototype);
372 
373     ArrayPrototype *arrayProto = new ArrayPrototype(&m_globalExec, objProto);
374     m_ArrayPrototype = arrayProto;
375     StringPrototype *stringProto = new StringPrototype(&m_globalExec, objProto);
376     m_StringPrototype = stringProto;
377     BooleanPrototype *booleanProto = new BooleanPrototype(&m_globalExec, objProto, funcProto);
378     m_BooleanPrototype = booleanProto;
379     NumberPrototype *numberProto = new NumberPrototype(&m_globalExec, objProto, funcProto);
380     m_NumberPrototype = numberProto;
381     DatePrototype *dateProto = new DatePrototype(&m_globalExec, objProto);
382     m_DatePrototype = dateProto;
383     RegExpPrototype *regexpProto = new RegExpPrototype(&m_globalExec, objProto, funcProto);
384     m_RegExpPrototype = regexpProto;
385     ErrorPrototype *errorProto = new ErrorPrototype(&m_globalExec, objProto, funcProto);
386     m_ErrorPrototype = errorProto;
387 
388     JSObject *o = m_globalObject;
389     while (JSValue::isObject(o->prototype())) {
390         o = static_cast<JSObject *>(o->prototype());
391     }
392     o->setPrototype(m_ObjectPrototype);
393 
394     // Constructors (Object, Array, etc.)
395     m_Object = new ObjectObjectImp(&m_globalExec, objProto, funcProto);
396     m_Function = new FunctionObjectImp(&m_globalExec, funcProto);
397     m_Array = new ArrayObjectImp(&m_globalExec, funcProto, arrayProto);
398     m_String = new StringObjectImp(&m_globalExec, funcProto, stringProto);
399     m_Boolean = new BooleanObjectImp(&m_globalExec, funcProto, booleanProto);
400     m_Number = new NumberObjectImp(&m_globalExec, funcProto, numberProto);
401     m_Date = new DateObjectImp(&m_globalExec, funcProto, dateProto);
402     m_RegExp = new RegExpObjectImp(&m_globalExec, funcProto, regexpProto);
403     m_Error = new ErrorObjectImp(&m_globalExec, funcProto, errorProto);
404 
405     // Error object prototypes
406     m_EvalErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, EvalError, "EvalError", "EvalError");
407     m_RangeErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, RangeError, "RangeError", "RangeError");
408     m_ReferenceErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, ReferenceError, "ReferenceError", "ReferenceError");
409     m_SyntaxErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, SyntaxError, "SyntaxError", "SyntaxError");
410     m_TypeErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, TypeError, "TypeError", "TypeError");
411     m_UriErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, URIError, "URIError", "URIError");
412 
413     // Error objects
414     m_EvalError = new NativeErrorImp(&m_globalExec, funcProto, m_EvalErrorPrototype);
415     m_RangeError = new NativeErrorImp(&m_globalExec, funcProto, m_RangeErrorPrototype);
416     m_ReferenceError = new NativeErrorImp(&m_globalExec, funcProto, m_ReferenceErrorPrototype);
417     m_SyntaxError = new NativeErrorImp(&m_globalExec, funcProto, m_SyntaxErrorPrototype);
418     m_TypeError = new NativeErrorImp(&m_globalExec, funcProto, m_TypeErrorPrototype);
419     m_UriError = new NativeErrorImp(&m_globalExec, funcProto, m_UriErrorPrototype);
420 
421     // ECMA 15.3.4.1
422     funcProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Function, DontEnum);
423 
424     putNamedConstructor("Object", m_Object);
425     putNamedConstructor("Function", m_Function);
426     putNamedConstructor("Array", m_Array);
427     putNamedConstructor("Boolean", m_Boolean);
428     putNamedConstructor("String", m_String);
429     putNamedConstructor("Number", m_Number);
430     putNamedConstructor("Date", m_Date);
431     putNamedConstructor("RegExp", m_RegExp);
432     putNamedConstructor("Error", m_Error);
433     putNamedConstructor("EvalError", m_EvalError);
434     putNamedConstructor("RangeError", m_RangeError);
435     putNamedConstructor("ReferenceError", m_ReferenceError);
436     putNamedConstructor("SyntaxError", m_SyntaxError);
437     putNamedConstructor("TypeError", m_TypeError);
438     putNamedConstructor("URIError", m_UriError);
439 
440     // Set the constructorPropertyName property of all builtin constructors
441     objProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Object, DontEnum);
442     funcProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Function, DontEnum);
443     arrayProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Array, DontEnum);
444     booleanProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Boolean, DontEnum);
445     stringProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_String, DontEnum);
446     numberProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Number, DontEnum);
447     dateProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Date, DontEnum);
448     regexpProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_RegExp, DontEnum);
449     errorProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Error, DontEnum);
450     m_EvalErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_EvalError, DontEnum);
451     m_RangeErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_RangeError, DontEnum);
452     m_ReferenceErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_ReferenceError, DontEnum);
453     m_SyntaxErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_SyntaxError, DontEnum);
454     m_TypeErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_TypeError, DontEnum);
455     m_UriErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_UriError, DontEnum);
456 
457     // built-in values
458     m_globalObject->put(&m_globalExec, "NaN",        jsNaN(), DontEnum | DontDelete | ReadOnly);
459     m_globalObject->put(&m_globalExec, "Infinity",   jsNumber(Inf), DontEnum | DontDelete | ReadOnly);
460     m_globalObject->put(&m_globalExec, "undefined",  jsUndefined(), DontEnum | DontDelete | ReadOnly);
461 
462     // built-in functions
463     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::Eval, 1, "eval"), DontEnum);
464     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::ParseInt, 2, "parseInt"), DontEnum);
465     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::ParseFloat, 1, "parseFloat"), DontEnum);
466     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::IsNaN, 1, "isNaN"), DontEnum);
467     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::IsFinite, 1, "isFinite"), DontEnum);
468     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::Escape, 1, "escape"), DontEnum);
469     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::UnEscape, 1, "unescape"), DontEnum);
470     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::DecodeURI, 1, "decodeURI"), DontEnum);
471     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::DecodeURIComponent, 1, "decodeURIComponent"), DontEnum);
472     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::EncodeURI, 1, "encodeURI"), DontEnum);
473     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::EncodeURIComponent, 1, "encodeURIComponent"), DontEnum);
474 #ifndef NDEBUG
475     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::KJSPrint, 1, "kjsprint"), DontEnum);
476 #endif
477 
478     // built-in objects
479     m_globalObject->put(&m_globalExec, "Math", new MathObjectImp(&m_globalExec, objProto), DontEnum);
480     m_globalObject->put(&m_globalExec, "JSON", new JSONObjectImp(&m_globalExec, objProto), DontEnum);
481 }
482 
globalExec()483 ExecState *Interpreter::globalExec()
484 {
485     return &m_globalExec;
486 }
487 
setGlobalPackage(Package * p)488 void Interpreter::setGlobalPackage(Package *p)
489 {
490     globPkg = p;
491 }
492 
globalPackage()493 Package *Interpreter::globalPackage()
494 {
495     return globPkg;
496 }
497 
checkSyntax(const UString & sourceURL,int startingLineNumber,const UString & code)498 Completion Interpreter::checkSyntax(const UString &sourceURL, int startingLineNumber, const UString &code)
499 {
500     return checkSyntax(sourceURL, startingLineNumber, code.data(), code.size());
501 }
502 
checkSyntax(const UString & sourceURL,int startingLineNumber,const UChar * code,int codeLength)503 Completion Interpreter::checkSyntax(const UString &sourceURL, int startingLineNumber, const UChar *code, int codeLength)
504 {
505     JSLock lock;
506 
507     int errLine;
508     UString errMsg;
509     RefPtr<ProgramNode> progNode = parser().parseProgram(sourceURL, startingLineNumber, code, codeLength, nullptr, &errLine, &errMsg);
510     if (!progNode) {
511         return Completion(Throw, Error::create(&m_globalExec, SyntaxError, errMsg, errLine, 0, sourceURL));
512     }
513     return Completion(Normal);
514 }
515 
evaluate(const UString & sourceURL,int startingLineNumber,const UString & code,JSValue * thisV)516 Completion Interpreter::evaluate(const UString &sourceURL, int startingLineNumber, const UString &code, JSValue *thisV)
517 {
518     return evaluate(sourceURL, startingLineNumber, code.data(), code.size(), thisV);
519 }
520 
evaluate(const UString & sourceURL,int startingLineNumber,const UChar * code,int codeLength,JSValue * thisV)521 Completion Interpreter::evaluate(const UString &sourceURL, int startingLineNumber, const UChar *code, int codeLength, JSValue *thisV)
522 {
523     JSLock lock;
524 
525     // prevent against infinite recursion
526     if (m_recursion >= 20) {
527         return Completion(Throw, Error::create(&m_globalExec, GeneralError, "Recursion too deep"));
528     }
529 
530     // parse the source code
531     int sourceId;
532     int errLine;
533     UString errMsg;
534     RefPtr<ProgramNode> progNode = parser().parseProgram(sourceURL, startingLineNumber, code, codeLength, &sourceId, &errLine, &errMsg);
535 
536     // notify debugger that source has been parsed
537     if (m_debugger) {
538         m_debugger->reportSourceParsed(&m_globalExec, progNode.get(), sourceId, sourceURL,
539                                        UString(code, codeLength), startingLineNumber, errLine, errMsg);
540     }
541 
542     // no program node means a syntax error occurred
543     if (!progNode) {
544         Completion res(Throw, Error::create(&m_globalExec, SyntaxError, errMsg, errLine, sourceId, sourceURL));
545         if (m_debugger) {
546             m_debugger->reportException(&m_globalExec, res.value());
547         }
548 
549         if (shouldPrintExceptions()) {
550             printException(res, sourceURL);
551         }
552         return res;
553     }
554 
555     m_globalExec.clearException();
556 
557     m_recursion++;
558 
559     JSGlobalObject *globalObj = m_globalObject;
560     JSObject       *thisObj   = globalObj;
561 
562     // "this" must be an object... use same rules as Function.prototype.apply()
563     if (thisV && !JSValue::isUndefinedOrNull(thisV)) {
564         thisObj = JSValue::toObject(thisV, &m_globalExec);
565     }
566 
567     Completion res;
568     if (m_globalExec.hadException())
569         // the thisV->toObject() conversion above might have thrown an exception - if so, propagate it
570     {
571         res = Completion(Throw, m_globalExec.exception());
572     } else {
573         // execute the code
574         InterpreterExecState newExec(this, globalObj, thisObj, progNode.get());
575 
576         if (m_debugger && !m_debugger->enterContext(&newExec, sourceId, startingLineNumber, nullptr, List::empty())) {
577             // debugger requested we stop execution.
578             m_debugger->imp()->abort();
579             return Completion(Break);
580         }
581 
582         progNode->processDecls(&newExec);
583         res = progNode->execute(&newExec);
584 
585         if (m_debugger && !m_debugger->exitContext(&newExec, sourceId, startingLineNumber, nullptr)) {
586             // debugger requested we stop execution.
587             m_debugger->imp()->abort();
588             return Completion(Break);
589         }
590     }
591 
592     m_recursion--;
593 
594     if (shouldPrintExceptions() && res.complType() == Throw) {
595         printException(res, sourceURL);
596     }
597 
598     return res;
599 }
600 
normalizeCode(const UString & codeIn,UString * codeOut,int * errLine,UString * errMsg)601 bool Interpreter::normalizeCode(const UString &codeIn, UString *codeOut,
602                                 int *errLine, UString *errMsg)
603 {
604     assert(codeOut);
605     RefPtr<ProgramNode> progNode = parser().parseProgram("", // sourceURL
606                                    0, // line
607                                    codeIn.data(),
608                                    codeIn.size(),
609                                    nullptr, // &sourceId
610                                    errLine, errMsg);
611     if (progNode) {
612         *codeOut = progNode->toString();
613         return true;
614     } else {
615         return false;
616     }
617 }
618 
builtinObject() const619 JSObject *Interpreter::builtinObject() const
620 {
621     return m_Object;
622 }
623 
builtinFunction() const624 JSObject *Interpreter::builtinFunction() const
625 {
626     return m_Function;
627 }
628 
builtinArray() const629 JSObject *Interpreter::builtinArray() const
630 {
631     return m_Array;
632 }
633 
builtinBoolean() const634 JSObject *Interpreter::builtinBoolean() const
635 {
636     return m_Boolean;
637 }
638 
builtinString() const639 JSObject *Interpreter::builtinString() const
640 {
641     return m_String;
642 }
643 
builtinNumber() const644 JSObject *Interpreter::builtinNumber() const
645 {
646     return m_Number;
647 }
648 
builtinDate() const649 JSObject *Interpreter::builtinDate() const
650 {
651     return m_Date;
652 }
653 
builtinRegExp() const654 JSObject *Interpreter::builtinRegExp() const
655 {
656     return m_RegExp;
657 }
658 
builtinError() const659 JSObject *Interpreter::builtinError() const
660 {
661     return m_Error;
662 }
663 
builtinObjectPrototype() const664 JSObject *Interpreter::builtinObjectPrototype() const
665 {
666     return m_ObjectPrototype;
667 }
668 
builtinFunctionPrototype() const669 JSObject *Interpreter::builtinFunctionPrototype() const
670 {
671     return m_FunctionPrototype;
672 }
673 
builtinArrayPrototype() const674 JSObject *Interpreter::builtinArrayPrototype() const
675 {
676     return m_ArrayPrototype;
677 }
678 
builtinBooleanPrototype() const679 JSObject *Interpreter::builtinBooleanPrototype() const
680 {
681     return m_BooleanPrototype;
682 }
683 
builtinStringPrototype() const684 JSObject *Interpreter::builtinStringPrototype() const
685 {
686     return m_StringPrototype;
687 }
688 
builtinNumberPrototype() const689 JSObject *Interpreter::builtinNumberPrototype() const
690 {
691     return m_NumberPrototype;
692 }
693 
builtinDatePrototype() const694 JSObject *Interpreter::builtinDatePrototype() const
695 {
696     return m_DatePrototype;
697 }
698 
builtinRegExpPrototype() const699 JSObject *Interpreter::builtinRegExpPrototype() const
700 {
701     return m_RegExpPrototype;
702 }
703 
builtinErrorPrototype() const704 JSObject *Interpreter::builtinErrorPrototype() const
705 {
706     return m_ErrorPrototype;
707 }
708 
builtinEvalError() const709 JSObject *Interpreter::builtinEvalError() const
710 {
711     return m_EvalError;
712 }
713 
builtinRangeError() const714 JSObject *Interpreter::builtinRangeError() const
715 {
716     return m_RangeError;
717 }
718 
builtinReferenceError() const719 JSObject *Interpreter::builtinReferenceError() const
720 {
721     return m_ReferenceError;
722 }
723 
builtinSyntaxError() const724 JSObject *Interpreter::builtinSyntaxError() const
725 {
726     return m_SyntaxError;
727 }
728 
builtinTypeError() const729 JSObject *Interpreter::builtinTypeError() const
730 {
731     return m_TypeError;
732 }
733 
builtinURIError() const734 JSObject *Interpreter::builtinURIError() const
735 {
736     return m_UriError;
737 }
738 
builtinEvalErrorPrototype() const739 JSObject *Interpreter::builtinEvalErrorPrototype() const
740 {
741     return m_EvalErrorPrototype;
742 }
743 
builtinRangeErrorPrototype() const744 JSObject *Interpreter::builtinRangeErrorPrototype() const
745 {
746     return m_RangeErrorPrototype;
747 }
748 
builtinReferenceErrorPrototype() const749 JSObject *Interpreter::builtinReferenceErrorPrototype() const
750 {
751     return m_ReferenceErrorPrototype;
752 }
753 
builtinSyntaxErrorPrototype() const754 JSObject *Interpreter::builtinSyntaxErrorPrototype() const
755 {
756     return m_SyntaxErrorPrototype;
757 }
758 
builtinTypeErrorPrototype() const759 JSObject *Interpreter::builtinTypeErrorPrototype() const
760 {
761     return m_TypeErrorPrototype;
762 }
763 
builtinURIErrorPrototype() const764 JSObject *Interpreter::builtinURIErrorPrototype() const
765 {
766     return m_UriErrorPrototype;
767 }
768 
collect()769 bool Interpreter::collect()
770 {
771     return Collector::collect();
772 }
773 
mark(bool)774 void Interpreter::mark(bool)
775 {
776     if (m_execState) {
777         m_execState->mark();
778     }
779     if (m_globalObject && !m_globalObject->marked()) {
780         m_globalObject->mark();
781     }
782     if (m_globalExec.exception() && !JSValue::marked(m_globalExec.exception())) {
783         JSValue::mark(m_globalExec.exception());
784     }
785 
786     // Do not let cached activations survive the GC; as they have an unfortunate
787     // tendenacy to pin blocks, increasing their number and hence spreading out
788     // the objects somewhat
789     m_numCachedActivations = 0;
790 }
791 
markSourceCachedObjects()792 void Interpreter::markSourceCachedObjects()
793 {
794     markInternedStringsTable();
795 }
796 
797 #ifdef KJS_DEBUG_MEM
finalCheck()798 void Interpreter::finalCheck()
799 {
800     fprintf(stderr, "Interpreter::finalCheck()\n");
801     Collector::collect();
802 
803 //  Node::finalCheck();
804     Collector::finalCheck();
805 }
806 #endif
807 
808 static bool printExceptions = false;
809 
shouldPrintExceptions()810 bool Interpreter::shouldPrintExceptions()
811 {
812     return printExceptions;
813 }
814 
setShouldPrintExceptions(bool print)815 void Interpreter::setShouldPrintExceptions(bool print)
816 {
817     printExceptions = print;
818 }
819 
printException(const Completion & c,const UString & sourceURL)820 void Interpreter::printException(const Completion &c, const UString &sourceURL)
821 {
822     JSLock lock;
823     ExecState *exec = globalExec();
824     CString f = sourceURL.UTF8String();
825     CString message = JSValue::toObject(c.value(), exec)->toString(exec).UTF8String();
826     int line = JSValue::toUInt32(JSValue::toObject(c.value(), exec)->get(exec, "line"), exec);
827 #if PLATFORM(WIN_OS)
828     printf("%s line %d: %s\n", f.c_str(), line, message.c_str());
829 #else
830     printf("[%d] %s line %d: %s\n", getpid(), f.c_str(), line, message.c_str());
831 #endif
832 }
833 
834 // bindings are OS X WebKit-only for now
835 #if USE(BINDINGS)
createLanguageInstanceForValue(ExecState * exec,int language,JSObject * value,const Bindings::RootObject * origin,const Bindings::RootObject * current)836 void *Interpreter::createLanguageInstanceForValue(ExecState *exec, int language, JSObject *value, const Bindings::RootObject *origin, const Bindings::RootObject *current)
837 {
838     return Bindings::Instance::createLanguageInstanceForValue(exec, (Bindings::Instance::BindingLanguage)language, value, origin, current);
839 }
840 #endif
841 
saveBuiltins(SavedBuiltins & builtins) const842 void Interpreter::saveBuiltins(SavedBuiltins &builtins) const
843 {
844     if (!builtins._internal) {
845         builtins._internal = new SavedBuiltinsInternal;
846     }
847 
848     builtins._internal->m_Object = m_Object;
849     builtins._internal->m_Function = m_Function;
850     builtins._internal->m_Array = m_Array;
851     builtins._internal->m_Boolean = m_Boolean;
852     builtins._internal->m_String = m_String;
853     builtins._internal->m_Number = m_Number;
854     builtins._internal->m_Date = m_Date;
855     builtins._internal->m_RegExp = m_RegExp;
856     builtins._internal->m_Error = m_Error;
857 
858     builtins._internal->m_ObjectPrototype = m_ObjectPrototype;
859     builtins._internal->m_FunctionPrototype = m_FunctionPrototype;
860     builtins._internal->m_ArrayPrototype = m_ArrayPrototype;
861     builtins._internal->m_BooleanPrototype = m_BooleanPrototype;
862     builtins._internal->m_StringPrototype = m_StringPrototype;
863     builtins._internal->m_NumberPrototype = m_NumberPrototype;
864     builtins._internal->m_DatePrototype = m_DatePrototype;
865     builtins._internal->m_RegExpPrototype = m_RegExpPrototype;
866     builtins._internal->m_ErrorPrototype = m_ErrorPrototype;
867 
868     builtins._internal->m_EvalError = m_EvalError;
869     builtins._internal->m_RangeError = m_RangeError;
870     builtins._internal->m_ReferenceError = m_ReferenceError;
871     builtins._internal->m_SyntaxError = m_SyntaxError;
872     builtins._internal->m_TypeError = m_TypeError;
873     builtins._internal->m_UriError = m_UriError;
874 
875     builtins._internal->m_EvalErrorPrototype = m_EvalErrorPrototype;
876     builtins._internal->m_RangeErrorPrototype = m_RangeErrorPrototype;
877     builtins._internal->m_ReferenceErrorPrototype = m_ReferenceErrorPrototype;
878     builtins._internal->m_SyntaxErrorPrototype = m_SyntaxErrorPrototype;
879     builtins._internal->m_TypeErrorPrototype = m_TypeErrorPrototype;
880     builtins._internal->m_UriErrorPrototype = m_UriErrorPrototype;
881 }
882 
restoreBuiltins(const SavedBuiltins & builtins)883 void Interpreter::restoreBuiltins(const SavedBuiltins &builtins)
884 {
885     if (!builtins._internal) {
886         return;
887     }
888 
889     m_Object = builtins._internal->m_Object;
890     m_Function = builtins._internal->m_Function;
891     m_Array = builtins._internal->m_Array;
892     m_Boolean = builtins._internal->m_Boolean;
893     m_String = builtins._internal->m_String;
894     m_Number = builtins._internal->m_Number;
895     m_Date = builtins._internal->m_Date;
896     m_RegExp = builtins._internal->m_RegExp;
897     m_Error = builtins._internal->m_Error;
898 
899     m_ObjectPrototype = builtins._internal->m_ObjectPrototype;
900     m_FunctionPrototype = builtins._internal->m_FunctionPrototype;
901     m_ArrayPrototype = builtins._internal->m_ArrayPrototype;
902     m_BooleanPrototype = builtins._internal->m_BooleanPrototype;
903     m_StringPrototype = builtins._internal->m_StringPrototype;
904     m_NumberPrototype = builtins._internal->m_NumberPrototype;
905     m_DatePrototype = builtins._internal->m_DatePrototype;
906     m_RegExpPrototype = builtins._internal->m_RegExpPrototype;
907     m_ErrorPrototype = builtins._internal->m_ErrorPrototype;
908 
909     m_EvalError = builtins._internal->m_EvalError;
910     m_RangeError = builtins._internal->m_RangeError;
911     m_ReferenceError = builtins._internal->m_ReferenceError;
912     m_SyntaxError = builtins._internal->m_SyntaxError;
913     m_TypeError = builtins._internal->m_TypeError;
914     m_UriError = builtins._internal->m_UriError;
915 
916     m_EvalErrorPrototype = builtins._internal->m_EvalErrorPrototype;
917     m_RangeErrorPrototype = builtins._internal->m_RangeErrorPrototype;
918     m_ReferenceErrorPrototype = builtins._internal->m_ReferenceErrorPrototype;
919     m_SyntaxErrorPrototype = builtins._internal->m_SyntaxErrorPrototype;
920     m_TypeErrorPrototype = builtins._internal->m_TypeErrorPrototype;
921     m_UriErrorPrototype = builtins._internal->m_UriErrorPrototype;
922 }
923 
startTimeoutCheck()924 void Interpreter::startTimeoutCheck()
925 {
926     if (!m_timeoutChecker) {
927         m_timeoutChecker = new TimeoutChecker;
928     }
929 
930     m_timeoutChecker->startTimeoutCheck(this);
931 }
932 
stopTimeoutCheck()933 void Interpreter::stopTimeoutCheck()
934 {
935     ASSERT(m_timeoutChecker);
936 
937     m_timeoutChecker->stopTimeoutCheck(this);
938 }
939 
restartTimeoutCheck()940 void Interpreter::restartTimeoutCheck()
941 {
942     if (!m_timeoutChecker || !m_startTimeoutCheckCount) {
943         return;
944     }
945 
946     m_timedOut = false;
947     m_timeoutChecker->stopTimeoutCheck(this);
948     m_timeoutChecker->startTimeoutCheck(this);
949 }
950 
pauseTimeoutCheck()951 void Interpreter::pauseTimeoutCheck()
952 {
953     ASSERT(m_timeoutChecker);
954 
955     m_timeoutChecker->pauseTimeoutCheck(this);
956 }
957 
resumeTimeoutCheck()958 void Interpreter::resumeTimeoutCheck()
959 {
960     ASSERT(m_timeoutChecker);
961 
962     m_timeoutChecker->resumeTimeoutCheck(this);
963 }
964 
handleTimeout()965 bool Interpreter::handleTimeout()
966 {
967     m_timedOut = false;
968 
969     pauseTimeoutCheck();
970     bool retval = shouldInterruptScript();
971     resumeTimeoutCheck();
972 
973     return retval;
974 }
975 
976 Interpreter::InternedStringsTable *Interpreter::s_internedStrings;
977 
initInternedStringsTable()978 void Interpreter::initInternedStringsTable()
979 {
980     if (!s_internedStrings) {
981         s_internedStrings = new InternedStringsTable();
982     }
983 }
984 
internString(const UString & literal)985 StringImp *Interpreter::internString(const UString &literal)
986 {
987     InternedStringsTable::iterator i = s_internedStrings->find(literal.rep());
988 
989     if (i == s_internedStrings->end()) {
990         // Need to add. Note: we can't use ->add() above to avoid a double-hash
991         // as creation of a StringImp may cause a GC, which in turn may
992         // rearrange the hashtable, invalidating the iterator.
993         StringImp *si = static_cast<StringImp *>(jsOwnedString(literal));
994         s_internedStrings->add(literal.rep(), std::make_pair(si, 1));
995         return si;
996     } else {
997         ++i.values()->second; // just bump the ref count
998         return i.values()->first;
999     }
1000 }
1001 
releaseInternedString(const UString & literal)1002 void Interpreter::releaseInternedString(const UString &literal)
1003 {
1004     InternedStringsTable::iterator i = s_internedStrings->find(literal.rep());
1005 
1006     --i.values()->second;
1007     if (i.values()->second == 0) {
1008         s_internedStrings->remove(i);
1009     }
1010 }
1011 
markInternedStringsTable()1012 void Interpreter::markInternedStringsTable()
1013 {
1014     for (InternedStringsTable::iterator i = s_internedStrings->begin();
1015             i != s_internedStrings->end(); ++i) {
1016         // Note: the StringImp* may be null here if we got called in the middle
1017         // of internString.
1018         if (i.values()->first && !i.values()->first->marked()) {
1019             i.values()->first->mark();
1020         }
1021     }
1022 }
1023 
SavedBuiltins()1024 SavedBuiltins::SavedBuiltins() :
1025     _internal(nullptr)
1026 {
1027 }
1028 
~SavedBuiltins()1029 SavedBuiltins::~SavedBuiltins()
1030 {
1031     delete _internal;
1032 }
1033 
UnicodeSupport()1034 UnicodeSupport::UnicodeSupport()
1035 {
1036 }
1037 
setIdentStartChecker(bool (* f)(int c))1038 void UnicodeSupport::setIdentStartChecker(bool (*f)(int c))
1039 {
1040     Lexer::setIdentStartChecker(f);
1041 }
1042 
setIdentPartChecker(bool (* f)(int c))1043 void UnicodeSupport::setIdentPartChecker(bool (*f)(int c))
1044 {
1045     Lexer::setIdentPartChecker(f);
1046 }
1047 
setToLowerFunction(StringConversionFunction f)1048 void UnicodeSupport::setToLowerFunction(StringConversionFunction f)
1049 {
1050     StringProtoFunc::setToLowerFunction(f);
1051 }
1052 
setToUpperFunction(StringConversionFunction f)1053 void UnicodeSupport::setToUpperFunction(StringConversionFunction f)
1054 {
1055     StringProtoFunc::setToUpperFunction(f);
1056 }
1057 
1058 }
1059 
1060