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