28 #include "array_object.h"
29 #include "bool_object.h"
30 #include "collector.h"
32 #include "date_object.h"
34 #include "error_object.h"
35 #include "function_object.h"
38 #include "math_object.h"
40 #include "number_object.h"
42 #include "object_object.h"
43 #include "operations.h"
44 #include "regexp_object.h"
45 #include "string_object.h"
47 #define I18N_NOOP(s) s
49 extern int kjsyyparse();
56 typedef union {
unsigned char b[8];
double d; } kjs_double_t;
58 #ifdef WORDS_BIGENDIAN
59 static const kjs_double_t NaN_Bytes = { { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 } };
60 static const kjs_double_t Inf_Bytes = { { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } };
62 static const kjs_double_t NaN_Bytes = { { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 } };
63 static const kjs_double_t Inf_Bytes = { { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 } };
65 static const kjs_double_t NaN_Bytes = { { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f } };
66 static const kjs_double_t Inf_Bytes = { { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } };
69 const double NaN = NaN_Bytes.d;
70 const double Inf = Inf_Bytes.d;
73 #ifdef KJS_THREADSUPPORT
74 static pthread_once_t interpreterLockOnce = PTHREAD_ONCE_INIT;
75 static pthread_mutex_t interpreterLock;
76 static int interpreterLockCount = 0;
78 static void initializeInterpreterLock()
80 pthread_mutexattr_t attr;
82 pthread_mutexattr_init(&attr);
83 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
85 pthread_mutex_init(&interpreterLock, &attr);
89 static inline void lockInterpreter()
91 #ifdef KJS_THREADSUPPORT
92 pthread_once(&interpreterLockOnce, initializeInterpreterLock);
93 pthread_mutex_lock(&interpreterLock);
94 interpreterLockCount++;
98 static inline void unlockInterpreter()
100 #ifdef KJS_THREADSUPPORT
101 interpreterLockCount--;
102 pthread_mutex_unlock(&interpreterLock);
110 UndefinedImp *UndefinedImp::staticUndefined = 0;
117 bool UndefinedImp::toBoolean(
ExecState* )
const
122 double UndefinedImp::toNumber(
ExecState* )
const
135 exec->setException(err);
141 NullImp *NullImp::staticNull = 0;
148 bool NullImp::toBoolean(
ExecState* )
const
153 double NullImp::toNumber(
ExecState* )
const
166 exec->setException(err);
172 BooleanImp* BooleanImp::staticTrue = 0;
173 BooleanImp* BooleanImp::staticFalse = 0;
180 bool BooleanImp::toBoolean(
ExecState* )
const
185 double BooleanImp::toNumber(
ExecState* )
const
187 return val ? 1.0 : 0.0;
192 return val ?
"true" :
"false";
198 args.
append(const_cast<BooleanImp*>(
this));
209 bool StringImp::toBoolean(
ExecState* )
const
211 return (val.size() > 0);
214 double StringImp::toNumber(
ExecState* )
const
216 return val.toDouble();
227 args.
append(const_cast<StringImp*>(
this));
233 NumberImp *NumberImp::staticNaN;
237 if (SimpleNumber::fits(i))
238 return SimpleNumber::make(i);
239 NumberImp *imp =
new NumberImp(static_cast<double>(i));
240 imp->setGcAllowedFast();
244 ValueImp *NumberImp::create(
double d)
246 if (SimpleNumber::fits(d))
247 return SimpleNumber::make((
int)d);
250 NumberImp *imp =
new NumberImp(d);
251 imp->setGcAllowedFast();
257 return Number((NumberImp*)
this);
260 bool NumberImp::toBoolean(
ExecState *)
const
262 return !((val == 0) || isNaN(val));
265 double NumberImp::toNumber(
ExecState *)
const
280 args.
append(const_cast<NumberImp*>(
this));
284 bool NumberImp::toUInt32(
unsigned& uint32)
const
286 uint32 = (unsigned)val;
287 return (
double)uint32 == val;
290 double SimpleNumber::negZero = -0.0;
294 LabelStack::LabelStack(
const LabelStack &other)
305 StackElem *se = other.tos;
307 StackElem *newPrev =
new StackElem;
309 newPrev->id = se->id;
325 StackElem *newtos =
new StackElem;
337 for (StackElem *curr = tos; curr; curr = curr->prev)
347 StackElem *prev = tos->prev;
353 LabelStack::~LabelStack()
358 void LabelStack::clear()
373 ContextImp::ContextImp(
Object &glob, InterpreterImp *interpreter,
Object &thisV,
int _sourceId, CodeType type,
375 : _interpreter(interpreter), _function(func), _arguments(args)
378 _callingContext = callingCon;
381 sourceId = _sourceId;
385 if (func && func->inherits(&DeclaredFunctionImp::info))
386 functionName = static_cast<DeclaredFunctionImp*>(func)->name();
391 if (type == FunctionCode) {
392 activation =
Object(
new ActivationImp(func,*args));
393 variable = activation;
402 if (_callingContext) {
403 scope = _callingContext->scopeChain();
404 #ifndef KJS_PURE_ECMA
405 if (thisV.imp() != glob.imp())
406 scope.push(thisV.imp());
408 variable = _callingContext->variableObject();
409 thisVal = _callingContext->thisValue();
414 scope.push(glob.imp());
415 #ifndef KJS_PURE_ECMA
423 scope = func->scope();
424 scope.push(activation.imp());
425 variable = activation;
430 _interpreter->setContext(
this);
433 ContextImp::~ContextImp()
435 _interpreter->setContext(_callingContext);
438 void ContextImp::mark()
440 for (
ContextImp *context =
this; context; context = context->_callingContext) {
441 context->scope.mark();
445 bool ContextImp::inTryCatch()
const
448 while (c && !c->tryCatch)
449 c = c->_callingContext;
450 return (c && c->tryCatch);
455 void SourceCode::cleanup()
457 if (interpreter && interpreter->debugger())
458 interpreter->debugger()->sourceUnused(interpreter->globalExec(),sid);
460 interpreter->removeSourceCode(
this);
466 FunctionBodyNode *Parser::progNode = 0;
468 SourceCode *Parser::source = 0;
470 FunctionBodyNode *Parser::parse(
const UChar *code,
unsigned int length, SourceCode **src,
478 Lexer::curr()->setCode(code, length);
482 source =
new SourceCode(sid);
489 int parseError = kjsyyparse();
490 if (Lexer::curr()->hadError())
492 Lexer::curr()->doneParsing();
493 FunctionBodyNode *prog = progNode;
499 int eline = Lexer::curr()->lineNo();
505 fprintf( stderr,
"[kjs-internal] %s\n",
UString(code,length).ascii() );
508 fprintf( stderr,
"[kjs-internal] KJS: JavaScript parse error at line %d.\n", eline);
514 fprintf( stderr,
"[kjs-internal] %s\n", prog->toCode().ascii() );
522 InterpreterImp* InterpreterImp::s_hook = 0L;
524 void InterpreterImp::globalInit()
527 UndefinedImp::staticUndefined =
new UndefinedImp();
528 UndefinedImp::staticUndefined->ref();
529 NullImp::staticNull =
new NullImp();
530 NullImp::staticNull->ref();
531 BooleanImp::staticTrue =
new BooleanImp(
true);
532 BooleanImp::staticTrue->ref();
533 BooleanImp::staticFalse =
new BooleanImp(
false);
534 BooleanImp::staticFalse->ref();
535 NumberImp::staticNaN =
new NumberImp(NaN);
536 NumberImp::staticNaN->ref();
539 void InterpreterImp::globalClear()
542 UndefinedImp::staticUndefined->deref();
543 UndefinedImp::staticUndefined->setGcAllowed();
544 UndefinedImp::staticUndefined = 0L;
545 NullImp::staticNull->deref();
546 NullImp::staticNull->setGcAllowed();
547 NullImp::staticNull = 0L;
548 BooleanImp::staticTrue->deref();
549 BooleanImp::staticTrue->setGcAllowed();
550 BooleanImp::staticTrue = 0L;
551 BooleanImp::staticFalse->deref();
552 BooleanImp::staticFalse->setGcAllowed();
553 BooleanImp::staticFalse = 0L;
554 NumberImp::staticNaN->deref();
555 NumberImp::staticNaN->setGcAllowed();
556 NumberImp::staticNaN = 0;
560 : m_interpreter(interp),
574 s_hook->next->prev =
this;
578 s_hook =
next = prev =
this;
583 globExec =
new ExecState(m_interpreter,0);
589 void InterpreterImp::lock()
594 void InterpreterImp::unlock()
599 void InterpreterImp::initGlobalObject()
604 b_FunctionPrototype =
Object(funcProto);
605 ObjectPrototypeImp *objProto =
new ObjectPrototypeImp(globExec,funcProto);
606 b_ObjectPrototype =
Object(objProto);
607 funcProto->setPrototype(b_ObjectPrototype);
609 ArrayPrototypeImp *arrayProto =
new ArrayPrototypeImp(globExec,objProto);
610 b_ArrayPrototype =
Object(arrayProto);
611 StringPrototypeImp *stringProto =
new StringPrototypeImp(globExec,objProto);
612 b_StringPrototype =
Object(stringProto);
613 BooleanPrototypeImp *booleanProto =
new BooleanPrototypeImp(globExec,objProto,funcProto);
614 b_BooleanPrototype =
Object(booleanProto);
615 NumberPrototypeImp *numberProto =
new NumberPrototypeImp(globExec,objProto,funcProto);
616 b_NumberPrototype =
Object(numberProto);
617 DatePrototypeImp *dateProto =
new DatePrototypeImp(globExec,objProto);
618 b_DatePrototype =
Object(dateProto);
619 RegExpPrototypeImp *regexpProto =
new RegExpPrototypeImp(globExec,objProto,funcProto);
620 b_RegExpPrototype =
Object(regexpProto);
621 ErrorPrototypeImp *errorProto =
new ErrorPrototypeImp(globExec,objProto,funcProto);
622 b_ErrorPrototype =
Object(errorProto);
624 static_cast<ObjectImp*
>(global.imp())->setPrototype(b_ObjectPrototype);
628 b_Object =
Object(
new ObjectObjectImp(globExec, objProto, funcProto));
629 b_Function =
Object(
new FunctionObjectImp(globExec, funcProto));
630 b_Array =
Object(
new ArrayObjectImp(globExec, funcProto, arrayProto));
631 b_String =
Object(
new StringObjectImp(globExec, funcProto, stringProto));
632 b_Boolean =
Object(
new BooleanObjectImp(globExec, funcProto, booleanProto));
633 b_Number =
Object(
new NumberObjectImp(globExec, funcProto, numberProto));
634 b_Date =
Object(
new DateObjectImp(globExec, funcProto, dateProto));
635 b_RegExp =
Object(
new RegExpObjectImp(globExec, funcProto, regexpProto));
636 b_Error =
Object(
new ErrorObjectImp(globExec, funcProto, errorProto));
639 b_evalErrorPrototype =
Object(
new NativeErrorPrototypeImp(globExec,errorProto,EvalError,
640 "EvalError",
"EvalError"));
641 b_rangeErrorPrototype =
Object(
new NativeErrorPrototypeImp(globExec,errorProto,RangeError,
642 "RangeError",
"RangeError"));
643 b_referenceErrorPrototype =
Object(
new NativeErrorPrototypeImp(globExec,errorProto,ReferenceError,
644 "ReferenceError",
"ReferenceError"));
645 b_syntaxErrorPrototype =
Object(
new NativeErrorPrototypeImp(globExec,errorProto,SyntaxError,
646 "SyntaxError",
"SyntaxError"));
647 b_typeErrorPrototype =
Object(
new NativeErrorPrototypeImp(globExec,errorProto,TypeError,
648 "TypeError",
"TypeError"));
649 b_uriErrorPrototype =
Object(
new NativeErrorPrototypeImp(globExec,errorProto,URIError,
650 "URIError",
"URIError"));
653 b_evalError =
Object(
new NativeErrorImp(globExec,funcProto,b_evalErrorPrototype));
654 b_rangeError =
Object(
new NativeErrorImp(globExec,funcProto,b_rangeErrorPrototype));
655 b_referenceError =
Object(
new NativeErrorImp(globExec,funcProto,b_referenceErrorPrototype));
656 b_syntaxError =
Object(
new NativeErrorImp(globExec,funcProto,b_syntaxErrorPrototype));
657 b_typeError =
Object(
new NativeErrorImp(globExec,funcProto,b_typeErrorPrototype));
658 b_uriError =
Object(
new NativeErrorImp(globExec,funcProto,b_uriErrorPrototype));
661 funcProto->put(globExec,constructorPropertyName, b_Function, DontEnum);
663 global.put(globExec,
"Object", b_Object, DontEnum);
664 global.put(globExec,
"Function", b_Function, DontEnum);
665 global.put(globExec,
"Array", b_Array, DontEnum);
666 global.put(globExec,
"Boolean", b_Boolean, DontEnum);
667 global.put(globExec,
"String", b_String, DontEnum);
668 global.put(globExec,
"Number", b_Number, DontEnum);
669 global.put(globExec,
"Date", b_Date, DontEnum);
670 global.put(globExec,
"RegExp", b_RegExp, DontEnum);
671 global.put(globExec,
"Error", b_Error, DontEnum);
674 global.put(globExec,
"EvalError",b_evalError, Internal);
675 global.put(globExec,
"RangeError",b_rangeError, Internal);
676 global.put(globExec,
"ReferenceError",b_referenceError, Internal);
677 global.put(globExec,
"SyntaxError",b_syntaxError, Internal);
678 global.put(globExec,
"TypeError",b_typeError, Internal);
679 global.put(globExec,
"URIError",b_uriError, Internal);
682 objProto->put(globExec, constructorPropertyName, b_Object, DontEnum | DontDelete | ReadOnly);
683 funcProto->put(globExec, constructorPropertyName, b_Function, DontEnum | DontDelete | ReadOnly);
684 arrayProto->put(globExec, constructorPropertyName, b_Array, DontEnum | DontDelete | ReadOnly);
685 booleanProto->put(globExec, constructorPropertyName, b_Boolean, DontEnum | DontDelete | ReadOnly);
686 stringProto->put(globExec, constructorPropertyName, b_String, DontEnum | DontDelete | ReadOnly);
687 numberProto->put(globExec, constructorPropertyName, b_Number, DontEnum | DontDelete | ReadOnly);
688 dateProto->put(globExec, constructorPropertyName, b_Date, DontEnum | DontDelete | ReadOnly);
689 regexpProto->put(globExec, constructorPropertyName, b_RegExp, DontEnum | DontDelete | ReadOnly);
690 errorProto->put(globExec, constructorPropertyName, b_Error, DontEnum | DontDelete | ReadOnly);
691 b_evalErrorPrototype.put(globExec, constructorPropertyName, b_evalError, DontEnum | DontDelete | ReadOnly);
692 b_rangeErrorPrototype.put(globExec, constructorPropertyName, b_rangeError, DontEnum | DontDelete | ReadOnly);
693 b_referenceErrorPrototype.put(globExec, constructorPropertyName, b_referenceError, DontEnum | DontDelete | ReadOnly);
694 b_syntaxErrorPrototype.put(globExec, constructorPropertyName, b_syntaxError, DontEnum | DontDelete | ReadOnly);
695 b_typeErrorPrototype.put(globExec, constructorPropertyName, b_typeError, DontEnum | DontDelete | ReadOnly);
696 b_uriErrorPrototype.put(globExec, constructorPropertyName, b_uriError, DontEnum | DontDelete | ReadOnly);
699 global.put(globExec,
"NaN",
Number(NaN), DontEnum|DontDelete);
700 global.put(globExec,
"Infinity",
Number(Inf), DontEnum|DontDelete);
701 global.put(globExec,
"undefined",
Undefined(), DontEnum|DontDelete);
704 #ifdef KJS_PURE_ECMA // otherwise as deprecated Object.prototype property
705 global.put(globExec,
"eval",
706 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::Eval,1,
"eval")), DontEnum);
708 global.put(globExec,
"parseInt",
709 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::ParseInt,2,
"parseInt")), DontEnum);
710 global.put(globExec,
"parseFloat",
711 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::ParseFloat,1,
"parseFloat")), DontEnum);
712 global.put(globExec,
"isNaN",
713 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::IsNaN,1,
"isNaN")), DontEnum);
714 global.put(globExec,
"isFinite",
715 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::IsFinite,1,
"isFinite")), DontEnum);
716 global.put(globExec,
"decodeURI",
717 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::DecodeURI,1,
"decodeURI")),
719 global.put(globExec,
"decodeURIComponent",
720 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::DecodeURIComponent,1,
"decodeURIComponent")),
722 global.put(globExec,
"encodeURI",
723 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::EncodeURI,1,
"encodeURI")),
725 global.put(globExec,
"encodeURIComponent",
726 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::EncodeURIComponent,1,
"encodeURIComponent")),
728 global.put(globExec,
"escape",
729 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::Escape,1,
"escape")), DontEnum);
730 global.put(globExec,
"unescape",
731 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::UnEscape,1,
"unescape")), DontEnum);
733 global.put(globExec,
"kjsprint",
734 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::KJSPrint,1,
"kjsprint")), DontEnum);
738 global.put(globExec,
"Math",
Object(
new MathObjectImp(globExec,objProto)), DontEnum);
741 InterpreterImp::~InterpreterImp()
744 dbg->detach(m_interpreter);
745 for (SourceCode *s = sources; s; s = s->next)
752 void InterpreterImp::clear()
769 void InterpreterImp::mark()
775 if (UndefinedImp::staticUndefined && !UndefinedImp::staticUndefined->marked())
776 UndefinedImp::staticUndefined->mark();
777 if (NullImp::staticNull && !NullImp::staticNull->marked())
778 NullImp::staticNull->mark();
779 if (NumberImp::staticNaN && !NumberImp::staticNaN->marked())
780 NumberImp::staticNaN->mark();
781 if (BooleanImp::staticTrue && !BooleanImp::staticTrue->marked())
782 BooleanImp::staticTrue->mark();
783 if (BooleanImp::staticFalse && !BooleanImp::staticFalse->marked())
784 BooleanImp::staticFalse->mark();
787 global.imp()->mark();
789 m_interpreter->mark();
794 bool InterpreterImp::checkSyntax(
const UString &code,
int *errLine,
UString *errMsg)
798 FunctionBodyNode *progNode = Parser::parse(code.
data(),code.
size(),&source,errLine,errMsg);
800 bool ok = (progNode != 0);
805 bool InterpreterImp::checkSyntax(
const UString &code)
809 FunctionBodyNode *progNode = Parser::parse(code.
data(),code.
size(),&source,0,0);
811 bool ok = (progNode != 0);
821 if (recursion >= 20) {
831 FunctionBodyNode *progNode = Parser::parse(code.
data(),code.
size(),&source,&errLine,&errMsg);
835 bool cont = dbg->sourceParsed(globExec,source->sid,code,errLine);
845 addSourceCode(source);
850 err.
put(globExec,
"sid",
Number(source->sid));
851 globExec->setException(err);
852 globExec->clearException();
859 globExec->clearException();
864 Object &globalObj = globalObject();
865 Object thisObj = globalObject();
869 if (thisV.
isA(NullType) || thisV.
isA(UndefinedType))
870 thisObj = globalObject();
877 if (globExec->hadException()) {
880 res =
Completion(Throw,globExec->exception());
884 ContextImp ctx(globalObj,
this, thisObj, source->sid);
889 progNode->processVarDecls(&newExec);
891 ctx.setLines(progNode->firstLine(),progNode->firstLine());
894 if (!dbg->enterContext(&newExec)) {
902 ctx.setLines(progNode->lastLine(),progNode->lastLine());
903 res = progNode->execute(&newExec);
904 if (dbg && !dbg->exitContext(&newExec,res)) {
913 if (progNode->deref())
917 if (globExec->hadException()) {
918 res =
Completion(Throw,globExec->exception());
919 globExec->clearException();
926 void InterpreterImp::setDebugger(Debugger *d)
934 old->detach(m_interpreter);
937 void InterpreterImp::addSourceCode(SourceCode *code)
940 assert(!code->interpreter);
941 code->next = sources;
942 code->interpreter =
this;
946 void InterpreterImp::removeSourceCode(SourceCode *code)
951 if (code == sources) {
952 sources = sources->next;
956 SourceCode *prev = sources;
957 SourceCode *cur = sources->next;
958 while (cur != code) {
964 prev->next = cur->next;
969 const ClassInfo InternalFunctionImp::info = {
"Function", 0, 0, 0};
972 : ObjectImp(funcProto)
977 : ObjectImp(static_cast<
FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp()))
981 bool InternalFunctionImp::implementsHasInstance()
const
988 if (value.
type() != ObjectType)
991 Value prot =
get(exec,prototypePropertyName);
992 if (prot.
type() != ObjectType && prot.
type() != NullType) {
994 "in instanceof operation.");
995 exec->setException(err);
999 Object v =
Object(static_cast<ObjectImp*>(value.imp()));
1001 if (v.imp() == prot.imp())
1012 if (isNaN(n) || isInf(n))
1014 double an = fabs(n);
1017 double d = floor(an);
1026 void KJS::printInfo(
ExecState *exec,
const char *s,
const Value &o,
int lineno)
1029 fprintf(stderr,
"KJS: %s: (null)", s);
1032 unsigned int arrayLength = 0;
1033 bool hadExcep = exec->hadException();
1036 switch ( v.
type() ) {
1037 case UnspecifiedType:
1038 name =
"Unspecified";
1059 name =
"(unknown class)";
1060 if ( obj.inherits(&ArrayInstanceImp::info) )
1061 arrayLength = obj.
get(exec,lengthPropertyName).
toUInt32(exec);
1067 if ( arrayLength > 100 )
1072 exec->clearException();
1073 if ( vString.
size() > 50 )
1074 vString = vString.
substr( 0, 50 ) +
"...";
1078 fprintf(stderr,
"KJS: %s: %s : %s (%p)",
1079 s, tempString.c_str(), name.
ascii(), (
void*)v.imp());
1082 fprintf(stderr,
", line %d\n",lineno);
1084 fprintf(stderr,
"\n");