File indexing completed on 2024-05-12 15:43:23
0001 /* 0002 * This file is part of the KDE libraries 0003 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 0004 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 0005 * Copyright (C) 2003 Apple Computer, Inc. 0006 * Copyright (C) 2008, 2009 Maksim Orlovich (maksim@kde.org) 0007 * 0008 * This library is free software; you can redistribute it and/or 0009 * modify it under the terms of the GNU Library General Public 0010 * License as published by the Free Software Foundation; either 0011 * version 2 of the License, or (at your option) any later version. 0012 * 0013 * This library is distributed in the hope that it will be useful, 0014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0016 * Library General Public License for more details. 0017 * 0018 * You should have received a copy of the GNU Library General Public License 0019 * along with this library; see the file COPYING.LIB. If not, write to 0020 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0021 * Boston, MA 02110-1301, USA. 0022 * 0023 */ 0024 0025 #include "interpreter.h" 0026 0027 #include "SavedBuiltins.h" 0028 #include "array_object.h" 0029 #include "bool_object.h" 0030 #include "collector.h" 0031 #include "date_object.h" 0032 #include "debugger.h" 0033 #include "error_object.h" 0034 #include "function_object.h" 0035 #include "internal.h" 0036 #include "math_object.h" 0037 #include "nodes.h" 0038 #include "number_object.h" 0039 #include "object.h" 0040 #include "object_object.h" 0041 #include "operations.h" 0042 #include "regexp_object.h" 0043 #include "string_object.h" 0044 #include "lexer.h" 0045 #include "json_object.h" 0046 0047 #if USE(BINDINGS) 0048 #include "runtime.h" 0049 #endif 0050 0051 #if defined _WIN32 || defined _WIN64 0052 #define HAVE_SYS_TIME_H 0 // no setitimer in kdewin32 0053 #endif 0054 #if HAVE_SYS_TIME_H 0055 #include <sys/time.h> 0056 #endif 0057 0058 #include <assert.h> 0059 #include <cstdlib> 0060 #include <math.h> 0061 #include <signal.h> 0062 #include <stdio.h> 0063 #if HAVE_UNISTD_H 0064 #include <unistd.h> 0065 #endif 0066 0067 namespace KJS 0068 { 0069 0070 class TimeoutChecker 0071 { 0072 public: 0073 void startTimeoutCheck(Interpreter *); 0074 void stopTimeoutCheck(Interpreter *); 0075 void pauseTimeoutCheck(Interpreter *); 0076 void resumeTimeoutCheck(Interpreter *); 0077 0078 private: 0079 #if HAVE_SYS_TIME_H 0080 static Interpreter *s_executingInterpreter; 0081 static void alarmHandler(int); 0082 0083 Interpreter *m_oldInterpreter; 0084 itimerval m_oldtv; 0085 itimerval m_pausetv; 0086 void (*m_oldAlarmHandler)(int); 0087 #endif 0088 }; 0089 0090 #if HAVE_SYS_TIME_H 0091 Interpreter *TimeoutChecker::s_executingInterpreter = nullptr; 0092 #endif 0093 0094 void TimeoutChecker::startTimeoutCheck(Interpreter *interpreter) 0095 { 0096 if (!interpreter->m_timeoutTime) { 0097 return; 0098 } 0099 0100 interpreter->m_startTimeoutCheckCount++; 0101 0102 #if HAVE_SYS_TIME_H 0103 if (s_executingInterpreter == interpreter) { 0104 return; 0105 } 0106 0107 // Block signals 0108 m_oldAlarmHandler = signal(SIGALRM, SIG_IGN); 0109 0110 m_oldInterpreter = s_executingInterpreter; 0111 s_executingInterpreter = interpreter; 0112 0113 itimerval tv = { 0114 { time_t(interpreter->m_timeoutTime / 1000), 0115 suseconds_t((interpreter->m_timeoutTime % 1000) * 1000) }, 0116 { time_t(interpreter->m_timeoutTime / 1000), 0117 suseconds_t((interpreter->m_timeoutTime % 1000) * 1000) } 0118 }; 0119 setitimer(ITIMER_REAL, &tv, &m_oldtv); 0120 0121 // Unblock signals 0122 signal(SIGALRM, alarmHandler); 0123 #endif 0124 } 0125 0126 void TimeoutChecker::stopTimeoutCheck(Interpreter *interpreter) 0127 { 0128 if (!interpreter->m_timeoutTime) { 0129 return; 0130 } 0131 0132 ASSERT(interpreter->m_startTimeoutCheckCount > 0); 0133 0134 interpreter->m_startTimeoutCheckCount--; 0135 0136 if (interpreter->m_startTimeoutCheckCount != 0) { 0137 return; 0138 } 0139 0140 #if HAVE_SYS_TIME_H 0141 signal(SIGALRM, SIG_IGN); 0142 0143 s_executingInterpreter = m_oldInterpreter; 0144 0145 setitimer(ITIMER_REAL, &m_oldtv, nullptr); 0146 signal(SIGALRM, m_oldAlarmHandler); 0147 #endif 0148 } 0149 0150 #if HAVE_SYS_TIME_H 0151 void TimeoutChecker::alarmHandler(int) 0152 { 0153 s_executingInterpreter->m_timedOut = true; 0154 } 0155 #endif 0156 0157 void TimeoutChecker::pauseTimeoutCheck(Interpreter *interpreter) 0158 { 0159 if (interpreter->m_startTimeoutCheckCount == 0) { 0160 return; 0161 } 0162 0163 #if HAVE_SYS_TIME_H 0164 ASSERT(interpreter == s_executingInterpreter); 0165 0166 void (*currentSignalHandler)(int); 0167 0168 // Block signal 0169 currentSignalHandler = signal(SIGALRM, SIG_IGN); 0170 0171 if (currentSignalHandler != alarmHandler) { 0172 signal(SIGALRM, currentSignalHandler); 0173 return; 0174 } 0175 0176 getitimer(ITIMER_REAL, &m_pausetv); 0177 #endif 0178 0179 interpreter->m_pauseTimeoutCheckCount++; 0180 } 0181 0182 void TimeoutChecker::resumeTimeoutCheck(Interpreter *interpreter) 0183 { 0184 if (interpreter->m_startTimeoutCheckCount == 0) { 0185 return; 0186 } 0187 0188 #if HAVE_SYS_TIME_H 0189 ASSERT(interpreter == s_executingInterpreter); 0190 #endif 0191 0192 interpreter->m_pauseTimeoutCheckCount--; 0193 0194 if (interpreter->m_pauseTimeoutCheckCount != 0) { 0195 return; 0196 } 0197 0198 #if HAVE_SYS_TIME_H 0199 void (*currentSignalHandler)(int); 0200 0201 // Check so we have the right handler 0202 currentSignalHandler = signal(SIGALRM, SIG_IGN); 0203 0204 if (currentSignalHandler != SIG_IGN) { 0205 signal(SIGALRM, currentSignalHandler); 0206 return; 0207 } 0208 0209 setitimer(ITIMER_REAL, &m_pausetv, nullptr); 0210 0211 // Unblock signal 0212 currentSignalHandler = signal(SIGALRM, alarmHandler); 0213 #endif 0214 } 0215 0216 Interpreter *Interpreter::s_hook = nullptr; 0217 0218 Interpreter::Interpreter(JSGlobalObject *globalObject) 0219 : m_globalObject(globalObject), 0220 m_globalExec(this, globalObject), 0221 globPkg(nullptr) 0222 { 0223 init(); 0224 } 0225 0226 Interpreter::Interpreter() 0227 : m_globalObject(new JSGlobalObject()), 0228 m_globalExec(this, m_globalObject), 0229 globPkg(nullptr) 0230 { 0231 init(); 0232 } 0233 0234 void Interpreter::init() 0235 { 0236 JSLock lock; 0237 0238 initInternedStringsTable(); 0239 0240 m_refCount = 0; 0241 m_timeoutTime = 0; 0242 m_recursion = 0; 0243 m_debugger = nullptr; 0244 m_execState = nullptr; 0245 m_timedOut = false; 0246 m_timeoutChecker = nullptr; 0247 m_startTimeoutCheckCount = 0; 0248 m_pauseTimeoutCheckCount = 0; 0249 m_compatMode = NativeMode; 0250 0251 const int initialStackSize = 8192; 0252 stackBase = (unsigned char *)std::malloc(initialStackSize); 0253 stackPtr = stackBase; 0254 stackEnd = stackBase + initialStackSize; 0255 0256 m_numCachedActivations = 0; 0257 0258 m_globalObject->setInterpreter(this); 0259 0260 if (s_hook) { 0261 prev = s_hook; 0262 next = s_hook->next; 0263 s_hook->next->prev = this; 0264 s_hook->next = this; 0265 } else { 0266 // This is the first interpreter 0267 s_hook = next = prev = this; 0268 } 0269 0270 initGlobalObject(); 0271 } 0272 0273 Interpreter::~Interpreter() 0274 { 0275 JSLock lock; 0276 0277 ASSERT(m_startTimeoutCheckCount == 0); 0278 ASSERT(m_pauseTimeoutCheckCount == 0); 0279 0280 delete m_timeoutChecker; 0281 0282 if (m_debugger) { 0283 m_debugger->detach(this); 0284 } 0285 0286 std::free(stackBase); 0287 0288 next->prev = prev; 0289 prev->next = next; 0290 s_hook = next; 0291 if (s_hook == this) { 0292 // This was the last interpreter 0293 s_hook = nullptr; 0294 } 0295 0296 m_globalObject->setInterpreter(nullptr); 0297 } 0298 0299 unsigned char *Interpreter::extendStack(size_t needed) 0300 { 0301 unsigned char *oldBase = stackBase; // needed for fixing up localStores 0302 0303 size_t curSize = stackEnd - stackBase; 0304 size_t avail = stackEnd - stackPtr; 0305 size_t extra = needed - avail; 0306 0307 if (extra < 8192) { 0308 extra = 8192; 0309 } 0310 size_t newSize = curSize + extra; 0311 0312 //printf("Grow stack:%d -> %d\n", curSize, newSize); 0313 0314 stackBase = (unsigned char *)std::malloc(newSize); // Not realloc since we need the old stuff 0315 // ### seems optimizeable 0316 std::memcpy(stackBase, oldBase, curSize); 0317 stackPtr = stackBase + (stackPtr - oldBase); 0318 stackEnd = stackBase + newSize; 0319 0320 // Now go through and fix up activations.. 0321 ExecState *e = m_execState; 0322 while (e) { 0323 if (e->codeType() == FunctionCode) { 0324 ActivationImp *act = static_cast<ActivationImp *>(e->activationObject()); 0325 if (act->localStorage) { 0326 act->localStorage = (LocalStorageEntry *) 0327 (stackBase + ((unsigned char *)act->localStorage - oldBase)); 0328 e->updateLocalStorage(act->localStorage); 0329 } 0330 } 0331 0332 e = e->savedExecState(); 0333 } 0334 0335 std::free(oldBase); 0336 0337 return stackAlloc(needed); 0338 } 0339 0340 void Interpreter::recycleActivation(ActivationImp *act) 0341 { 0342 ASSERT(act->localStorage == nullptr); // Should not refer to anything by now 0343 if (m_numCachedActivations >= MaxCachedActivations) { 0344 return; 0345 } 0346 0347 act->clearProperties(); 0348 m_cachedActivations[m_numCachedActivations] = act; 0349 ++m_numCachedActivations; 0350 } 0351 0352 JSGlobalObject *Interpreter::globalObject() const 0353 { 0354 return m_globalObject; 0355 } 0356 0357 void Interpreter::putNamedConstructor(const char *name, JSObject *value) 0358 { 0359 assert(value->implementsCall()); 0360 Identifier i(name); 0361 m_globalObject->put(&m_globalExec, i, value, DontEnum); 0362 static_cast<InternalFunctionImp *>(value)->setFunctionName(i); 0363 } 0364 0365 void Interpreter::initGlobalObject() 0366 { 0367 FunctionPrototype *funcProto = new FunctionPrototype(&m_globalExec); 0368 m_FunctionPrototype = funcProto; 0369 ObjectPrototype *objProto = new ObjectPrototype(&m_globalExec, funcProto); 0370 m_ObjectPrototype = objProto; 0371 funcProto->setPrototype(m_ObjectPrototype); 0372 0373 ArrayPrototype *arrayProto = new ArrayPrototype(&m_globalExec, objProto); 0374 m_ArrayPrototype = arrayProto; 0375 StringPrototype *stringProto = new StringPrototype(&m_globalExec, objProto); 0376 m_StringPrototype = stringProto; 0377 BooleanPrototype *booleanProto = new BooleanPrototype(&m_globalExec, objProto, funcProto); 0378 m_BooleanPrototype = booleanProto; 0379 NumberPrototype *numberProto = new NumberPrototype(&m_globalExec, objProto, funcProto); 0380 m_NumberPrototype = numberProto; 0381 DatePrototype *dateProto = new DatePrototype(&m_globalExec, objProto); 0382 m_DatePrototype = dateProto; 0383 RegExpPrototype *regexpProto = new RegExpPrototype(&m_globalExec, objProto, funcProto); 0384 m_RegExpPrototype = regexpProto; 0385 ErrorPrototype *errorProto = new ErrorPrototype(&m_globalExec, objProto, funcProto); 0386 m_ErrorPrototype = errorProto; 0387 0388 JSObject *o = m_globalObject; 0389 while (JSValue::isObject(o->prototype())) { 0390 o = static_cast<JSObject *>(o->prototype()); 0391 } 0392 o->setPrototype(m_ObjectPrototype); 0393 0394 // Constructors (Object, Array, etc.) 0395 m_Object = new ObjectObjectImp(&m_globalExec, objProto, funcProto); 0396 m_Function = new FunctionObjectImp(&m_globalExec, funcProto); 0397 m_Array = new ArrayObjectImp(&m_globalExec, funcProto, arrayProto); 0398 m_String = new StringObjectImp(&m_globalExec, funcProto, stringProto); 0399 m_Boolean = new BooleanObjectImp(&m_globalExec, funcProto, booleanProto); 0400 m_Number = new NumberObjectImp(&m_globalExec, funcProto, numberProto); 0401 m_Date = new DateObjectImp(&m_globalExec, funcProto, dateProto); 0402 m_RegExp = new RegExpObjectImp(&m_globalExec, funcProto, regexpProto); 0403 m_Error = new ErrorObjectImp(&m_globalExec, funcProto, errorProto); 0404 0405 // Error object prototypes 0406 m_EvalErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, EvalError, "EvalError", "EvalError"); 0407 m_RangeErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, RangeError, "RangeError", "RangeError"); 0408 m_ReferenceErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, ReferenceError, "ReferenceError", "ReferenceError"); 0409 m_SyntaxErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, SyntaxError, "SyntaxError", "SyntaxError"); 0410 m_TypeErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, TypeError, "TypeError", "TypeError"); 0411 m_UriErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, URIError, "URIError", "URIError"); 0412 0413 // Error objects 0414 m_EvalError = new NativeErrorImp(&m_globalExec, funcProto, m_EvalErrorPrototype); 0415 m_RangeError = new NativeErrorImp(&m_globalExec, funcProto, m_RangeErrorPrototype); 0416 m_ReferenceError = new NativeErrorImp(&m_globalExec, funcProto, m_ReferenceErrorPrototype); 0417 m_SyntaxError = new NativeErrorImp(&m_globalExec, funcProto, m_SyntaxErrorPrototype); 0418 m_TypeError = new NativeErrorImp(&m_globalExec, funcProto, m_TypeErrorPrototype); 0419 m_UriError = new NativeErrorImp(&m_globalExec, funcProto, m_UriErrorPrototype); 0420 0421 // ECMA 15.3.4.1 0422 funcProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Function, DontEnum); 0423 0424 putNamedConstructor("Object", m_Object); 0425 putNamedConstructor("Function", m_Function); 0426 putNamedConstructor("Array", m_Array); 0427 putNamedConstructor("Boolean", m_Boolean); 0428 putNamedConstructor("String", m_String); 0429 putNamedConstructor("Number", m_Number); 0430 putNamedConstructor("Date", m_Date); 0431 putNamedConstructor("RegExp", m_RegExp); 0432 putNamedConstructor("Error", m_Error); 0433 putNamedConstructor("EvalError", m_EvalError); 0434 putNamedConstructor("RangeError", m_RangeError); 0435 putNamedConstructor("ReferenceError", m_ReferenceError); 0436 putNamedConstructor("SyntaxError", m_SyntaxError); 0437 putNamedConstructor("TypeError", m_TypeError); 0438 putNamedConstructor("URIError", m_UriError); 0439 0440 // Set the constructorPropertyName property of all builtin constructors 0441 objProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Object, DontEnum); 0442 funcProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Function, DontEnum); 0443 arrayProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Array, DontEnum); 0444 booleanProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Boolean, DontEnum); 0445 stringProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_String, DontEnum); 0446 numberProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Number, DontEnum); 0447 dateProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Date, DontEnum); 0448 regexpProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_RegExp, DontEnum); 0449 errorProto->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Error, DontEnum); 0450 m_EvalErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_EvalError, DontEnum); 0451 m_RangeErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_RangeError, DontEnum); 0452 m_ReferenceErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_ReferenceError, DontEnum); 0453 m_SyntaxErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_SyntaxError, DontEnum); 0454 m_TypeErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_TypeError, DontEnum); 0455 m_UriErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_UriError, DontEnum); 0456 0457 // built-in values 0458 m_globalObject->put(&m_globalExec, "NaN", jsNaN(), DontEnum | DontDelete | ReadOnly); 0459 m_globalObject->put(&m_globalExec, "Infinity", jsNumber(Inf), DontEnum | DontDelete | ReadOnly); 0460 m_globalObject->put(&m_globalExec, "undefined", jsUndefined(), DontEnum | DontDelete | ReadOnly); 0461 0462 // built-in functions 0463 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::Eval, 1, "eval"), DontEnum); 0464 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::ParseInt, 2, "parseInt"), DontEnum); 0465 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::ParseFloat, 1, "parseFloat"), DontEnum); 0466 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::IsNaN, 1, "isNaN"), DontEnum); 0467 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::IsFinite, 1, "isFinite"), DontEnum); 0468 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::Escape, 1, "escape"), DontEnum); 0469 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::UnEscape, 1, "unescape"), DontEnum); 0470 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::DecodeURI, 1, "decodeURI"), DontEnum); 0471 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::DecodeURIComponent, 1, "decodeURIComponent"), DontEnum); 0472 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::EncodeURI, 1, "encodeURI"), DontEnum); 0473 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::EncodeURIComponent, 1, "encodeURIComponent"), DontEnum); 0474 #ifndef NDEBUG 0475 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::KJSPrint, 1, "kjsprint"), DontEnum); 0476 #endif 0477 0478 // built-in objects 0479 m_globalObject->put(&m_globalExec, "Math", new MathObjectImp(&m_globalExec, objProto), DontEnum); 0480 m_globalObject->put(&m_globalExec, "JSON", new JSONObjectImp(&m_globalExec, objProto), DontEnum); 0481 } 0482 0483 ExecState *Interpreter::globalExec() 0484 { 0485 return &m_globalExec; 0486 } 0487 0488 void Interpreter::setGlobalPackage(Package *p) 0489 { 0490 globPkg = p; 0491 } 0492 0493 Package *Interpreter::globalPackage() 0494 { 0495 return globPkg; 0496 } 0497 0498 Completion Interpreter::checkSyntax(const UString &sourceURL, int startingLineNumber, const UString &code) 0499 { 0500 return checkSyntax(sourceURL, startingLineNumber, code.data(), code.size()); 0501 } 0502 0503 Completion Interpreter::checkSyntax(const UString &sourceURL, int startingLineNumber, const UChar *code, int codeLength) 0504 { 0505 JSLock lock; 0506 0507 int errLine; 0508 UString errMsg; 0509 RefPtr<ProgramNode> progNode = parser().parseProgram(sourceURL, startingLineNumber, code, codeLength, nullptr, &errLine, &errMsg); 0510 if (!progNode) { 0511 return Completion(Throw, Error::create(&m_globalExec, SyntaxError, errMsg, errLine, 0, sourceURL)); 0512 } 0513 return Completion(Normal); 0514 } 0515 0516 Completion Interpreter::evaluate(const UString &sourceURL, int startingLineNumber, const UString &code, JSValue *thisV) 0517 { 0518 return evaluate(sourceURL, startingLineNumber, code.data(), code.size(), thisV); 0519 } 0520 0521 Completion Interpreter::evaluate(const UString &sourceURL, int startingLineNumber, const UChar *code, int codeLength, JSValue *thisV) 0522 { 0523 JSLock lock; 0524 0525 // prevent against infinite recursion 0526 if (m_recursion >= 20) { 0527 return Completion(Throw, Error::create(&m_globalExec, GeneralError, "Recursion too deep")); 0528 } 0529 0530 // parse the source code 0531 int sourceId; 0532 int errLine; 0533 UString errMsg; 0534 RefPtr<ProgramNode> progNode = parser().parseProgram(sourceURL, startingLineNumber, code, codeLength, &sourceId, &errLine, &errMsg); 0535 0536 // notify debugger that source has been parsed 0537 if (m_debugger) { 0538 m_debugger->reportSourceParsed(&m_globalExec, progNode.get(), sourceId, sourceURL, 0539 UString(code, codeLength), startingLineNumber, errLine, errMsg); 0540 } 0541 0542 // no program node means a syntax error occurred 0543 if (!progNode) { 0544 Completion res(Throw, Error::create(&m_globalExec, SyntaxError, errMsg, errLine, sourceId, sourceURL)); 0545 if (m_debugger) { 0546 m_debugger->reportException(&m_globalExec, res.value()); 0547 } 0548 0549 if (shouldPrintExceptions()) { 0550 printException(res, sourceURL); 0551 } 0552 return res; 0553 } 0554 0555 m_globalExec.clearException(); 0556 0557 m_recursion++; 0558 0559 JSGlobalObject *globalObj = m_globalObject; 0560 JSObject *thisObj = globalObj; 0561 0562 // "this" must be an object... use same rules as Function.prototype.apply() 0563 if (thisV && !JSValue::isUndefinedOrNull(thisV)) { 0564 thisObj = JSValue::toObject(thisV, &m_globalExec); 0565 } 0566 0567 Completion res; 0568 if (m_globalExec.hadException()) 0569 // the thisV->toObject() conversion above might have thrown an exception - if so, propagate it 0570 { 0571 res = Completion(Throw, m_globalExec.exception()); 0572 } else { 0573 // execute the code 0574 InterpreterExecState newExec(this, globalObj, thisObj, progNode.get()); 0575 0576 if (m_debugger && !m_debugger->enterContext(&newExec, sourceId, startingLineNumber, nullptr, List::empty())) { 0577 // debugger requested we stop execution. 0578 m_debugger->imp()->abort(); 0579 return Completion(Break); 0580 } 0581 0582 progNode->processDecls(&newExec); 0583 res = progNode->execute(&newExec); 0584 0585 if (m_debugger && !m_debugger->exitContext(&newExec, sourceId, startingLineNumber, nullptr)) { 0586 // debugger requested we stop execution. 0587 m_debugger->imp()->abort(); 0588 return Completion(Break); 0589 } 0590 } 0591 0592 m_recursion--; 0593 0594 if (shouldPrintExceptions() && res.complType() == Throw) { 0595 printException(res, sourceURL); 0596 } 0597 0598 return res; 0599 } 0600 0601 bool Interpreter::normalizeCode(const UString &codeIn, UString *codeOut, 0602 int *errLine, UString *errMsg) 0603 { 0604 assert(codeOut); 0605 RefPtr<ProgramNode> progNode = parser().parseProgram("", // sourceURL 0606 0, // line 0607 codeIn.data(), 0608 codeIn.size(), 0609 nullptr, // &sourceId 0610 errLine, errMsg); 0611 if (progNode) { 0612 *codeOut = progNode->toString(); 0613 return true; 0614 } else { 0615 return false; 0616 } 0617 } 0618 0619 JSObject *Interpreter::builtinObject() const 0620 { 0621 return m_Object; 0622 } 0623 0624 JSObject *Interpreter::builtinFunction() const 0625 { 0626 return m_Function; 0627 } 0628 0629 JSObject *Interpreter::builtinArray() const 0630 { 0631 return m_Array; 0632 } 0633 0634 JSObject *Interpreter::builtinBoolean() const 0635 { 0636 return m_Boolean; 0637 } 0638 0639 JSObject *Interpreter::builtinString() const 0640 { 0641 return m_String; 0642 } 0643 0644 JSObject *Interpreter::builtinNumber() const 0645 { 0646 return m_Number; 0647 } 0648 0649 JSObject *Interpreter::builtinDate() const 0650 { 0651 return m_Date; 0652 } 0653 0654 JSObject *Interpreter::builtinRegExp() const 0655 { 0656 return m_RegExp; 0657 } 0658 0659 JSObject *Interpreter::builtinError() const 0660 { 0661 return m_Error; 0662 } 0663 0664 JSObject *Interpreter::builtinObjectPrototype() const 0665 { 0666 return m_ObjectPrototype; 0667 } 0668 0669 JSObject *Interpreter::builtinFunctionPrototype() const 0670 { 0671 return m_FunctionPrototype; 0672 } 0673 0674 JSObject *Interpreter::builtinArrayPrototype() const 0675 { 0676 return m_ArrayPrototype; 0677 } 0678 0679 JSObject *Interpreter::builtinBooleanPrototype() const 0680 { 0681 return m_BooleanPrototype; 0682 } 0683 0684 JSObject *Interpreter::builtinStringPrototype() const 0685 { 0686 return m_StringPrototype; 0687 } 0688 0689 JSObject *Interpreter::builtinNumberPrototype() const 0690 { 0691 return m_NumberPrototype; 0692 } 0693 0694 JSObject *Interpreter::builtinDatePrototype() const 0695 { 0696 return m_DatePrototype; 0697 } 0698 0699 JSObject *Interpreter::builtinRegExpPrototype() const 0700 { 0701 return m_RegExpPrototype; 0702 } 0703 0704 JSObject *Interpreter::builtinErrorPrototype() const 0705 { 0706 return m_ErrorPrototype; 0707 } 0708 0709 JSObject *Interpreter::builtinEvalError() const 0710 { 0711 return m_EvalError; 0712 } 0713 0714 JSObject *Interpreter::builtinRangeError() const 0715 { 0716 return m_RangeError; 0717 } 0718 0719 JSObject *Interpreter::builtinReferenceError() const 0720 { 0721 return m_ReferenceError; 0722 } 0723 0724 JSObject *Interpreter::builtinSyntaxError() const 0725 { 0726 return m_SyntaxError; 0727 } 0728 0729 JSObject *Interpreter::builtinTypeError() const 0730 { 0731 return m_TypeError; 0732 } 0733 0734 JSObject *Interpreter::builtinURIError() const 0735 { 0736 return m_UriError; 0737 } 0738 0739 JSObject *Interpreter::builtinEvalErrorPrototype() const 0740 { 0741 return m_EvalErrorPrototype; 0742 } 0743 0744 JSObject *Interpreter::builtinRangeErrorPrototype() const 0745 { 0746 return m_RangeErrorPrototype; 0747 } 0748 0749 JSObject *Interpreter::builtinReferenceErrorPrototype() const 0750 { 0751 return m_ReferenceErrorPrototype; 0752 } 0753 0754 JSObject *Interpreter::builtinSyntaxErrorPrototype() const 0755 { 0756 return m_SyntaxErrorPrototype; 0757 } 0758 0759 JSObject *Interpreter::builtinTypeErrorPrototype() const 0760 { 0761 return m_TypeErrorPrototype; 0762 } 0763 0764 JSObject *Interpreter::builtinURIErrorPrototype() const 0765 { 0766 return m_UriErrorPrototype; 0767 } 0768 0769 bool Interpreter::collect() 0770 { 0771 return Collector::collect(); 0772 } 0773 0774 void Interpreter::mark(bool) 0775 { 0776 if (m_execState) { 0777 m_execState->mark(); 0778 } 0779 if (m_globalObject && !m_globalObject->marked()) { 0780 m_globalObject->mark(); 0781 } 0782 if (m_globalExec.exception() && !JSValue::marked(m_globalExec.exception())) { 0783 JSValue::mark(m_globalExec.exception()); 0784 } 0785 0786 // Do not let cached activations survive the GC; as they have an unfortunate 0787 // tendenacy to pin blocks, increasing their number and hence spreading out 0788 // the objects somewhat 0789 m_numCachedActivations = 0; 0790 } 0791 0792 void Interpreter::markSourceCachedObjects() 0793 { 0794 markInternedStringsTable(); 0795 } 0796 0797 #ifdef KJS_DEBUG_MEM 0798 void Interpreter::finalCheck() 0799 { 0800 fprintf(stderr, "Interpreter::finalCheck()\n"); 0801 Collector::collect(); 0802 0803 // Node::finalCheck(); 0804 Collector::finalCheck(); 0805 } 0806 #endif 0807 0808 static bool printExceptions = false; 0809 0810 bool Interpreter::shouldPrintExceptions() 0811 { 0812 return printExceptions; 0813 } 0814 0815 void Interpreter::setShouldPrintExceptions(bool print) 0816 { 0817 printExceptions = print; 0818 } 0819 0820 void Interpreter::printException(const Completion &c, const UString &sourceURL) 0821 { 0822 JSLock lock; 0823 ExecState *exec = globalExec(); 0824 CString f = sourceURL.UTF8String(); 0825 CString message = JSValue::toObject(c.value(), exec)->toString(exec).UTF8String(); 0826 int line = JSValue::toUInt32(JSValue::toObject(c.value(), exec)->get(exec, "line"), exec); 0827 #if PLATFORM(WIN_OS) 0828 printf("%s line %d: %s\n", f.c_str(), line, message.c_str()); 0829 #else 0830 printf("[%d] %s line %d: %s\n", getpid(), f.c_str(), line, message.c_str()); 0831 #endif 0832 } 0833 0834 // bindings are OS X WebKit-only for now 0835 #if USE(BINDINGS) 0836 void *Interpreter::createLanguageInstanceForValue(ExecState *exec, int language, JSObject *value, const Bindings::RootObject *origin, const Bindings::RootObject *current) 0837 { 0838 return Bindings::Instance::createLanguageInstanceForValue(exec, (Bindings::Instance::BindingLanguage)language, value, origin, current); 0839 } 0840 #endif 0841 0842 void Interpreter::saveBuiltins(SavedBuiltins &builtins) const 0843 { 0844 if (!builtins._internal) { 0845 builtins._internal = new SavedBuiltinsInternal; 0846 } 0847 0848 builtins._internal->m_Object = m_Object; 0849 builtins._internal->m_Function = m_Function; 0850 builtins._internal->m_Array = m_Array; 0851 builtins._internal->m_Boolean = m_Boolean; 0852 builtins._internal->m_String = m_String; 0853 builtins._internal->m_Number = m_Number; 0854 builtins._internal->m_Date = m_Date; 0855 builtins._internal->m_RegExp = m_RegExp; 0856 builtins._internal->m_Error = m_Error; 0857 0858 builtins._internal->m_ObjectPrototype = m_ObjectPrototype; 0859 builtins._internal->m_FunctionPrototype = m_FunctionPrototype; 0860 builtins._internal->m_ArrayPrototype = m_ArrayPrototype; 0861 builtins._internal->m_BooleanPrototype = m_BooleanPrototype; 0862 builtins._internal->m_StringPrototype = m_StringPrototype; 0863 builtins._internal->m_NumberPrototype = m_NumberPrototype; 0864 builtins._internal->m_DatePrototype = m_DatePrototype; 0865 builtins._internal->m_RegExpPrototype = m_RegExpPrototype; 0866 builtins._internal->m_ErrorPrototype = m_ErrorPrototype; 0867 0868 builtins._internal->m_EvalError = m_EvalError; 0869 builtins._internal->m_RangeError = m_RangeError; 0870 builtins._internal->m_ReferenceError = m_ReferenceError; 0871 builtins._internal->m_SyntaxError = m_SyntaxError; 0872 builtins._internal->m_TypeError = m_TypeError; 0873 builtins._internal->m_UriError = m_UriError; 0874 0875 builtins._internal->m_EvalErrorPrototype = m_EvalErrorPrototype; 0876 builtins._internal->m_RangeErrorPrototype = m_RangeErrorPrototype; 0877 builtins._internal->m_ReferenceErrorPrototype = m_ReferenceErrorPrototype; 0878 builtins._internal->m_SyntaxErrorPrototype = m_SyntaxErrorPrototype; 0879 builtins._internal->m_TypeErrorPrototype = m_TypeErrorPrototype; 0880 builtins._internal->m_UriErrorPrototype = m_UriErrorPrototype; 0881 } 0882 0883 void Interpreter::restoreBuiltins(const SavedBuiltins &builtins) 0884 { 0885 if (!builtins._internal) { 0886 return; 0887 } 0888 0889 m_Object = builtins._internal->m_Object; 0890 m_Function = builtins._internal->m_Function; 0891 m_Array = builtins._internal->m_Array; 0892 m_Boolean = builtins._internal->m_Boolean; 0893 m_String = builtins._internal->m_String; 0894 m_Number = builtins._internal->m_Number; 0895 m_Date = builtins._internal->m_Date; 0896 m_RegExp = builtins._internal->m_RegExp; 0897 m_Error = builtins._internal->m_Error; 0898 0899 m_ObjectPrototype = builtins._internal->m_ObjectPrototype; 0900 m_FunctionPrototype = builtins._internal->m_FunctionPrototype; 0901 m_ArrayPrototype = builtins._internal->m_ArrayPrototype; 0902 m_BooleanPrototype = builtins._internal->m_BooleanPrototype; 0903 m_StringPrototype = builtins._internal->m_StringPrototype; 0904 m_NumberPrototype = builtins._internal->m_NumberPrototype; 0905 m_DatePrototype = builtins._internal->m_DatePrototype; 0906 m_RegExpPrototype = builtins._internal->m_RegExpPrototype; 0907 m_ErrorPrototype = builtins._internal->m_ErrorPrototype; 0908 0909 m_EvalError = builtins._internal->m_EvalError; 0910 m_RangeError = builtins._internal->m_RangeError; 0911 m_ReferenceError = builtins._internal->m_ReferenceError; 0912 m_SyntaxError = builtins._internal->m_SyntaxError; 0913 m_TypeError = builtins._internal->m_TypeError; 0914 m_UriError = builtins._internal->m_UriError; 0915 0916 m_EvalErrorPrototype = builtins._internal->m_EvalErrorPrototype; 0917 m_RangeErrorPrototype = builtins._internal->m_RangeErrorPrototype; 0918 m_ReferenceErrorPrototype = builtins._internal->m_ReferenceErrorPrototype; 0919 m_SyntaxErrorPrototype = builtins._internal->m_SyntaxErrorPrototype; 0920 m_TypeErrorPrototype = builtins._internal->m_TypeErrorPrototype; 0921 m_UriErrorPrototype = builtins._internal->m_UriErrorPrototype; 0922 } 0923 0924 void Interpreter::startTimeoutCheck() 0925 { 0926 if (!m_timeoutChecker) { 0927 m_timeoutChecker = new TimeoutChecker; 0928 } 0929 0930 m_timeoutChecker->startTimeoutCheck(this); 0931 } 0932 0933 void Interpreter::stopTimeoutCheck() 0934 { 0935 ASSERT(m_timeoutChecker); 0936 0937 m_timeoutChecker->stopTimeoutCheck(this); 0938 } 0939 0940 void Interpreter::restartTimeoutCheck() 0941 { 0942 if (!m_timeoutChecker || !m_startTimeoutCheckCount) { 0943 return; 0944 } 0945 0946 m_timedOut = false; 0947 m_timeoutChecker->stopTimeoutCheck(this); 0948 m_timeoutChecker->startTimeoutCheck(this); 0949 } 0950 0951 void Interpreter::pauseTimeoutCheck() 0952 { 0953 ASSERT(m_timeoutChecker); 0954 0955 m_timeoutChecker->pauseTimeoutCheck(this); 0956 } 0957 0958 void Interpreter::resumeTimeoutCheck() 0959 { 0960 ASSERT(m_timeoutChecker); 0961 0962 m_timeoutChecker->resumeTimeoutCheck(this); 0963 } 0964 0965 bool Interpreter::handleTimeout() 0966 { 0967 m_timedOut = false; 0968 0969 pauseTimeoutCheck(); 0970 bool retval = shouldInterruptScript(); 0971 resumeTimeoutCheck(); 0972 0973 return retval; 0974 } 0975 0976 Interpreter::InternedStringsTable *Interpreter::s_internedStrings; 0977 0978 void Interpreter::initInternedStringsTable() 0979 { 0980 if (!s_internedStrings) { 0981 s_internedStrings = new InternedStringsTable(); 0982 } 0983 } 0984 0985 StringImp *Interpreter::internString(const UString &literal) 0986 { 0987 InternedStringsTable::iterator i = s_internedStrings->find(literal.rep()); 0988 0989 if (i == s_internedStrings->end()) { 0990 // Need to add. Note: we can't use ->add() above to avoid a double-hash 0991 // as creation of a StringImp may cause a GC, which in turn may 0992 // rearrange the hashtable, invalidating the iterator. 0993 StringImp *si = static_cast<StringImp *>(jsOwnedString(literal)); 0994 s_internedStrings->add(literal.rep(), std::make_pair(si, 1)); 0995 return si; 0996 } else { 0997 ++i.values()->second; // just bump the ref count 0998 return i.values()->first; 0999 } 1000 } 1001 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 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 1024 SavedBuiltins::SavedBuiltins() : 1025 _internal(nullptr) 1026 { 1027 } 1028 1029 SavedBuiltins::~SavedBuiltins() 1030 { 1031 delete _internal; 1032 } 1033 1034 UnicodeSupport::UnicodeSupport() 1035 { 1036 } 1037 1038 void UnicodeSupport::setIdentStartChecker(bool (*f)(int c)) 1039 { 1040 Lexer::setIdentStartChecker(f); 1041 } 1042 1043 void UnicodeSupport::setIdentPartChecker(bool (*f)(int c)) 1044 { 1045 Lexer::setIdentPartChecker(f); 1046 } 1047 1048 void UnicodeSupport::setToLowerFunction(StringConversionFunction f) 1049 { 1050 StringProtoFunc::setToLowerFunction(f); 1051 } 1052 1053 void UnicodeSupport::setToUpperFunction(StringConversionFunction f) 1054 { 1055 StringProtoFunc::setToUpperFunction(f); 1056 } 1057 1058 } 1059