1 // -*- c-basic-offset: 2 -*-
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
5 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
6 * Copyright (C) 2004 Apple Computer, Inc.
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.
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.
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., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
29 #include <strings.h> // for strdup
32 #include "array_object.h"
33 #include "bool_object.h"
34 #include "collector.h"
36 #include "date_object.h"
38 #include "error_object.h"
39 #include "function_object.h"
41 #include "interpreter_map.h"
43 #include "math_object.h"
45 #include "number_object.h"
47 #include "object_object.h"
48 #include "operations.h"
49 #include "regexp_object.h"
50 #include "string_object.h"
52 #define I18N_NOOP(s) s
54 extern int kjsyyparse();
61 #ifdef WORDS_BIGENDIAN
62 const unsigned char NaN_Bytes[] = { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 };
63 const unsigned char Inf_Bytes[] = { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 };
65 const unsigned char NaN_Bytes[] = { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 };
66 const unsigned char Inf_Bytes[] = { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 };
68 const unsigned char NaN_Bytes[] = { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f };
69 const unsigned char Inf_Bytes[] = { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f };
72 const double NaN = *(const double*) NaN_Bytes;
73 const double Inf = *(const double*) Inf_Bytes;
76 #endif // APPLE_CHANGES
78 static pthread_once_t interpreterLockOnce = PTHREAD_ONCE_INIT;
79 static pthread_mutex_t interpreterLock;
80 static int interpreterLockCount = 0;
82 static void initializeInterpreterLock()
84 pthread_mutexattr_t attr;
86 pthread_mutexattr_init(&attr);
87 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
89 pthread_mutex_init(&interpreterLock, &attr);
92 static inline void lockInterpreter()
94 pthread_once(&interpreterLockOnce, initializeInterpreterLock);
95 pthread_mutex_lock(&interpreterLock);
96 interpreterLockCount++;
99 static inline void unlockInterpreter()
101 interpreterLockCount--;
102 pthread_mutex_unlock(&interpreterLock);
107 // ------------------------------ UndefinedImp ---------------------------------
109 UndefinedImp *UndefinedImp::staticUndefined = 0;
111 Value UndefinedImp::toPrimitive(ExecState */*exec*/, Type) const
113 return Value((ValueImp*)this);
116 bool UndefinedImp::toBoolean(ExecState */*exec*/) const
121 double UndefinedImp::toNumber(ExecState */*exec*/) const
126 UString UndefinedImp::toString(ExecState */*exec*/) const
131 Object UndefinedImp::toObject(ExecState *exec) const
133 Object err = Error::create(exec, TypeError, I18N_NOOP("Undefined value"));
134 exec->setException(err);
138 // ------------------------------ NullImp --------------------------------------
140 NullImp *NullImp::staticNull = 0;
142 Value NullImp::toPrimitive(ExecState */*exec*/, Type) const
144 return Value((ValueImp*)this);
147 bool NullImp::toBoolean(ExecState */*exec*/) const
152 double NullImp::toNumber(ExecState */*exec*/) const
157 UString NullImp::toString(ExecState */*exec*/) const
162 Object NullImp::toObject(ExecState *exec) const
164 Object err = Error::create(exec, TypeError, I18N_NOOP("Null value"));
165 exec->setException(err);
169 // ------------------------------ BooleanImp -----------------------------------
171 BooleanImp* BooleanImp::staticTrue = 0;
172 BooleanImp* BooleanImp::staticFalse = 0;
174 Value BooleanImp::toPrimitive(ExecState */*exec*/, Type) const
176 return Value((ValueImp*)this);
179 bool BooleanImp::toBoolean(ExecState */*exec*/) const
184 double BooleanImp::toNumber(ExecState */*exec*/) const
186 return val ? 1.0 : 0.0;
189 UString BooleanImp::toString(ExecState */*exec*/) const
191 return val ? "true" : "false";
194 Object BooleanImp::toObject(ExecState *exec) const
197 args.append(const_cast<BooleanImp*>(this));
198 return Object::dynamicCast(exec->lexicalInterpreter()->builtinBoolean().construct(exec,args));
201 // ------------------------------ StringImp ------------------------------------
203 Value StringImp::toPrimitive(ExecState */*exec*/, Type) const
205 return Value((ValueImp*)this);
208 bool StringImp::toBoolean(ExecState */*exec*/) const
210 return (val.size() > 0);
213 double StringImp::toNumber(ExecState */*exec*/) const
215 return val.toDouble();
218 UString StringImp::toString(ExecState */*exec*/) const
223 Object StringImp::toObject(ExecState *exec) const
226 args.append(const_cast<StringImp*>(this));
227 return Object::dynamicCast(exec->lexicalInterpreter()->builtinString().construct(exec,args));
230 // ------------------------------ NumberImp ------------------------------------
232 NumberImp *NumberImp::staticNaN;
234 ValueImp *NumberImp::create(int i)
236 if (SimpleNumber::fits(i))
237 return SimpleNumber::make(i);
238 NumberImp *imp = new NumberImp(static_cast<double>(i));
239 #if !USE_CONSERVATIVE_GC
240 imp->setGcAllowedFast();
245 ValueImp *NumberImp::create(double d)
247 if (SimpleNumber::fits(d))
248 return SimpleNumber::make((int)d);
251 NumberImp *imp = new NumberImp(d);
252 #if !USE_CONSERVATIVE_GC
253 imp->setGcAllowedFast();
258 Value NumberImp::toPrimitive(ExecState *, Type) const
260 return Number((NumberImp*)this);
263 bool NumberImp::toBoolean(ExecState *) const
265 return !((val == 0) /* || (iVal() == N0) */ || isNaN(val));
268 double NumberImp::toNumber(ExecState *) const
273 UString NumberImp::toString(ExecState *) const
275 if (val == 0.0) // +0.0 or -0.0
277 return UString::from(val);
280 Object NumberImp::toObject(ExecState *exec) const
283 args.append(const_cast<NumberImp*>(this));
284 return Object::dynamicCast(exec->lexicalInterpreter()->builtinNumber().construct(exec,args));
287 bool NumberImp::toUInt32(unsigned& uint32) const
289 uint32 = (unsigned)val;
290 return (double)uint32 == val;
293 double SimpleNumber::negZero = -0.0;
295 // ------------------------------ LabelStack -----------------------------------
297 LabelStack::LabelStack(const LabelStack &other)
303 LabelStack &LabelStack::operator=(const LabelStack &other)
308 StackElem *se = other.tos;
310 StackElem *newPrev = new StackElem;
312 newPrev->id = se->id;
323 bool LabelStack::push(const Identifier &id)
325 if (id.isEmpty() || contains(id))
328 StackElem *newtos = new StackElem;
335 bool LabelStack::contains(const Identifier &id) const
340 for (StackElem *curr = tos; curr; curr = curr->prev)
347 void LabelStack::pop()
350 StackElem *prev = tos->prev;
356 LabelStack::~LabelStack()
361 void LabelStack::clear()
372 // ------------------------------ ContextImp -----------------------------------
375 ContextImp::ContextImp(Object &glob, InterpreterImp *interpreter, Object &thisV, CodeType type,
376 ContextImp *callingCon, FunctionImp *func, const List *args)
377 : _interpreter(interpreter), _function(func), _arguments(args)
380 _callingContext = callingCon;
382 // create and initialize activation object (ECMA 10.1.6)
383 if (type == FunctionCode || type == AnonymousCode ) {
384 activation = Object(new ActivationImp(func, *args));
385 variable = activation;
387 activation = Object();
394 if (_callingContext) {
395 scope = _callingContext->scopeChain();
396 variable = _callingContext->variableObject();
397 thisVal = _callingContext->thisValue();
399 } // else same as GlobalCode
402 scope.push(glob.imp());
403 thisVal = Object(static_cast<ObjectImp*>(glob.imp()));
407 if (type == FunctionCode) {
408 scope = func->scope();
409 scope.push(activation.imp());
412 scope.push(glob.imp());
413 scope.push(activation.imp());
415 variable = activation; // TODO: DontDelete ? (ECMA 10.2.3)
420 _interpreter->setContext(this);
423 ContextImp::~ContextImp()
425 _interpreter->setContext(_callingContext);
428 void ContextImp::mark()
430 for (ContextImp *context = this; context; context = context->_callingContext) {
431 context->scope.mark();
435 // ------------------------------ Parser ---------------------------------------
437 ProgramNode *Parser::progNode = 0;
440 ProgramNode *Parser::parse(const UString &sourceURL, int startingLineNumber,
441 const UChar *code, unsigned int length, int *sourceId,
442 int *errLine, UString *errMsg)
449 Lexer::curr()->setCode(sourceURL, startingLineNumber, code, length);
454 // Enable this (and the #define YYDEBUG in grammar.y) to debug a parse error
455 //extern int kjsyydebug;
457 int parseError = kjsyyparse();
458 bool lexError = Lexer::curr()->sawError();
459 Lexer::curr()->doneParsing();
460 ProgramNode *prog = progNode;
464 if (parseError || lexError) {
465 int eline = Lexer::curr()->lineNo();
469 *errMsg = "Parse error";
471 // must ref and deref to clean up properly
482 // ------------------------------ InterpreterImp -------------------------------
484 InterpreterImp* InterpreterImp::s_hook = 0L;
486 void InterpreterImp::globalInit()
488 //fprintf( stderr, "InterpreterImp::globalInit()\n" );
489 UndefinedImp::staticUndefined = new UndefinedImp();
490 #if !USE_CONSERVATIVE_GC
491 UndefinedImp::staticUndefined->ref();
493 NullImp::staticNull = new NullImp();
494 #if !USE_CONSERVATIVE_GC
495 NullImp::staticNull->ref();
497 BooleanImp::staticTrue = new BooleanImp(true);
498 #if !USE_CONSERVATIVE_GC
499 BooleanImp::staticTrue->ref();
501 BooleanImp::staticFalse = new BooleanImp(false);
502 #if !USE_CONSERVATIVE_GC
503 BooleanImp::staticFalse->ref();
505 NumberImp::staticNaN = new NumberImp(NaN);
506 #if !USE_CONSERVATIVE_GC
507 NumberImp::staticNaN->ref();
511 void InterpreterImp::globalClear()
513 //fprintf( stderr, "InterpreterImp::globalClear()\n" );
514 #if !USE_CONSERVATIVE_GC
515 UndefinedImp::staticUndefined->deref();
516 UndefinedImp::staticUndefined->setGcAllowed();
518 UndefinedImp::staticUndefined = 0L;
519 #if !USE_CONSERVATIVE_GC
520 NullImp::staticNull->deref();
521 NullImp::staticNull->setGcAllowed();
523 NullImp::staticNull = 0L;
524 #if !USE_CONSERVATIVE_GC
525 BooleanImp::staticTrue->deref();
526 BooleanImp::staticTrue->setGcAllowed();
528 BooleanImp::staticTrue = 0L;
529 #if !USE_CONSERVATIVE_GC
530 BooleanImp::staticFalse->deref();
531 BooleanImp::staticFalse->setGcAllowed();
533 BooleanImp::staticFalse = 0L;
534 #if !USE_CONSERVATIVE_GC
535 NumberImp::staticNaN->deref();
536 NumberImp::staticNaN->setGcAllowed();
538 NumberImp::staticNaN = 0;
541 InterpreterImp::InterpreterImp(Interpreter *interp, const Object &glob)
544 // add this interpreter to the global chain
545 // as a root set for garbage collection
547 m_interpreter = interp;
551 s_hook->next->prev = this;
554 // This is the first interpreter
555 s_hook = next = prev = this;
559 InterpreterMap::setInterpreterForGlobalObject(this, glob.imp());
562 globExec = new ExecState(m_interpreter,0);
564 m_compatMode = Interpreter::NativeMode;
566 // initialize properties of the global object
573 void InterpreterImp::lock()
578 int InterpreterImp::lockCount()
580 return interpreterLockCount;
583 void InterpreterImp::unlock()
588 void InterpreterImp::initGlobalObject()
592 // Contructor prototype objects (Object.prototype, Array.prototype etc)
594 FunctionPrototypeImp *funcProto = new FunctionPrototypeImp(globExec);
595 b_FunctionPrototype = Object(funcProto);
596 ObjectPrototypeImp *objProto = new ObjectPrototypeImp(globExec,funcProto);
597 b_ObjectPrototype = Object(objProto);
598 funcProto->setPrototype(b_ObjectPrototype);
600 ArrayPrototypeImp *arrayProto = new ArrayPrototypeImp(globExec,objProto);
601 b_ArrayPrototype = Object(arrayProto);
602 StringPrototypeImp *stringProto = new StringPrototypeImp(globExec,objProto);
603 b_StringPrototype = Object(stringProto);
604 BooleanPrototypeImp *booleanProto = new BooleanPrototypeImp(globExec,objProto,funcProto);
605 b_BooleanPrototype = Object(booleanProto);
606 NumberPrototypeImp *numberProto = new NumberPrototypeImp(globExec,objProto,funcProto);
607 b_NumberPrototype = Object(numberProto);
608 DatePrototypeImp *dateProto = new DatePrototypeImp(globExec,objProto);
609 b_DatePrototype = Object(dateProto);
610 RegExpPrototypeImp *regexpProto = new RegExpPrototypeImp(globExec,objProto,funcProto);
611 b_RegExpPrototype = Object(regexpProto);
612 ErrorPrototypeImp *errorProto = new ErrorPrototypeImp(globExec,objProto,funcProto);
613 b_ErrorPrototype = Object(errorProto);
615 static_cast<ObjectImp*>(global.imp())->setPrototype(b_ObjectPrototype);
617 // Constructors (Object, Array, etc.)
618 b_Object = Object(new ObjectObjectImp(globExec, objProto, funcProto));
619 b_Function = Object(new FunctionObjectImp(globExec, funcProto));
620 b_Array = Object(new ArrayObjectImp(globExec, funcProto, arrayProto));
621 b_String = Object(new StringObjectImp(globExec, funcProto, stringProto));
622 b_Boolean = Object(new BooleanObjectImp(globExec, funcProto, booleanProto));
623 b_Number = Object(new NumberObjectImp(globExec, funcProto, numberProto));
624 b_Date = Object(new DateObjectImp(globExec, funcProto, dateProto));
625 b_RegExp = Object(new RegExpObjectImp(globExec, funcProto, regexpProto));
626 b_Error = Object(new ErrorObjectImp(globExec, funcProto, errorProto));
628 // Error object prototypes
629 b_evalErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,EvalError,
630 "EvalError","EvalError"));
631 b_rangeErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,RangeError,
632 "RangeError","RangeError"));
633 b_referenceErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,ReferenceError,
634 "ReferenceError","ReferenceError"));
635 b_syntaxErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,SyntaxError,
636 "SyntaxError","SyntaxError"));
637 b_typeErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,TypeError,
638 "TypeError","TypeError"));
639 b_uriErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,URIError,
640 "URIError","URIError"));
643 b_evalError = Object(new NativeErrorImp(globExec,funcProto,b_evalErrorPrototype));
644 b_rangeError = Object(new NativeErrorImp(globExec,funcProto,b_rangeErrorPrototype));
645 b_referenceError = Object(new NativeErrorImp(globExec,funcProto,b_referenceErrorPrototype));
646 b_syntaxError = Object(new NativeErrorImp(globExec,funcProto,b_syntaxErrorPrototype));
647 b_typeError = Object(new NativeErrorImp(globExec,funcProto,b_typeErrorPrototype));
648 b_uriError = Object(new NativeErrorImp(globExec,funcProto,b_uriErrorPrototype));
651 funcProto->put(globExec,"constructor", b_Function, DontEnum);
653 global.put(globExec,"Object", b_Object, DontEnum);
654 global.put(globExec,"Function", b_Function, DontEnum);
655 global.put(globExec,"Array", b_Array, DontEnum);
656 global.put(globExec,"Boolean", b_Boolean, DontEnum);
657 global.put(globExec,"String", b_String, DontEnum);
658 global.put(globExec,"Number", b_Number, DontEnum);
659 global.put(globExec,"Date", b_Date, DontEnum);
660 global.put(globExec,"RegExp", b_RegExp, DontEnum);
661 global.put(globExec,"Error", b_Error, DontEnum);
662 // Using Internal for those to have something != 0
663 // (see kjs_window). Maybe DontEnum would be ok too ?
664 global.put(globExec,"EvalError",b_evalError, Internal);
665 global.put(globExec,"RangeError",b_rangeError, Internal);
666 global.put(globExec,"ReferenceError",b_referenceError, Internal);
667 global.put(globExec,"SyntaxError",b_syntaxError, Internal);
668 global.put(globExec,"TypeError",b_typeError, Internal);
669 global.put(globExec,"URIError",b_uriError, Internal);
671 // Set the "constructor" property of all builtin constructors
672 objProto->put(globExec, "constructor", b_Object, DontEnum | DontDelete | ReadOnly);
673 funcProto->put(globExec, "constructor", b_Function, DontEnum | DontDelete | ReadOnly);
674 arrayProto->put(globExec, "constructor", b_Array, DontEnum | DontDelete | ReadOnly);
675 booleanProto->put(globExec, "constructor", b_Boolean, DontEnum | DontDelete | ReadOnly);
676 stringProto->put(globExec, "constructor", b_String, DontEnum | DontDelete | ReadOnly);
677 numberProto->put(globExec, "constructor", b_Number, DontEnum | DontDelete | ReadOnly);
678 dateProto->put(globExec, "constructor", b_Date, DontEnum | DontDelete | ReadOnly);
679 regexpProto->put(globExec, "constructor", b_RegExp, DontEnum | DontDelete | ReadOnly);
680 errorProto->put(globExec, "constructor", b_Error, DontEnum | DontDelete | ReadOnly);
681 b_evalErrorPrototype.put(globExec, "constructor", b_evalError, DontEnum | DontDelete | ReadOnly);
682 b_rangeErrorPrototype.put(globExec, "constructor", b_rangeError, DontEnum | DontDelete | ReadOnly);
683 b_referenceErrorPrototype.put(globExec, "constructor", b_referenceError, DontEnum | DontDelete | ReadOnly);
684 b_syntaxErrorPrototype.put(globExec, "constructor", b_syntaxError, DontEnum | DontDelete | ReadOnly);
685 b_typeErrorPrototype.put(globExec, "constructor", b_typeError, DontEnum | DontDelete | ReadOnly);
686 b_uriErrorPrototype.put(globExec, "constructor", b_uriError, DontEnum | DontDelete | ReadOnly);
689 global.put(globExec, "NaN", Number(NaN), DontEnum|DontDelete);
690 global.put(globExec, "Infinity", Number(Inf), DontEnum|DontDelete);
691 global.put(globExec, "undefined", Undefined(), DontEnum|DontDelete);
693 // built-in functions
694 global.put(globExec,"eval", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::Eval, 1)), DontEnum);
695 global.put(globExec,"parseInt", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::ParseInt, 2)), DontEnum);
696 global.put(globExec,"parseFloat", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::ParseFloat, 1)), DontEnum);
697 global.put(globExec,"isNaN", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::IsNaN, 1)), DontEnum);
698 global.put(globExec,"isFinite", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::IsFinite, 1)), DontEnum);
699 global.put(globExec,"escape", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::Escape, 1)), DontEnum);
700 global.put(globExec,"unescape", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::UnEscape, 1)), DontEnum);
701 global.put(globExec,"decodeURI", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::DecodeURI, 1)), DontEnum);
702 global.put(globExec,"decodeURIComponent", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::DecodeURIComponent, 1)), DontEnum);
703 global.put(globExec,"encodeURI", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::EncodeURI, 1)), DontEnum);
704 global.put(globExec,"encodeURIComponent", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::EncodeURIComponent, 1)), DontEnum);
706 global.put(globExec,"kjsprint", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::KJSPrint, 1)), DontEnum);
710 global.put(globExec,"Math", Object(new MathObjectImp(globExec,objProto)), DontEnum);
713 InterpreterImp::~InterpreterImp()
716 dbg->detach(m_interpreter);
722 void InterpreterImp::clear()
724 //fprintf(stderr,"InterpreterImp::clear\n");
725 // remove from global chain (see init())
734 // This was the last interpreter
738 InterpreterMap::removeInterpreterForGlobalObject(global.imp());
745 void InterpreterImp::mark()
747 //if (exVal && !exVal->marked())
749 //if (retVal && !retVal->marked())
751 if (UndefinedImp::staticUndefined && !UndefinedImp::staticUndefined->marked())
752 UndefinedImp::staticUndefined->mark();
753 if (NullImp::staticNull && !NullImp::staticNull->marked())
754 NullImp::staticNull->mark();
755 if (BooleanImp::staticTrue && !BooleanImp::staticTrue->marked())
756 BooleanImp::staticTrue->mark();
757 if (BooleanImp::staticFalse && !BooleanImp::staticFalse->marked())
758 BooleanImp::staticFalse->mark();
759 //fprintf( stderr, "InterpreterImp::mark this=%p global.imp()=%p\n", this, global.imp() );
761 m_interpreter->mark();
766 bool InterpreterImp::checkSyntax(const UString &code)
768 // Parser::parse() returns 0 in a syntax error occurs, so we just check for that
769 ProgramNode *progNode = Parser::parse(UString(), 0, code.data(),code.size(),0,0,0);
770 bool ok = (progNode != 0);
772 // must ref and deref to clean up properly
780 Completion InterpreterImp::evaluate(const UString &code, const Value &thisV, const UString &sourceURL, int startingLineNumber)
785 // prevent against infinite recursion
786 if (recursion >= 20) {
788 Completion result = Completion(Throw,Error::create(globExec,GeneralError,"Recursion too deep"));
792 return Completion(Throw,Error::create(globExec,GeneralError,"Recursion too deep"));
796 // parse the source code
800 ProgramNode *progNode = Parser::parse(sourceURL, startingLineNumber, code.data(),code.size(),&sid,&errLine,&errMsg);
802 // notify debugger that source has been parsed
804 bool cont = dbg->sourceParsed(globExec,sid,code,errLine);
809 return Completion(Break);
812 return Completion(Break);
816 // no program node means a syntax error occurred
818 Object err = Error::create(globExec,SyntaxError,errMsg.ascii(),errLine, -1, &sourceURL);
819 err.put(globExec,"sid",Number(sid));
823 return Completion(Throw,err);
826 globExec->clearException();
831 Object &globalObj = globalObject();
832 Object thisObj = globalObject();
834 if (!thisV.isNull()) {
835 // "this" must be an object... use same rules as Function.prototype.apply()
836 if (thisV.isA(NullType) || thisV.isA(UndefinedType))
837 thisObj = globalObject();
839 thisObj = thisV.toObject(globExec);
844 if (globExec->hadException()) {
845 // the thisArg.toObject() conversion above might have thrown an exception - if so,
847 res = Completion(Throw,globExec->exception());
851 ContextImp ctx(globalObj, this, thisObj);
852 ExecState newExec(m_interpreter,&ctx);
853 progNode->processVarDecls(&newExec);
854 res = progNode->execute(&newExec);
857 if (progNode->deref())
867 void InterpreterImp::setDebugger(Debugger *d)
870 d->detach(m_interpreter);
874 void InterpreterImp::saveBuiltins (SavedBuiltins &builtins) const
876 if (!builtins._internal) {
877 builtins._internal = new SavedBuiltinsInternal;
880 builtins._internal->b_Object = b_Object;
881 builtins._internal->b_Function = b_Function;
882 builtins._internal->b_Array = b_Array;
883 builtins._internal->b_Boolean = b_Boolean;
884 builtins._internal->b_String = b_String;
885 builtins._internal->b_Number = b_Number;
886 builtins._internal->b_Date = b_Date;
887 builtins._internal->b_RegExp = b_RegExp;
888 builtins._internal->b_Error = b_Error;
890 builtins._internal->b_ObjectPrototype = b_ObjectPrototype;
891 builtins._internal->b_FunctionPrototype = b_FunctionPrototype;
892 builtins._internal->b_ArrayPrototype = b_ArrayPrototype;
893 builtins._internal->b_BooleanPrototype = b_BooleanPrototype;
894 builtins._internal->b_StringPrototype = b_StringPrototype;
895 builtins._internal->b_NumberPrototype = b_NumberPrototype;
896 builtins._internal->b_DatePrototype = b_DatePrototype;
897 builtins._internal->b_RegExpPrototype = b_RegExpPrototype;
898 builtins._internal->b_ErrorPrototype = b_ErrorPrototype;
900 builtins._internal->b_evalError = b_evalError;
901 builtins._internal->b_rangeError = b_rangeError;
902 builtins._internal->b_referenceError = b_referenceError;
903 builtins._internal->b_syntaxError = b_syntaxError;
904 builtins._internal->b_typeError = b_typeError;
905 builtins._internal->b_uriError = b_uriError;
907 builtins._internal->b_evalErrorPrototype = b_evalErrorPrototype;
908 builtins._internal->b_rangeErrorPrototype = b_rangeErrorPrototype;
909 builtins._internal->b_referenceErrorPrototype = b_referenceErrorPrototype;
910 builtins._internal->b_syntaxErrorPrototype = b_syntaxErrorPrototype;
911 builtins._internal->b_typeErrorPrototype = b_typeErrorPrototype;
912 builtins._internal->b_uriErrorPrototype = b_uriErrorPrototype;
915 void InterpreterImp::restoreBuiltins (const SavedBuiltins &builtins)
917 if (!builtins._internal) {
921 b_Object = builtins._internal->b_Object;
922 b_Function = builtins._internal->b_Function;
923 b_Array = builtins._internal->b_Array;
924 b_Boolean = builtins._internal->b_Boolean;
925 b_String = builtins._internal->b_String;
926 b_Number = builtins._internal->b_Number;
927 b_Date = builtins._internal->b_Date;
928 b_RegExp = builtins._internal->b_RegExp;
929 b_Error = builtins._internal->b_Error;
931 b_ObjectPrototype = builtins._internal->b_ObjectPrototype;
932 b_FunctionPrototype = builtins._internal->b_FunctionPrototype;
933 b_ArrayPrototype = builtins._internal->b_ArrayPrototype;
934 b_BooleanPrototype = builtins._internal->b_BooleanPrototype;
935 b_StringPrototype = builtins._internal->b_StringPrototype;
936 b_NumberPrototype = builtins._internal->b_NumberPrototype;
937 b_DatePrototype = builtins._internal->b_DatePrototype;
938 b_RegExpPrototype = builtins._internal->b_RegExpPrototype;
939 b_ErrorPrototype = builtins._internal->b_ErrorPrototype;
941 b_evalError = builtins._internal->b_evalError;
942 b_rangeError = builtins._internal->b_rangeError;
943 b_referenceError = builtins._internal->b_referenceError;
944 b_syntaxError = builtins._internal->b_syntaxError;
945 b_typeError = builtins._internal->b_typeError;
946 b_uriError = builtins._internal->b_uriError;
948 b_evalErrorPrototype = builtins._internal->b_evalErrorPrototype;
949 b_rangeErrorPrototype = builtins._internal->b_rangeErrorPrototype;
950 b_referenceErrorPrototype = builtins._internal->b_referenceErrorPrototype;
951 b_syntaxErrorPrototype = builtins._internal->b_syntaxErrorPrototype;
952 b_typeErrorPrototype = builtins._internal->b_typeErrorPrototype;
953 b_uriErrorPrototype = builtins._internal->b_uriErrorPrototype;
956 InterpreterImp *InterpreterImp::interpreterWithGlobalObject(ObjectImp *global)
958 return InterpreterMap::getInterpreterForGlobalObject(global);
962 // ------------------------------ InternalFunctionImp --------------------------
964 const ClassInfo InternalFunctionImp::info = {"Function", 0, 0, 0};
966 InternalFunctionImp::InternalFunctionImp(FunctionPrototypeImp *funcProto)
967 : ObjectImp(funcProto)
971 bool InternalFunctionImp::implementsHasInstance() const
976 Boolean InternalFunctionImp::hasInstance(ExecState *exec, const Value &value)
978 if (value.type() != ObjectType)
979 return Boolean(false);
981 Value prot = get(exec,prototypePropertyName);
982 if (prot.type() != ObjectType && prot.type() != NullType) {
983 Object err = Error::create(exec, TypeError, "Invalid prototype encountered "
984 "in instanceof operation.");
985 exec->setException(err);
986 return Boolean(false);
989 Object v = Object(static_cast<ObjectImp*>(value.imp()));
990 while ((v = Object::dynamicCast(v.prototype())).imp()) {
991 if (v.imp() == prot.imp())
992 return Boolean(true);
994 return Boolean(false);
997 // ------------------------------ global functions -----------------------------
999 double KJS::roundValue(ExecState *exec, const Value &v)
1001 Number n = v.toNumber(exec);
1002 double d = n.value();
1003 double ad = fabs(d);
1004 if (ad == 0 || isNaN(d) || isInf(d))
1006 return copysign(floor(ad), d);
1011 void KJS::printInfo(ExecState *exec, const char *s, const Value &o, int lineno)
1014 fprintf(stderr, "KJS: %s: (null)", s);
1019 switch ( v.type() ) {
1020 case UnspecifiedType:
1021 name = "Unspecified";
1039 name = Object::dynamicCast(v).className();
1041 name = "(unknown class)";
1044 UString vString = v.toString(exec);
1045 if ( vString.size() > 50 )
1046 vString = vString.substr( 0, 50 ) + "...";
1047 // Can't use two UString::ascii() in the same fprintf call
1048 CString tempString( vString.cstring() );
1050 fprintf(stderr, "KJS: %s: %s : %s (%p)",
1051 s, tempString.c_str(), name.ascii(), (void*)v.imp());
1054 fprintf(stderr, ", line %d\n",lineno);
1056 fprintf(stderr, "\n");