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++;
97 Collector::registerThread();
100 static inline void unlockInterpreter()
102 interpreterLockCount--;
103 pthread_mutex_unlock(&interpreterLock);
108 // ------------------------------ UndefinedImp ---------------------------------
110 UndefinedImp *UndefinedImp::staticUndefined = 0;
112 Value UndefinedImp::toPrimitive(ExecState */*exec*/, Type) const
114 return Value((ValueImp*)this);
117 bool UndefinedImp::toBoolean(ExecState */*exec*/) const
122 double UndefinedImp::toNumber(ExecState */*exec*/) const
127 UString UndefinedImp::toString(ExecState */*exec*/) const
132 Object UndefinedImp::toObject(ExecState *exec) const
134 Object err = Error::create(exec, TypeError, I18N_NOOP("Undefined value"));
135 exec->setException(err);
139 // ------------------------------ NullImp --------------------------------------
141 NullImp *NullImp::staticNull = 0;
143 Value NullImp::toPrimitive(ExecState */*exec*/, Type) const
145 return Value((ValueImp*)this);
148 bool NullImp::toBoolean(ExecState */*exec*/) const
153 double NullImp::toNumber(ExecState */*exec*/) const
158 UString NullImp::toString(ExecState */*exec*/) const
163 Object NullImp::toObject(ExecState *exec) const
165 Object err = Error::create(exec, TypeError, I18N_NOOP("Null value"));
166 exec->setException(err);
170 // ------------------------------ BooleanImp -----------------------------------
172 BooleanImp* BooleanImp::staticTrue = 0;
173 BooleanImp* BooleanImp::staticFalse = 0;
175 Value BooleanImp::toPrimitive(ExecState */*exec*/, Type) const
177 return Value((ValueImp*)this);
180 bool BooleanImp::toBoolean(ExecState */*exec*/) const
185 double BooleanImp::toNumber(ExecState */*exec*/) const
187 return val ? 1.0 : 0.0;
190 UString BooleanImp::toString(ExecState */*exec*/) const
192 return val ? "true" : "false";
195 Object BooleanImp::toObject(ExecState *exec) const
198 args.append(const_cast<BooleanImp*>(this));
199 return Object::dynamicCast(exec->lexicalInterpreter()->builtinBoolean().construct(exec,args));
202 // ------------------------------ StringImp ------------------------------------
204 Value StringImp::toPrimitive(ExecState */*exec*/, Type) const
206 return Value((ValueImp*)this);
209 bool StringImp::toBoolean(ExecState */*exec*/) const
211 return (val.size() > 0);
214 double StringImp::toNumber(ExecState */*exec*/) const
216 return val.toDouble();
219 UString StringImp::toString(ExecState */*exec*/) const
224 Object StringImp::toObject(ExecState *exec) const
227 args.append(const_cast<StringImp*>(this));
228 return Object(static_cast<ObjectImp *>(exec->lexicalInterpreter()->builtinString().construct(exec, args).imp()));
231 // ------------------------------ NumberImp ------------------------------------
233 NumberImp *NumberImp::staticNaN;
235 ValueImp *NumberImp::create(int i)
237 if (SimpleNumber::fits(i))
238 return SimpleNumber::make(i);
239 NumberImp *imp = new NumberImp(static_cast<double>(i));
240 #if !USE_CONSERVATIVE_GC
241 imp->setGcAllowedFast();
246 ValueImp *NumberImp::create(double d)
248 if (SimpleNumber::fits(d))
249 return SimpleNumber::make((int)d);
252 NumberImp *imp = new NumberImp(d);
253 #if !USE_CONSERVATIVE_GC
254 imp->setGcAllowedFast();
259 Value NumberImp::toPrimitive(ExecState *, Type) const
261 return Number((NumberImp*)this);
264 bool NumberImp::toBoolean(ExecState *) const
266 return !((val == 0) /* || (iVal() == N0) */ || isNaN(val));
269 double NumberImp::toNumber(ExecState *) const
274 UString NumberImp::toString(ExecState *) const
276 if (val == 0.0) // +0.0 or -0.0
278 return UString::from(val);
281 Object NumberImp::toObject(ExecState *exec) const
284 args.append(const_cast<NumberImp*>(this));
285 return Object::dynamicCast(exec->lexicalInterpreter()->builtinNumber().construct(exec,args));
288 bool NumberImp::toUInt32(unsigned& uint32) const
290 uint32 = (unsigned)val;
291 return (double)uint32 == val;
294 double SimpleNumber::negZero = -0.0;
296 // ------------------------------ LabelStack -----------------------------------
298 LabelStack::LabelStack(const LabelStack &other)
304 LabelStack &LabelStack::operator=(const LabelStack &other)
309 StackElem *se = other.tos;
311 StackElem *newPrev = new StackElem;
313 newPrev->id = se->id;
324 bool LabelStack::push(const Identifier &id)
326 if (id.isEmpty() || contains(id))
329 StackElem *newtos = new StackElem;
336 bool LabelStack::contains(const Identifier &id) const
341 for (StackElem *curr = tos; curr; curr = curr->prev)
348 void LabelStack::pop()
351 StackElem *prev = tos->prev;
357 LabelStack::~LabelStack()
362 void LabelStack::clear()
373 // ------------------------------ ContextImp -----------------------------------
376 ContextImp::ContextImp(Object &glob, InterpreterImp *interpreter, Object &thisV, CodeType type,
377 ContextImp *callingCon, FunctionImp *func, const List *args)
378 : _interpreter(interpreter), _function(func), _arguments(args)
381 _callingContext = callingCon;
383 // create and initialize activation object (ECMA 10.1.6)
384 if (type == FunctionCode || type == AnonymousCode ) {
385 activation = Object(new ActivationImp(func, *args));
386 variable = activation;
388 activation = Object();
395 if (_callingContext) {
396 scope = _callingContext->scopeChain();
397 variable = _callingContext->variableObject();
398 thisVal = _callingContext->thisValue();
400 } // else same as GlobalCode
403 scope.push(glob.imp());
404 thisVal = Object(static_cast<ObjectImp*>(glob.imp()));
408 if (type == FunctionCode) {
409 scope = func->scope();
410 scope.push(activation.imp());
413 scope.push(glob.imp());
414 scope.push(activation.imp());
416 variable = activation; // TODO: DontDelete ? (ECMA 10.2.3)
421 _interpreter->setContext(this);
424 ContextImp::~ContextImp()
426 _interpreter->setContext(_callingContext);
429 void ContextImp::mark()
431 for (ContextImp *context = this; context; context = context->_callingContext) {
432 context->scope.mark();
436 // ------------------------------ Parser ---------------------------------------
438 ProgramNode *Parser::progNode = 0;
441 ProgramNode *Parser::parse(const UString &sourceURL, int startingLineNumber,
442 const UChar *code, unsigned int length, int *sourceId,
443 int *errLine, UString *errMsg)
450 Lexer::curr()->setCode(sourceURL, startingLineNumber, code, length);
455 // Enable this (and the #define YYDEBUG in grammar.y) to debug a parse error
456 //extern int kjsyydebug;
458 int parseError = kjsyyparse();
459 bool lexError = Lexer::curr()->sawError();
460 Lexer::curr()->doneParsing();
461 ProgramNode *prog = progNode;
465 if (parseError || lexError) {
466 int eline = Lexer::curr()->lineNo();
470 *errMsg = "Parse error";
472 // must ref and deref to clean up properly
483 // ------------------------------ InterpreterImp -------------------------------
485 InterpreterImp* InterpreterImp::s_hook = 0L;
487 void InterpreterImp::globalInit()
489 //fprintf( stderr, "InterpreterImp::globalInit()\n" );
490 UndefinedImp::staticUndefined = new UndefinedImp();
491 #if !USE_CONSERVATIVE_GC
492 UndefinedImp::staticUndefined->ref();
494 NullImp::staticNull = new NullImp();
495 #if !USE_CONSERVATIVE_GC
496 NullImp::staticNull->ref();
498 BooleanImp::staticTrue = new BooleanImp(true);
499 #if !USE_CONSERVATIVE_GC
500 BooleanImp::staticTrue->ref();
502 BooleanImp::staticFalse = new BooleanImp(false);
503 #if !USE_CONSERVATIVE_GC
504 BooleanImp::staticFalse->ref();
506 NumberImp::staticNaN = new NumberImp(NaN);
507 #if !USE_CONSERVATIVE_GC
508 NumberImp::staticNaN->ref();
512 void InterpreterImp::globalClear()
514 //fprintf( stderr, "InterpreterImp::globalClear()\n" );
515 #if !USE_CONSERVATIVE_GC
516 UndefinedImp::staticUndefined->deref();
517 UndefinedImp::staticUndefined->setGcAllowed();
519 UndefinedImp::staticUndefined = 0L;
520 #if !USE_CONSERVATIVE_GC
521 NullImp::staticNull->deref();
522 NullImp::staticNull->setGcAllowed();
524 NullImp::staticNull = 0L;
525 #if !USE_CONSERVATIVE_GC
526 BooleanImp::staticTrue->deref();
527 BooleanImp::staticTrue->setGcAllowed();
529 BooleanImp::staticTrue = 0L;
530 #if !USE_CONSERVATIVE_GC
531 BooleanImp::staticFalse->deref();
532 BooleanImp::staticFalse->setGcAllowed();
534 BooleanImp::staticFalse = 0L;
535 #if !USE_CONSERVATIVE_GC
536 NumberImp::staticNaN->deref();
537 NumberImp::staticNaN->setGcAllowed();
539 NumberImp::staticNaN = 0;
542 InterpreterImp::InterpreterImp(Interpreter *interp, const Object &glob)
545 // add this interpreter to the global chain
546 // as a root set for garbage collection
548 m_interpreter = interp;
552 s_hook->next->prev = this;
555 // This is the first interpreter
556 s_hook = next = prev = this;
560 InterpreterMap::setInterpreterForGlobalObject(this, glob.imp());
563 globExec = new ExecState(m_interpreter,0);
565 m_compatMode = Interpreter::NativeMode;
567 // initialize properties of the global object
574 void InterpreterImp::lock()
579 int InterpreterImp::lockCount()
581 return interpreterLockCount;
584 void InterpreterImp::unlock()
589 void InterpreterImp::initGlobalObject()
593 // Contructor prototype objects (Object.prototype, Array.prototype etc)
595 FunctionPrototypeImp *funcProto = new FunctionPrototypeImp(globExec);
596 b_FunctionPrototype = Object(funcProto);
597 ObjectPrototypeImp *objProto = new ObjectPrototypeImp(globExec,funcProto);
598 b_ObjectPrototype = Object(objProto);
599 funcProto->setPrototype(b_ObjectPrototype);
601 ArrayPrototypeImp *arrayProto = new ArrayPrototypeImp(globExec,objProto);
602 b_ArrayPrototype = Object(arrayProto);
603 StringPrototypeImp *stringProto = new StringPrototypeImp(globExec,objProto);
604 b_StringPrototype = Object(stringProto);
605 BooleanPrototypeImp *booleanProto = new BooleanPrototypeImp(globExec,objProto,funcProto);
606 b_BooleanPrototype = Object(booleanProto);
607 NumberPrototypeImp *numberProto = new NumberPrototypeImp(globExec,objProto,funcProto);
608 b_NumberPrototype = Object(numberProto);
609 DatePrototypeImp *dateProto = new DatePrototypeImp(globExec,objProto);
610 b_DatePrototype = Object(dateProto);
611 RegExpPrototypeImp *regexpProto = new RegExpPrototypeImp(globExec,objProto,funcProto);
612 b_RegExpPrototype = Object(regexpProto);
613 ErrorPrototypeImp *errorProto = new ErrorPrototypeImp(globExec,objProto,funcProto);
614 b_ErrorPrototype = Object(errorProto);
616 static_cast<ObjectImp*>(global.imp())->setPrototype(b_ObjectPrototype);
618 // Constructors (Object, Array, etc.)
619 b_Object = Object(new ObjectObjectImp(globExec, objProto, funcProto));
620 b_Function = Object(new FunctionObjectImp(globExec, funcProto));
621 b_Array = Object(new ArrayObjectImp(globExec, funcProto, arrayProto));
622 b_String = Object(new StringObjectImp(globExec, funcProto, stringProto));
623 b_Boolean = Object(new BooleanObjectImp(globExec, funcProto, booleanProto));
624 b_Number = Object(new NumberObjectImp(globExec, funcProto, numberProto));
625 b_Date = Object(new DateObjectImp(globExec, funcProto, dateProto));
626 b_RegExp = Object(new RegExpObjectImp(globExec, funcProto, regexpProto));
627 b_Error = Object(new ErrorObjectImp(globExec, funcProto, errorProto));
629 // Error object prototypes
630 b_evalErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,EvalError,
631 "EvalError","EvalError"));
632 b_rangeErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,RangeError,
633 "RangeError","RangeError"));
634 b_referenceErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,ReferenceError,
635 "ReferenceError","ReferenceError"));
636 b_syntaxErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,SyntaxError,
637 "SyntaxError","SyntaxError"));
638 b_typeErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,TypeError,
639 "TypeError","TypeError"));
640 b_uriErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,URIError,
641 "URIError","URIError"));
644 b_evalError = Object(new NativeErrorImp(globExec,funcProto,b_evalErrorPrototype));
645 b_rangeError = Object(new NativeErrorImp(globExec,funcProto,b_rangeErrorPrototype));
646 b_referenceError = Object(new NativeErrorImp(globExec,funcProto,b_referenceErrorPrototype));
647 b_syntaxError = Object(new NativeErrorImp(globExec,funcProto,b_syntaxErrorPrototype));
648 b_typeError = Object(new NativeErrorImp(globExec,funcProto,b_typeErrorPrototype));
649 b_uriError = Object(new NativeErrorImp(globExec,funcProto,b_uriErrorPrototype));
652 funcProto->put(globExec,"constructor", b_Function, DontEnum);
654 global.put(globExec,"Object", b_Object, DontEnum);
655 global.put(globExec,"Function", b_Function, DontEnum);
656 global.put(globExec,"Array", b_Array, DontEnum);
657 global.put(globExec,"Boolean", b_Boolean, DontEnum);
658 global.put(globExec,"String", b_String, DontEnum);
659 global.put(globExec,"Number", b_Number, DontEnum);
660 global.put(globExec,"Date", b_Date, DontEnum);
661 global.put(globExec,"RegExp", b_RegExp, DontEnum);
662 global.put(globExec,"Error", b_Error, DontEnum);
663 // Using Internal for those to have something != 0
664 // (see kjs_window). Maybe DontEnum would be ok too ?
665 global.put(globExec,"EvalError",b_evalError, Internal);
666 global.put(globExec,"RangeError",b_rangeError, Internal);
667 global.put(globExec,"ReferenceError",b_referenceError, Internal);
668 global.put(globExec,"SyntaxError",b_syntaxError, Internal);
669 global.put(globExec,"TypeError",b_typeError, Internal);
670 global.put(globExec,"URIError",b_uriError, Internal);
672 // Set the "constructor" property of all builtin constructors
673 objProto->put(globExec, "constructor", b_Object, DontEnum | DontDelete | ReadOnly);
674 funcProto->put(globExec, "constructor", b_Function, DontEnum | DontDelete | ReadOnly);
675 arrayProto->put(globExec, "constructor", b_Array, DontEnum | DontDelete | ReadOnly);
676 booleanProto->put(globExec, "constructor", b_Boolean, DontEnum | DontDelete | ReadOnly);
677 stringProto->put(globExec, "constructor", b_String, DontEnum | DontDelete | ReadOnly);
678 numberProto->put(globExec, "constructor", b_Number, DontEnum | DontDelete | ReadOnly);
679 dateProto->put(globExec, "constructor", b_Date, DontEnum | DontDelete | ReadOnly);
680 regexpProto->put(globExec, "constructor", b_RegExp, DontEnum | DontDelete | ReadOnly);
681 errorProto->put(globExec, "constructor", b_Error, DontEnum | DontDelete | ReadOnly);
682 b_evalErrorPrototype.put(globExec, "constructor", b_evalError, DontEnum | DontDelete | ReadOnly);
683 b_rangeErrorPrototype.put(globExec, "constructor", b_rangeError, DontEnum | DontDelete | ReadOnly);
684 b_referenceErrorPrototype.put(globExec, "constructor", b_referenceError, DontEnum | DontDelete | ReadOnly);
685 b_syntaxErrorPrototype.put(globExec, "constructor", b_syntaxError, DontEnum | DontDelete | ReadOnly);
686 b_typeErrorPrototype.put(globExec, "constructor", b_typeError, DontEnum | DontDelete | ReadOnly);
687 b_uriErrorPrototype.put(globExec, "constructor", b_uriError, DontEnum | DontDelete | ReadOnly);
690 global.put(globExec, "NaN", Number(NaN), DontEnum|DontDelete);
691 global.put(globExec, "Infinity", Number(Inf), DontEnum|DontDelete);
692 global.put(globExec, "undefined", Undefined(), DontEnum|DontDelete);
694 // built-in functions
695 global.put(globExec,"eval", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::Eval, 1)), DontEnum);
696 global.put(globExec,"parseInt", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::ParseInt, 2)), DontEnum);
697 global.put(globExec,"parseFloat", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::ParseFloat, 1)), DontEnum);
698 global.put(globExec,"isNaN", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::IsNaN, 1)), DontEnum);
699 global.put(globExec,"isFinite", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::IsFinite, 1)), DontEnum);
700 global.put(globExec,"escape", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::Escape, 1)), DontEnum);
701 global.put(globExec,"unescape", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::UnEscape, 1)), DontEnum);
702 global.put(globExec,"decodeURI", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::DecodeURI, 1)), DontEnum);
703 global.put(globExec,"decodeURIComponent", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::DecodeURIComponent, 1)), DontEnum);
704 global.put(globExec,"encodeURI", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::EncodeURI, 1)), DontEnum);
705 global.put(globExec,"encodeURIComponent", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::EncodeURIComponent, 1)), DontEnum);
707 global.put(globExec,"kjsprint", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::KJSPrint, 1)), DontEnum);
711 global.put(globExec,"Math", Object(new MathObjectImp(globExec,objProto)), DontEnum);
714 InterpreterImp::~InterpreterImp()
717 dbg->detach(m_interpreter);
723 void InterpreterImp::clear()
725 //fprintf(stderr,"InterpreterImp::clear\n");
726 // remove from global chain (see init())
735 // This was the last interpreter
739 InterpreterMap::removeInterpreterForGlobalObject(global.imp());
746 void InterpreterImp::mark()
748 //if (exVal && !exVal->marked())
750 //if (retVal && !retVal->marked())
752 if (UndefinedImp::staticUndefined && !UndefinedImp::staticUndefined->marked())
753 UndefinedImp::staticUndefined->mark();
754 if (NullImp::staticNull && !NullImp::staticNull->marked())
755 NullImp::staticNull->mark();
756 if (NumberImp::staticNaN && !NumberImp::staticNaN->marked())
757 NumberImp::staticNaN->mark();
758 if (BooleanImp::staticTrue && !BooleanImp::staticTrue->marked())
759 BooleanImp::staticTrue->mark();
760 if (BooleanImp::staticFalse && !BooleanImp::staticFalse->marked())
761 BooleanImp::staticFalse->mark();
762 //fprintf( stderr, "InterpreterImp::mark this=%p global.imp()=%p\n", this, global.imp() );
764 m_interpreter->mark();
769 bool InterpreterImp::checkSyntax(const UString &code)
771 // Parser::parse() returns 0 in a syntax error occurs, so we just check for that
772 ProgramNode *progNode = Parser::parse(UString(), 0, code.data(),code.size(),0,0,0);
773 bool ok = (progNode != 0);
775 // must ref and deref to clean up properly
783 Completion InterpreterImp::evaluate(const UString &code, const Value &thisV, const UString &sourceURL, int startingLineNumber)
788 // prevent against infinite recursion
789 if (recursion >= 20) {
791 Completion result = Completion(Throw,Error::create(globExec,GeneralError,"Recursion too deep"));
795 return Completion(Throw,Error::create(globExec,GeneralError,"Recursion too deep"));
799 // parse the source code
803 ProgramNode *progNode = Parser::parse(sourceURL, startingLineNumber, code.data(),code.size(),&sid,&errLine,&errMsg);
805 // notify debugger that source has been parsed
807 bool cont = dbg->sourceParsed(globExec,sid,code,errLine);
812 return Completion(Break);
815 return Completion(Break);
819 // no program node means a syntax error occurred
821 Object err = Error::create(globExec,SyntaxError,errMsg.ascii(),errLine, -1, &sourceURL);
822 err.put(globExec,"sid",Number(sid));
826 return Completion(Throw,err);
829 globExec->clearException();
834 Object &globalObj = globalObject();
835 Object thisObj = globalObject();
837 if (!thisV.isNull()) {
838 // "this" must be an object... use same rules as Function.prototype.apply()
839 if (thisV.isA(NullType) || thisV.isA(UndefinedType))
840 thisObj = globalObject();
842 thisObj = thisV.toObject(globExec);
847 if (globExec->hadException()) {
848 // the thisArg.toObject() conversion above might have thrown an exception - if so,
850 res = Completion(Throw,globExec->exception());
854 ContextImp ctx(globalObj, this, thisObj);
855 ExecState newExec(m_interpreter,&ctx);
856 progNode->processVarDecls(&newExec);
857 res = progNode->execute(&newExec);
860 if (progNode->deref())
870 void InterpreterImp::setDebugger(Debugger *d)
873 d->detach(m_interpreter);
877 void InterpreterImp::saveBuiltins (SavedBuiltins &builtins) const
879 if (!builtins._internal) {
880 builtins._internal = new SavedBuiltinsInternal;
883 builtins._internal->b_Object = b_Object;
884 builtins._internal->b_Function = b_Function;
885 builtins._internal->b_Array = b_Array;
886 builtins._internal->b_Boolean = b_Boolean;
887 builtins._internal->b_String = b_String;
888 builtins._internal->b_Number = b_Number;
889 builtins._internal->b_Date = b_Date;
890 builtins._internal->b_RegExp = b_RegExp;
891 builtins._internal->b_Error = b_Error;
893 builtins._internal->b_ObjectPrototype = b_ObjectPrototype;
894 builtins._internal->b_FunctionPrototype = b_FunctionPrototype;
895 builtins._internal->b_ArrayPrototype = b_ArrayPrototype;
896 builtins._internal->b_BooleanPrototype = b_BooleanPrototype;
897 builtins._internal->b_StringPrototype = b_StringPrototype;
898 builtins._internal->b_NumberPrototype = b_NumberPrototype;
899 builtins._internal->b_DatePrototype = b_DatePrototype;
900 builtins._internal->b_RegExpPrototype = b_RegExpPrototype;
901 builtins._internal->b_ErrorPrototype = b_ErrorPrototype;
903 builtins._internal->b_evalError = b_evalError;
904 builtins._internal->b_rangeError = b_rangeError;
905 builtins._internal->b_referenceError = b_referenceError;
906 builtins._internal->b_syntaxError = b_syntaxError;
907 builtins._internal->b_typeError = b_typeError;
908 builtins._internal->b_uriError = b_uriError;
910 builtins._internal->b_evalErrorPrototype = b_evalErrorPrototype;
911 builtins._internal->b_rangeErrorPrototype = b_rangeErrorPrototype;
912 builtins._internal->b_referenceErrorPrototype = b_referenceErrorPrototype;
913 builtins._internal->b_syntaxErrorPrototype = b_syntaxErrorPrototype;
914 builtins._internal->b_typeErrorPrototype = b_typeErrorPrototype;
915 builtins._internal->b_uriErrorPrototype = b_uriErrorPrototype;
918 void InterpreterImp::restoreBuiltins (const SavedBuiltins &builtins)
920 if (!builtins._internal) {
924 b_Object = builtins._internal->b_Object;
925 b_Function = builtins._internal->b_Function;
926 b_Array = builtins._internal->b_Array;
927 b_Boolean = builtins._internal->b_Boolean;
928 b_String = builtins._internal->b_String;
929 b_Number = builtins._internal->b_Number;
930 b_Date = builtins._internal->b_Date;
931 b_RegExp = builtins._internal->b_RegExp;
932 b_Error = builtins._internal->b_Error;
934 b_ObjectPrototype = builtins._internal->b_ObjectPrototype;
935 b_FunctionPrototype = builtins._internal->b_FunctionPrototype;
936 b_ArrayPrototype = builtins._internal->b_ArrayPrototype;
937 b_BooleanPrototype = builtins._internal->b_BooleanPrototype;
938 b_StringPrototype = builtins._internal->b_StringPrototype;
939 b_NumberPrototype = builtins._internal->b_NumberPrototype;
940 b_DatePrototype = builtins._internal->b_DatePrototype;
941 b_RegExpPrototype = builtins._internal->b_RegExpPrototype;
942 b_ErrorPrototype = builtins._internal->b_ErrorPrototype;
944 b_evalError = builtins._internal->b_evalError;
945 b_rangeError = builtins._internal->b_rangeError;
946 b_referenceError = builtins._internal->b_referenceError;
947 b_syntaxError = builtins._internal->b_syntaxError;
948 b_typeError = builtins._internal->b_typeError;
949 b_uriError = builtins._internal->b_uriError;
951 b_evalErrorPrototype = builtins._internal->b_evalErrorPrototype;
952 b_rangeErrorPrototype = builtins._internal->b_rangeErrorPrototype;
953 b_referenceErrorPrototype = builtins._internal->b_referenceErrorPrototype;
954 b_syntaxErrorPrototype = builtins._internal->b_syntaxErrorPrototype;
955 b_typeErrorPrototype = builtins._internal->b_typeErrorPrototype;
956 b_uriErrorPrototype = builtins._internal->b_uriErrorPrototype;
959 InterpreterImp *InterpreterImp::interpreterWithGlobalObject(ObjectImp *global)
961 return InterpreterMap::getInterpreterForGlobalObject(global);
965 // ------------------------------ InternalFunctionImp --------------------------
967 const ClassInfo InternalFunctionImp::info = {"Function", 0, 0, 0};
969 InternalFunctionImp::InternalFunctionImp(FunctionPrototypeImp *funcProto)
970 : ObjectImp(funcProto)
974 bool InternalFunctionImp::implementsHasInstance() const
979 Boolean InternalFunctionImp::hasInstance(ExecState *exec, const Value &value)
981 if (value.type() != ObjectType)
982 return Boolean(false);
984 Value prot = get(exec,prototypePropertyName);
985 if (prot.type() != ObjectType && prot.type() != NullType) {
986 Object err = Error::create(exec, TypeError, "Invalid prototype encountered "
987 "in instanceof operation.");
988 exec->setException(err);
989 return Boolean(false);
992 Object v = Object(static_cast<ObjectImp*>(value.imp()));
993 while ((v = Object::dynamicCast(v.prototype())).imp()) {
994 if (v.imp() == prot.imp())
995 return Boolean(true);
997 return Boolean(false);
1000 // ------------------------------ global functions -----------------------------
1002 double KJS::roundValue(ExecState *exec, const Value &v)
1004 Number n = v.toNumber(exec);
1005 double d = n.value();
1006 double ad = fabs(d);
1007 if (ad == 0 || isNaN(d) || isInf(d))
1009 return copysign(floor(ad), d);
1014 void KJS::printInfo(ExecState *exec, const char *s, const Value &o, int lineno)
1017 fprintf(stderr, "KJS: %s: (null)", s);
1022 switch ( v.type() ) {
1023 case UnspecifiedType:
1024 name = "Unspecified";
1042 name = Object::dynamicCast(v).className();
1044 name = "(unknown class)";
1047 UString vString = v.toString(exec);
1048 if ( vString.size() > 50 )
1049 vString = vString.substr( 0, 50 ) + "...";
1050 // Can't use two UString::ascii() in the same fprintf call
1051 CString tempString( vString.cstring() );
1053 fprintf(stderr, "KJS: %s: %s : %s (%p)",
1054 s, tempString.c_str(), name.ascii(), (void*)v.imp());
1057 fprintf(stderr, ", line %d\n",lineno);
1059 fprintf(stderr, "\n");