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