29 #include "array_object.h"
30 #include "bool_object.h"
31 #include "collector.h"
33 #include "date_object.h"
35 #include "error_object.h"
36 #include "function_object.h"
39 #include "math_object.h"
41 #include "number_object.h"
43 #include "object_object.h"
44 #include "operations.h"
45 #include "regexp_object.h"
46 #include "string_object.h"
48 #define I18N_NOOP(s) s
50 extern int kjsyyparse();
57 typedef union {
unsigned char b[8];
double d; } kjs_double_t;
59 #ifdef WORDS_BIGENDIAN
60 static const kjs_double_t NaN_Bytes = { { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 } };
61 static const kjs_double_t Inf_Bytes = { { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } };
63 static const kjs_double_t NaN_Bytes = { { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 } };
64 static const kjs_double_t Inf_Bytes = { { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 } };
66 static const kjs_double_t NaN_Bytes = { { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f } };
67 static const kjs_double_t Inf_Bytes = { { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } };
70 const double NaN = NaN_Bytes.d;
71 const double Inf = Inf_Bytes.d;
74 #ifdef KJS_THREADSUPPORT
75 static pthread_once_t interpreterLockOnce = PTHREAD_ONCE_INIT;
76 static pthread_mutex_t interpreterLock;
77 static int interpreterLockCount = 0;
79 static void initializeInterpreterLock()
81 pthread_mutexattr_t attr;
83 pthread_mutexattr_init(&attr);
84 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
86 pthread_mutex_init(&interpreterLock, &attr);
90 static inline void lockInterpreter()
92 #ifdef KJS_THREADSUPPORT
93 pthread_once(&interpreterLockOnce, initializeInterpreterLock);
94 pthread_mutex_lock(&interpreterLock);
95 interpreterLockCount++;
99 static inline void unlockInterpreter()
101 #ifdef KJS_THREADSUPPORT
102 interpreterLockCount--;
103 pthread_mutex_unlock(&interpreterLock);
111 UndefinedImp *UndefinedImp::staticUndefined = 0;
118 bool UndefinedImp::toBoolean(
ExecState* )
const
123 double UndefinedImp::toNumber(
ExecState* )
const
136 exec->setException(err);
142 NullImp *NullImp::staticNull = 0;
149 bool NullImp::toBoolean(
ExecState* )
const
154 double NullImp::toNumber(
ExecState* )
const
167 exec->setException(err);
173 BooleanImp* BooleanImp::staticTrue = 0;
174 BooleanImp* BooleanImp::staticFalse = 0;
181 bool BooleanImp::toBoolean(
ExecState* )
const
186 double BooleanImp::toNumber(
ExecState* )
const
188 return val ? 1.0 : 0.0;
193 return val ?
"true" :
"false";
199 args.
append(const_cast<BooleanImp*>(
this));
210 bool StringImp::toBoolean(
ExecState* )
const
212 return (val.size() > 0);
215 double StringImp::toNumber(
ExecState* )
const
217 return val.toDouble();
228 args.
append(const_cast<StringImp*>(
this));
234 NumberImp *NumberImp::staticNaN;
238 if (SimpleNumber::fits(i))
239 return SimpleNumber::make(i);
240 NumberImp *imp =
new NumberImp(static_cast<double>(i));
241 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 imp->setGcAllowedFast();
258 return Number((NumberImp*)
this);
261 bool NumberImp::toBoolean(
ExecState *)
const
263 return !((val == 0) || isNaN(val));
266 double NumberImp::toNumber(
ExecState *)
const
281 args.
append(const_cast<NumberImp*>(
this));
285 bool NumberImp::toUInt32(
unsigned& uint32)
const
287 uint32 = (unsigned)val;
288 return (
double)uint32 == val;
291 double SimpleNumber::negZero = -0.0;
295 LabelStack::LabelStack(
const LabelStack &other)
306 StackElem *se = other.tos;
308 StackElem *newPrev =
new StackElem;
310 newPrev->id = se->id;
326 StackElem *newtos =
new StackElem;
338 for (StackElem *curr = tos; curr; curr = curr->prev)
348 StackElem *prev = tos->prev;
354 LabelStack::~LabelStack()
359 void LabelStack::clear()
374 ContextImp::ContextImp(
Object &glob, InterpreterImp *interpreter,
Object &thisV,
int _sourceId, CodeType type,
376 : _interpreter(interpreter), _function(func), _arguments(args)
379 _callingContext = callingCon;
382 sourceId = _sourceId;
386 if (func && func->inherits(&DeclaredFunctionImp::info))
387 functionName = static_cast<DeclaredFunctionImp*>(func)->name();
392 if (type == FunctionCode) {
393 activation =
Object(
new ActivationImp(func,*args));
394 variable = activation;
403 if (_callingContext) {
404 scope = _callingContext->scopeChain();
405 #ifndef KJS_PURE_ECMA
406 if (thisV.imp() != glob.imp())
407 scope.push(thisV.imp());
409 variable = _callingContext->variableObject();
410 thisVal = _callingContext->thisValue();
415 scope.push(glob.imp());
416 #ifndef KJS_PURE_ECMA
424 scope = func->scope();
425 scope.push(activation.imp());
426 variable = activation;
431 _interpreter->setContext(
this);
434 ContextImp::~ContextImp()
436 _interpreter->setContext(_callingContext);
439 void ContextImp::mark()
441 for (
ContextImp *context =
this; context; context = context->_callingContext) {
442 context->scope.mark();
446 bool ContextImp::inTryCatch()
const
449 while (c && !c->tryCatch)
450 c = c->_callingContext;
451 return (c && c->tryCatch);
456 void SourceCode::cleanup()
458 if (interpreter && interpreter->debugger())
459 interpreter->debugger()->sourceUnused(interpreter->globalExec(),sid);
461 interpreter->removeSourceCode(
this);
467 FunctionBodyNode *Parser::progNode = 0;
469 SourceCode *Parser::source = 0;
471 FunctionBodyNode *Parser::parse(
const UChar *code,
unsigned int length, SourceCode **src,
479 Lexer::curr()->setCode(code, length);
483 source =
new SourceCode(sid);
490 int parseError = kjsyyparse();
491 if (Lexer::curr()->hadError())
493 Lexer::curr()->doneParsing();
494 FunctionBodyNode *prog = progNode;
500 int eline = Lexer::curr()->lineNo();
506 fprintf( stderr,
"[kjs-internal] %s\n",
UString(code,length).ascii() );
509 fprintf( stderr,
"[kjs-internal] KJS: JavaScript parse error at line %d.\n", eline);
515 fprintf( stderr,
"[kjs-internal] %s\n", prog->toCode().ascii() );
523 InterpreterImp* InterpreterImp::s_hook = 0L;
525 void InterpreterImp::globalInit()
528 UndefinedImp::staticUndefined =
new UndefinedImp();
529 UndefinedImp::staticUndefined->ref();
530 NullImp::staticNull =
new NullImp();
531 NullImp::staticNull->ref();
532 BooleanImp::staticTrue =
new BooleanImp(
true);
533 BooleanImp::staticTrue->ref();
534 BooleanImp::staticFalse =
new BooleanImp(
false);
535 BooleanImp::staticFalse->ref();
536 NumberImp::staticNaN =
new NumberImp(NaN);
537 NumberImp::staticNaN->ref();
540 void InterpreterImp::globalClear()
543 UndefinedImp::staticUndefined->deref();
544 UndefinedImp::staticUndefined->setGcAllowed();
545 UndefinedImp::staticUndefined = 0L;
546 NullImp::staticNull->deref();
547 NullImp::staticNull->setGcAllowed();
548 NullImp::staticNull = 0L;
549 BooleanImp::staticTrue->deref();
550 BooleanImp::staticTrue->setGcAllowed();
551 BooleanImp::staticTrue = 0L;
552 BooleanImp::staticFalse->deref();
553 BooleanImp::staticFalse->setGcAllowed();
554 BooleanImp::staticFalse = 0L;
555 NumberImp::staticNaN->deref();
556 NumberImp::staticNaN->setGcAllowed();
557 NumberImp::staticNaN = 0;
561 : m_interpreter(interp),
575 s_hook->next->prev =
this;
579 s_hook =
next = prev =
this;
584 globExec =
new ExecState(m_interpreter,0);
590 void InterpreterImp::lock()
595 void InterpreterImp::unlock()
600 void InterpreterImp::initGlobalObject()
605 b_FunctionPrototype =
Object(funcProto);
606 ObjectPrototypeImp *objProto =
new ObjectPrototypeImp(globExec,funcProto);
607 b_ObjectPrototype =
Object(objProto);
608 funcProto->setPrototype(b_ObjectPrototype);
610 ArrayPrototypeImp *arrayProto =
new ArrayPrototypeImp(globExec,objProto);
611 b_ArrayPrototype =
Object(arrayProto);
612 StringPrototypeImp *stringProto =
new StringPrototypeImp(globExec,objProto);
613 b_StringPrototype =
Object(stringProto);
614 BooleanPrototypeImp *booleanProto =
new BooleanPrototypeImp(globExec,objProto,funcProto);
615 b_BooleanPrototype =
Object(booleanProto);
616 NumberPrototypeImp *numberProto =
new NumberPrototypeImp(globExec,objProto,funcProto);
617 b_NumberPrototype =
Object(numberProto);
618 DatePrototypeImp *dateProto =
new DatePrototypeImp(globExec,objProto);
619 b_DatePrototype =
Object(dateProto);
620 RegExpPrototypeImp *regexpProto =
new RegExpPrototypeImp(globExec,objProto,funcProto);
621 b_RegExpPrototype =
Object(regexpProto);
622 ErrorPrototypeImp *errorProto =
new ErrorPrototypeImp(globExec,objProto,funcProto);
623 b_ErrorPrototype =
Object(errorProto);
625 static_cast<ObjectImp*
>(global.imp())->setPrototype(b_ObjectPrototype);
629 b_Object =
Object(
new ObjectObjectImp(globExec, objProto, funcProto));
630 b_Function =
Object(
new FunctionObjectImp(globExec, funcProto));
631 b_Array =
Object(
new ArrayObjectImp(globExec, funcProto, arrayProto));
632 b_String =
Object(
new StringObjectImp(globExec, funcProto, stringProto));
633 b_Boolean =
Object(
new BooleanObjectImp(globExec, funcProto, booleanProto));
634 b_Number =
Object(
new NumberObjectImp(globExec, funcProto, numberProto));
635 b_Date =
Object(
new DateObjectImp(globExec, funcProto, dateProto));
636 b_RegExp =
Object(
new RegExpObjectImp(globExec, funcProto, regexpProto));
637 b_Error =
Object(
new ErrorObjectImp(globExec, funcProto, errorProto));
640 b_evalErrorPrototype =
Object(
new NativeErrorPrototypeImp(globExec,errorProto,EvalError,
641 "EvalError",
"EvalError"));
642 b_rangeErrorPrototype =
Object(
new NativeErrorPrototypeImp(globExec,errorProto,RangeError,
643 "RangeError",
"RangeError"));
644 b_referenceErrorPrototype =
Object(
new NativeErrorPrototypeImp(globExec,errorProto,ReferenceError,
645 "ReferenceError",
"ReferenceError"));
646 b_syntaxErrorPrototype =
Object(
new NativeErrorPrototypeImp(globExec,errorProto,SyntaxError,
647 "SyntaxError",
"SyntaxError"));
648 b_typeErrorPrototype =
Object(
new NativeErrorPrototypeImp(globExec,errorProto,TypeError,
649 "TypeError",
"TypeError"));
650 b_uriErrorPrototype =
Object(
new NativeErrorPrototypeImp(globExec,errorProto,URIError,
651 "URIError",
"URIError"));
654 b_evalError =
Object(
new NativeErrorImp(globExec,funcProto,b_evalErrorPrototype));
655 b_rangeError =
Object(
new NativeErrorImp(globExec,funcProto,b_rangeErrorPrototype));
656 b_referenceError =
Object(
new NativeErrorImp(globExec,funcProto,b_referenceErrorPrototype));
657 b_syntaxError =
Object(
new NativeErrorImp(globExec,funcProto,b_syntaxErrorPrototype));
658 b_typeError =
Object(
new NativeErrorImp(globExec,funcProto,b_typeErrorPrototype));
659 b_uriError =
Object(
new NativeErrorImp(globExec,funcProto,b_uriErrorPrototype));
662 funcProto->put(globExec,constructorPropertyName, b_Function, DontEnum);
664 global.put(globExec,
"Object", b_Object, DontEnum);
665 global.put(globExec,
"Function", b_Function, DontEnum);
666 global.put(globExec,
"Array", b_Array, DontEnum);
667 global.put(globExec,
"Boolean", b_Boolean, DontEnum);
668 global.put(globExec,
"String", b_String, DontEnum);
669 global.put(globExec,
"Number", b_Number, DontEnum);
670 global.put(globExec,
"Date", b_Date, DontEnum);
671 global.put(globExec,
"RegExp", b_RegExp, DontEnum);
672 global.put(globExec,
"Error", b_Error, DontEnum);
675 global.put(globExec,
"EvalError",b_evalError, Internal);
676 global.put(globExec,
"RangeError",b_rangeError, Internal);
677 global.put(globExec,
"ReferenceError",b_referenceError, Internal);
678 global.put(globExec,
"SyntaxError",b_syntaxError, Internal);
679 global.put(globExec,
"TypeError",b_typeError, Internal);
680 global.put(globExec,
"URIError",b_uriError, Internal);
683 objProto->put(globExec, constructorPropertyName, b_Object, DontEnum | DontDelete | ReadOnly);
684 funcProto->put(globExec, constructorPropertyName, b_Function, DontEnum | DontDelete | ReadOnly);
685 arrayProto->put(globExec, constructorPropertyName, b_Array, DontEnum | DontDelete | ReadOnly);
686 booleanProto->put(globExec, constructorPropertyName, b_Boolean, DontEnum | DontDelete | ReadOnly);
687 stringProto->put(globExec, constructorPropertyName, b_String, DontEnum | DontDelete | ReadOnly);
688 numberProto->put(globExec, constructorPropertyName, b_Number, DontEnum | DontDelete | ReadOnly);
689 dateProto->put(globExec, constructorPropertyName, b_Date, DontEnum | DontDelete | ReadOnly);
690 regexpProto->put(globExec, constructorPropertyName, b_RegExp, DontEnum | DontDelete | ReadOnly);
691 errorProto->put(globExec, constructorPropertyName, b_Error, DontEnum | DontDelete | ReadOnly);
692 b_evalErrorPrototype.put(globExec, constructorPropertyName, b_evalError, DontEnum | DontDelete | ReadOnly);
693 b_rangeErrorPrototype.put(globExec, constructorPropertyName, b_rangeError, DontEnum | DontDelete | ReadOnly);
694 b_referenceErrorPrototype.put(globExec, constructorPropertyName, b_referenceError, DontEnum | DontDelete | ReadOnly);
695 b_syntaxErrorPrototype.put(globExec, constructorPropertyName, b_syntaxError, DontEnum | DontDelete | ReadOnly);
696 b_typeErrorPrototype.put(globExec, constructorPropertyName, b_typeError, DontEnum | DontDelete | ReadOnly);
697 b_uriErrorPrototype.put(globExec, constructorPropertyName, b_uriError, DontEnum | DontDelete | ReadOnly);
700 global.put(globExec,
"NaN",
Number(NaN), DontEnum|DontDelete);
701 global.put(globExec,
"Infinity",
Number(Inf), DontEnum|DontDelete);
702 global.put(globExec,
"undefined",
Undefined(), DontEnum|DontDelete);
705 #ifdef KJS_PURE_ECMA // otherwise as deprecated Object.prototype property
706 global.put(globExec,
"eval",
707 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::Eval,1,
"eval")), DontEnum);
709 global.put(globExec,
"parseInt",
710 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::ParseInt,2,
"parseInt")), DontEnum);
711 global.put(globExec,
"parseFloat",
712 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::ParseFloat,1,
"parseFloat")), DontEnum);
713 global.put(globExec,
"isNaN",
714 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::IsNaN,1,
"isNaN")), DontEnum);
715 global.put(globExec,
"isFinite",
716 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::IsFinite,1,
"isFinite")), DontEnum);
717 global.put(globExec,
"decodeURI",
718 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::DecodeURI,1,
"decodeURI")),
720 global.put(globExec,
"decodeURIComponent",
721 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::DecodeURIComponent,1,
"decodeURIComponent")),
723 global.put(globExec,
"encodeURI",
724 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::EncodeURI,1,
"encodeURI")),
726 global.put(globExec,
"encodeURIComponent",
727 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::EncodeURIComponent,1,
"encodeURIComponent")),
729 global.put(globExec,
"escape",
730 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::Escape,1,
"escape")), DontEnum);
731 global.put(globExec,
"unescape",
732 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::UnEscape,1,
"unescape")), DontEnum);
734 global.put(globExec,
"kjsprint",
735 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::KJSPrint,1,
"kjsprint")), DontEnum);
739 global.put(globExec,
"Math",
Object(
new MathObjectImp(globExec,objProto)), DontEnum);
742 InterpreterImp::~InterpreterImp()
745 dbg->detach(m_interpreter);
746 for (SourceCode *s = sources; s; s = s->next)
753 void InterpreterImp::clear()
770 void InterpreterImp::mark()
776 if (UndefinedImp::staticUndefined && !UndefinedImp::staticUndefined->marked())
777 UndefinedImp::staticUndefined->mark();
778 if (NullImp::staticNull && !NullImp::staticNull->marked())
779 NullImp::staticNull->mark();
780 if (NumberImp::staticNaN && !NumberImp::staticNaN->marked())
781 NumberImp::staticNaN->mark();
782 if (BooleanImp::staticTrue && !BooleanImp::staticTrue->marked())
783 BooleanImp::staticTrue->mark();
784 if (BooleanImp::staticFalse && !BooleanImp::staticFalse->marked())
785 BooleanImp::staticFalse->mark();
788 global.imp()->mark();
790 m_interpreter->mark();
795 bool InterpreterImp::checkSyntax(
const UString &code,
int *errLine,
UString *errMsg)
799 FunctionBodyNode *progNode = Parser::parse(code.
data(),code.
size(),&source,errLine,errMsg);
801 bool ok = (progNode != 0);
806 bool InterpreterImp::checkSyntax(
const UString &code)
810 FunctionBodyNode *progNode = Parser::parse(code.
data(),code.
size(),&source,0,0);
812 bool ok = (progNode != 0);
822 if (recursion >= 20) {
832 FunctionBodyNode *progNode = Parser::parse(code.
data(),code.
size(),&source,&errLine,&errMsg);
836 bool cont = dbg->sourceParsed(globExec,source->sid,code,errLine);
846 addSourceCode(source);
851 err.
put(globExec,
"sid",
Number(source->sid));
852 globExec->setException(err);
853 globExec->clearException();
860 globExec->clearException();
865 Object &globalObj = globalObject();
866 Object thisObj = globalObject();
870 if (thisV.
isA(NullType) || thisV.
isA(UndefinedType))
871 thisObj = globalObject();
878 if (globExec->hadException()) {
881 res =
Completion(Throw,globExec->exception());
885 ContextImp ctx(globalObj,
this, thisObj, source->sid);
890 progNode->processVarDecls(&newExec);
892 ctx.setLines(progNode->firstLine(),progNode->firstLine());
895 if (!dbg->enterContext(&newExec)) {
903 ctx.setLines(progNode->lastLine(),progNode->lastLine());
904 res = progNode->execute(&newExec);
905 if (dbg && !dbg->exitContext(&newExec,res)) {
914 if (progNode->deref())
918 if (globExec->hadException()) {
919 res =
Completion(Throw,globExec->exception());
920 globExec->clearException();
927 void InterpreterImp::setDebugger(Debugger *d)
935 old->detach(m_interpreter);
938 void InterpreterImp::addSourceCode(SourceCode *code)
941 assert(!code->interpreter);
942 code->next = sources;
943 code->interpreter =
this;
947 void InterpreterImp::removeSourceCode(SourceCode *code)
952 if (code == sources) {
953 sources = sources->next;
957 SourceCode *prev = sources;
958 SourceCode *cur = sources->next;
959 while (cur != code) {
965 prev->next = cur->next;
970 const ClassInfo InternalFunctionImp::info = {
"Function", 0, 0, 0};
973 : ObjectImp(funcProto)
978 : ObjectImp(static_cast<
FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp()))
982 bool InternalFunctionImp::implementsHasInstance()
const
989 if (value.
type() != ObjectType)
992 Value prot =
get(exec,prototypePropertyName);
993 if (prot.
type() != ObjectType && prot.
type() != NullType) {
995 "in instanceof operation.");
996 exec->setException(err);
1000 Object v =
Object(static_cast<ObjectImp*>(value.imp()));
1002 if (v.imp() == prot.imp())
1013 if (isNaN(n) || isInf(n))
1015 double an = fabs(n);
1018 double d = floor(an);
1027 void KJS::printInfo(
ExecState *exec,
const char *s,
const Value &o,
int lineno)
1030 fprintf(stderr,
"KJS: %s: (null)", s);
1033 unsigned int arrayLength = 0;
1034 bool hadExcep = exec->hadException();
1037 switch ( v.
type() ) {
1038 case UnspecifiedType:
1039 name =
"Unspecified";
1060 name =
"(unknown class)";
1061 if ( obj.inherits(&ArrayInstanceImp::info) )
1062 arrayLength = obj.
get(exec,lengthPropertyName).
toUInt32(exec);
1068 if ( arrayLength > 100 )
1073 exec->clearException();
1074 if ( vString.
size() > 50 )
1075 vString = vString.
substr( 0, 50 ) +
"...";
1079 fprintf(stderr,
"KJS: %s: %s : %s (%p)",
1080 s, tempString.c_str(), name.
ascii(), (
void*)v.imp());
1083 fprintf(stderr,
", line %d\n",lineno);
1085 fprintf(stderr,
"\n");