webengine/osswebengine/JavaScriptCore/kjs/interpreter.cpp
changeset 0 dd21522fd290
child 13 10e98eab6f85
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 // -*- c-basic-offset: 2 -*-
       
     2 /*
       
     3  *  This file is part of the KDE libraries
       
     4  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
       
     5  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
       
     6  *  Copyright (C) 2003 Apple Computer, Inc.
       
     7  *
       
     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.
       
    12  *
       
    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.
       
    17  *
       
    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., 51 Franklin Street, Fifth Floor,
       
    21  *  Boston, MA 02110-1301, USA.
       
    22  *
       
    23  */
       
    24 
       
    25 #include "config.h"
       
    26 #include "interpreter.h"
       
    27 
       
    28 #include "SavedBuiltins.h"
       
    29 #include "array_object.h"
       
    30 #include "bool_object.h"
       
    31 #include "collector.h"
       
    32 #include "context.h"
       
    33 #include "date_object.h"
       
    34 #include "debugger.h"
       
    35 #include "error_object.h"
       
    36 #include "function_object.h"
       
    37 #include "internal.h"
       
    38 #include "math_object.h"
       
    39 #include "nodes.h"
       
    40 #include "number_object.h"
       
    41 #include "object.h"
       
    42 #include "object_object.h"
       
    43 #include "operations.h"
       
    44 #include "regexp_object.h"
       
    45 #include "string_object.h"
       
    46 #include "types.h"
       
    47 #include "value.h"
       
    48 
       
    49 #include "runtime.h"
       
    50 
       
    51 #if HAVE(SYS_TIME_H)
       
    52 #include <sys/time.h>
       
    53 #endif
       
    54 
       
    55 #include <assert.h>
       
    56 #include <math.h>
       
    57 #include <signal.h>
       
    58 #include <stdio.h>
       
    59 
       
    60 #if PLATFORM(WIN_OS)
       
    61 #include <windows.h>
       
    62 #endif
       
    63 
       
    64 #if PLATFORM(QT)
       
    65 #include <QDateTime>
       
    66 #endif
       
    67 
       
    68 #if PLATFORM(SYMBIAN)
       
    69 #include "oom.h"
       
    70 #endif
       
    71 
       
    72 namespace KJS {
       
    73 
       
    74 // Default number of ticks before a timeout check should be done.
       
    75 static const int initialTickCountThreshold = 255;
       
    76 
       
    77 // Preferred number of milliseconds between each timeout check
       
    78 static const int preferredScriptCheckTimeInterval = 1000;
       
    79 
       
    80 Interpreter* Interpreter::s_hook = 0;
       
    81     
       
    82 typedef HashMap<JSObject*, Interpreter*> InterpreterMap;
       
    83 static inline InterpreterMap &interpreterMap()
       
    84 {
       
    85     static InterpreterMap* map = new InterpreterMap;
       
    86     return* map;
       
    87 }
       
    88     
       
    89 EXPORT
       
    90 Interpreter::Interpreter(JSObject* globalObject)
       
    91     : m_globalExec(this, 0)
       
    92     , m_globalObject(globalObject)
       
    93 {
       
    94     init();
       
    95 }
       
    96 
       
    97 Interpreter::Interpreter()
       
    98     : m_globalExec(this, 0)
       
    99     , m_globalObject(new JSObject())
       
   100 {
       
   101     init();
       
   102 }
       
   103 
       
   104 void Interpreter::init()
       
   105 {
       
   106     JSLock lock;
       
   107 
       
   108     m_refCount = 0;
       
   109     m_timeoutTime = 0;
       
   110     m_recursion = 0;
       
   111     m_debugger= 0;
       
   112     m_context = 0;
       
   113 
       
   114     resetTimeoutCheck();
       
   115     m_timeoutCheckCount = 0;
       
   116     
       
   117     m_compatMode = NativeMode;
       
   118 
       
   119     if (s_hook) {
       
   120         prev = s_hook;
       
   121         next = s_hook->next;
       
   122         s_hook->next->prev = this;
       
   123         s_hook->next = this;
       
   124     } else {
       
   125         // This is the first interpreter
       
   126         s_hook = next = prev = this;
       
   127     }
       
   128     interpreterMap().set(m_globalObject, this);
       
   129 
       
   130     initGlobalObject();
       
   131 }
       
   132 
       
   133 EXPORT
       
   134 Interpreter::~Interpreter()
       
   135 {
       
   136     JSLock lock;
       
   137     
       
   138     if (m_debugger)
       
   139         m_debugger->detach(this);
       
   140 
       
   141     next->prev = prev;
       
   142     prev->next = next;
       
   143     s_hook = next;
       
   144     if (s_hook == this) {
       
   145         // This was the last interpreter
       
   146         s_hook = 0;
       
   147     }
       
   148     interpreterMap().remove(m_globalObject);
       
   149 }
       
   150 
       
   151 EXPORT
       
   152 JSObject* Interpreter::globalObject() const
       
   153 {
       
   154   return m_globalObject;
       
   155 }
       
   156 
       
   157 EXPORT
       
   158 void Interpreter::initGlobalObject()
       
   159 {
       
   160     // Clear before inititalizing, to avoid marking uninitialized (dangerous) or 
       
   161     // stale (wasteful) pointers during initialization.
       
   162 
       
   163     // Prototypes
       
   164     m_FunctionPrototype = 0;
       
   165     m_ObjectPrototype = 0;
       
   166 
       
   167     m_ArrayPrototype = 0;
       
   168     m_StringPrototype = 0;
       
   169     m_BooleanPrototype = 0;
       
   170     m_NumberPrototype = 0;
       
   171     m_DatePrototype = 0;
       
   172     m_RegExpPrototype = 0;
       
   173     m_ErrorPrototype = 0;
       
   174     
       
   175     m_EvalErrorPrototype = 0;
       
   176     m_RangeErrorPrototype = 0;
       
   177     m_ReferenceErrorPrototype = 0;
       
   178     m_SyntaxErrorPrototype = 0;
       
   179     m_TypeErrorPrototype = 0;
       
   180     m_UriErrorPrototype = 0;
       
   181 
       
   182     // Constructors
       
   183     m_Object = 0;
       
   184     m_Function = 0;
       
   185     m_Array = 0;
       
   186     m_String = 0;
       
   187     m_Boolean = 0;
       
   188     m_Number = 0;
       
   189     m_Date = 0;
       
   190     m_RegExp = 0;
       
   191     m_Error = 0;
       
   192     
       
   193     m_EvalError = 0;
       
   194     m_RangeError = 0;
       
   195     m_ReferenceError = 0;
       
   196     m_SyntaxError = 0;
       
   197     m_TypeError = 0;
       
   198     m_UriError = 0;
       
   199 
       
   200     // Prototypes
       
   201     m_FunctionPrototype = new FunctionPrototype(&m_globalExec);
       
   202     m_ObjectPrototype = new ObjectPrototype(&m_globalExec, m_FunctionPrototype);
       
   203     m_FunctionPrototype->setPrototype(m_ObjectPrototype);
       
   204     
       
   205     m_ArrayPrototype = new ArrayPrototype(&m_globalExec, m_ObjectPrototype);
       
   206     m_StringPrototype = new StringPrototype(&m_globalExec, m_ObjectPrototype);
       
   207     m_BooleanPrototype = new BooleanPrototype(&m_globalExec, m_ObjectPrototype, m_FunctionPrototype);
       
   208     m_NumberPrototype = new NumberPrototype(&m_globalExec, m_ObjectPrototype, m_FunctionPrototype);
       
   209     m_DatePrototype = new DatePrototype(&m_globalExec, m_ObjectPrototype);
       
   210     m_RegExpPrototype = new RegExpPrototype(&m_globalExec, m_ObjectPrototype, m_FunctionPrototype);;
       
   211     m_ErrorPrototype = new ErrorPrototype(&m_globalExec, m_ObjectPrototype, m_FunctionPrototype);
       
   212     
       
   213     m_EvalErrorPrototype = new NativeErrorPrototype(&m_globalExec, m_ErrorPrototype, EvalError, "EvalError", "EvalError");
       
   214     m_RangeErrorPrototype = new NativeErrorPrototype(&m_globalExec, m_ErrorPrototype, RangeError, "RangeError", "RangeError");
       
   215     m_ReferenceErrorPrototype = new NativeErrorPrototype(&m_globalExec, m_ErrorPrototype, ReferenceError, "ReferenceError", "ReferenceError");
       
   216     m_SyntaxErrorPrototype = new NativeErrorPrototype(&m_globalExec, m_ErrorPrototype, SyntaxError, "SyntaxError", "SyntaxError");
       
   217     m_TypeErrorPrototype = new NativeErrorPrototype(&m_globalExec, m_ErrorPrototype, TypeError, "TypeError", "TypeError");
       
   218     m_UriErrorPrototype = new NativeErrorPrototype(&m_globalExec, m_ErrorPrototype, URIError, "URIError", "URIError");
       
   219 
       
   220     // Constructors
       
   221     m_Object = new ObjectObjectImp(&m_globalExec, m_ObjectPrototype, m_FunctionPrototype);
       
   222     m_Function = new FunctionObjectImp(&m_globalExec, m_FunctionPrototype);
       
   223     m_Array = new ArrayObjectImp(&m_globalExec, m_FunctionPrototype, m_ArrayPrototype);
       
   224     m_String = new StringObjectImp(&m_globalExec, m_FunctionPrototype, m_StringPrototype);
       
   225     m_Boolean = new BooleanObjectImp(&m_globalExec, m_FunctionPrototype, m_BooleanPrototype);
       
   226     m_Number = new NumberObjectImp(&m_globalExec, m_FunctionPrototype, m_NumberPrototype);
       
   227     m_Date = new DateObjectImp(&m_globalExec, m_FunctionPrototype, m_DatePrototype);
       
   228     m_RegExp = new RegExpObjectImp(&m_globalExec, m_FunctionPrototype, m_RegExpPrototype);
       
   229     m_Error = new ErrorObjectImp(&m_globalExec, m_FunctionPrototype, m_ErrorPrototype);
       
   230     
       
   231     m_EvalError = new NativeErrorImp(&m_globalExec, m_FunctionPrototype, m_EvalErrorPrototype);
       
   232     m_RangeError = new NativeErrorImp(&m_globalExec, m_FunctionPrototype, m_RangeErrorPrototype);
       
   233     m_ReferenceError = new NativeErrorImp(&m_globalExec, m_FunctionPrototype, m_ReferenceErrorPrototype);
       
   234     m_SyntaxError = new NativeErrorImp(&m_globalExec, m_FunctionPrototype, m_SyntaxErrorPrototype);
       
   235     m_TypeError = new NativeErrorImp(&m_globalExec, m_FunctionPrototype, m_TypeErrorPrototype);
       
   236     m_UriError = new NativeErrorImp(&m_globalExec, m_FunctionPrototype, m_UriErrorPrototype);
       
   237     
       
   238     m_FunctionPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Function, DontEnum);
       
   239     m_ObjectPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Object, DontEnum | DontDelete | ReadOnly);
       
   240     m_FunctionPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Function, DontEnum | DontDelete | ReadOnly);
       
   241     m_ArrayPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Array, DontEnum | DontDelete | ReadOnly);
       
   242     m_BooleanPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Boolean, DontEnum | DontDelete | ReadOnly);
       
   243     m_StringPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_String, DontEnum | DontDelete | ReadOnly);
       
   244     m_NumberPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Number, DontEnum | DontDelete | ReadOnly);
       
   245     m_DatePrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Date, DontEnum | DontDelete | ReadOnly);
       
   246     m_RegExpPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_RegExp, DontEnum | DontDelete | ReadOnly);
       
   247     m_ErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Error, DontEnum | DontDelete | ReadOnly);
       
   248     m_EvalErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_EvalError, DontEnum | DontDelete | ReadOnly);
       
   249     m_RangeErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_RangeError, DontEnum | DontDelete | ReadOnly);
       
   250     m_ReferenceErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_ReferenceError, DontEnum | DontDelete | ReadOnly);
       
   251     m_SyntaxErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_SyntaxError, DontEnum | DontDelete | ReadOnly);
       
   252     m_TypeErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_TypeError, DontEnum | DontDelete | ReadOnly);
       
   253     m_UriErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_UriError, DontEnum | DontDelete | ReadOnly);
       
   254 
       
   255     // Set global object prototype
       
   256     JSObject* o = m_globalObject;
       
   257     while (o->prototype()->isObject())
       
   258         o = static_cast<JSObject*>(o->prototype());
       
   259     o->setPrototype(m_ObjectPrototype);
       
   260 
       
   261     // Set global constructors
       
   262     // FIXME: kjs_window.cpp checks Internal/DontEnum as a performance hack, to
       
   263     // see that these values can be put directly without a check for override
       
   264     // properties. Maybe we should call putDirect instead, for better encapsulation.
       
   265     m_globalObject->put(&m_globalExec, "Object", m_Object, DontEnum);
       
   266     m_globalObject->put(&m_globalExec, "Function", m_Function, DontEnum);
       
   267     m_globalObject->put(&m_globalExec, "Array", m_Array, DontEnum);
       
   268     m_globalObject->put(&m_globalExec, "Boolean", m_Boolean, DontEnum);
       
   269     m_globalObject->put(&m_globalExec, "String", m_String, DontEnum);
       
   270     m_globalObject->put(&m_globalExec, "Number", m_Number, DontEnum);
       
   271     m_globalObject->put(&m_globalExec, "Date", m_Date, DontEnum);
       
   272     m_globalObject->put(&m_globalExec, "RegExp", m_RegExp, DontEnum);
       
   273     m_globalObject->put(&m_globalExec, "Error", m_Error, DontEnum);
       
   274     m_globalObject->put(&m_globalExec, "EvalError",m_EvalError, Internal);
       
   275     m_globalObject->put(&m_globalExec, "RangeError",m_RangeError, Internal);
       
   276     m_globalObject->put(&m_globalExec, "ReferenceError",m_ReferenceError, Internal);
       
   277     m_globalObject->put(&m_globalExec, "SyntaxError",m_SyntaxError, Internal);
       
   278     m_globalObject->put(&m_globalExec, "TypeError",m_TypeError, Internal);
       
   279     m_globalObject->put(&m_globalExec, "URIError",m_UriError, Internal);
       
   280 
       
   281     // Set global values
       
   282     m_globalObject->put(&m_globalExec, "Math", new MathObjectImp(&m_globalExec, m_ObjectPrototype), DontEnum);
       
   283     m_globalObject->put(&m_globalExec, "NaN", jsNaN(), DontEnum|DontDelete);
       
   284     m_globalObject->put(&m_globalExec, "Infinity", jsNumber(Inf), DontEnum|DontDelete);
       
   285     m_globalObject->put(&m_globalExec, "undefined", jsUndefined(), DontEnum|DontDelete);
       
   286     
       
   287     // Set global functions
       
   288     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::Eval, 1, "eval"), DontEnum);
       
   289     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::ParseInt, 2, "parseInt"), DontEnum);
       
   290     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::ParseFloat, 1, "parseFloat"), DontEnum);
       
   291     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::IsNaN, 1, "isNaN"), DontEnum);
       
   292     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::IsFinite, 1, "isFinite"), DontEnum);
       
   293     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::Escape, 1, "escape"), DontEnum);
       
   294     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::UnEscape, 1, "unescape"), DontEnum);
       
   295     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::DecodeURI, 1, "decodeURI"), DontEnum);
       
   296     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::DecodeURIComponent, 1, "decodeURIComponent"), DontEnum);
       
   297     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::EncodeURI, 1, "encodeURI"), DontEnum);
       
   298     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::EncodeURIComponent, 1, "encodeURIComponent"), DontEnum);
       
   299 #ifndef NDEBUG
       
   300     m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::KJSPrint, 1, "kjsprint"), DontEnum);
       
   301 #endif
       
   302 }
       
   303 
       
   304 EXPORT
       
   305 ExecState* Interpreter::globalExec()
       
   306 {
       
   307   return &m_globalExec;
       
   308 }
       
   309 
       
   310 Completion Interpreter::checkSyntax(const UString& sourceURL, int startingLineNumber, const UString& code)
       
   311 {
       
   312     return checkSyntax(sourceURL, startingLineNumber, code.data(), code.size());
       
   313 }
       
   314 
       
   315 Completion Interpreter::checkSyntax(const UString& sourceURL, int startingLineNumber, const UChar* code, int codeLength)
       
   316 {
       
   317     JSLock lock;
       
   318 
       
   319     int errLine;
       
   320     UString errMsg;
       
   321     RefPtr<ProgramNode> progNode = Parser::parse(sourceURL, startingLineNumber, code, codeLength, 0, &errLine, &errMsg);
       
   322     if (!progNode)
       
   323         return Completion(Throw, Error::create(&m_globalExec, SyntaxError, errMsg, errLine, 0, sourceURL));
       
   324     return Completion(Normal);
       
   325 }
       
   326 
       
   327 EXPORT
       
   328 Completion Interpreter::evaluate(const UString& sourceURL, int startingLineNumber, const UString& code, JSValue* thisV)
       
   329 {
       
   330     return evaluate(sourceURL, startingLineNumber, code.data(), code.size(), thisV);
       
   331 }
       
   332 
       
   333 EXPORT
       
   334 Completion Interpreter::evaluate(const UString& sourceURL, int startingLineNumber, const UChar* code, int codeLength, JSValue* thisV)
       
   335 {
       
   336 #if PLATFORM(SYMBIAN)
       
   337     resetStatementCount();
       
   338     // add 2MB memory hard limit for the JS engine to run
       
   339     OOM_PRE_CHECK(2*1024*1024, 0, "InterpreterImp::evaluate")
       
   340       // do nothing
       
   341     OOM_POST_CHECK_FAILED(      
       
   342         JSObject *error = Error::create(&m_globalExec, GeneralError, "Out of memory.");
       
   343         m_globalExec.setException(error);
       
   344         return Completion(Throw, error)
       
   345     )
       
   346 #endif
       
   347 
       
   348     JSLock lock;
       
   349     
       
   350     // prevent against infinite recursion
       
   351     if (m_recursion >= 20)
       
   352         return Completion(Throw, Error::create(&m_globalExec, GeneralError, "Recursion too deep"));
       
   353     
       
   354     // parse the source code
       
   355     int sid;
       
   356     int errLine;
       
   357     UString errMsg;
       
   358     RefPtr<ProgramNode> progNode = Parser::parse(sourceURL, startingLineNumber, code, codeLength, &sid, &errLine, &errMsg);
       
   359     
       
   360     // notify debugger that source has been parsed
       
   361     if (m_debugger) {
       
   362         bool cont = m_debugger->sourceParsed(&m_globalExec, sid, sourceURL, UString(code, codeLength), startingLineNumber, errLine, errMsg);
       
   363         if (!cont)
       
   364             return Completion(Break);
       
   365     }
       
   366     
       
   367     // no program node means a syntax error occurred
       
   368     if (!progNode)
       
   369         return Completion(Throw, Error::create(&m_globalExec, SyntaxError, errMsg, errLine, sid, sourceURL));
       
   370     
       
   371     m_globalExec.clearException();
       
   372     
       
   373     m_recursion++;
       
   374     
       
   375     JSObject* globalObj = m_globalObject;
       
   376     JSObject* thisObj = globalObj;
       
   377     
       
   378     // "this" must be an object... use same rules as Function.prototype.apply()
       
   379     if (thisV && !thisV->isUndefinedOrNull())
       
   380         thisObj = thisV->toObject(&m_globalExec);
       
   381     
       
   382     Completion res;
       
   383     if (m_globalExec.hadException())
       
   384         // the thisV->toObject() conversion above might have thrown an exception - if so, propagate it
       
   385         res = Completion(Throw, m_globalExec.exception());
       
   386     else {
       
   387         // execute the code
       
   388         Context ctx(globalObj, this, thisObj, progNode.get());
       
   389         ExecState newExec(this, &ctx);
       
   390         ctx.setExecState(&newExec);
       
   391         progNode->processVarDecls(&newExec);
       
   392         res = progNode->execute(&newExec);
       
   393     }
       
   394     
       
   395     m_recursion--;
       
   396     
       
   397     if (shouldPrintExceptions() && res.complType() == Throw) {
       
   398         JSLock lock;
       
   399         ExecState* exec = globalExec();
       
   400         CString f = sourceURL.UTF8String();
       
   401         CString message = res.value()->toObject(exec)->toString(exec).UTF8String();
       
   402         int line = res.value()->toObject(exec)->get(exec, "line")->toUInt32(exec);
       
   403 #if PLATFORM(WIN_OS) || PLATFORM(SYMBIAN)
       
   404         printf("%s line %d: %s\n", f.c_str(), line, message.c_str());
       
   405 #else
       
   406         printf("[%d] %s line %d: %s\n", getpid(), f.c_str(), line, message.c_str());
       
   407 #endif
       
   408     }
       
   409 
       
   410     return res;
       
   411 }
       
   412 
       
   413 JSObject *Interpreter::builtinObject() const
       
   414 {
       
   415   return m_Object;
       
   416 }
       
   417 
       
   418 EXPORT
       
   419 JSObject *Interpreter::builtinFunction() const
       
   420 {
       
   421   return m_Function;
       
   422 }
       
   423 
       
   424 EXPORT
       
   425 JSObject *Interpreter::builtinArray() const
       
   426 {
       
   427   return m_Array;
       
   428 }
       
   429 
       
   430 JSObject *Interpreter::builtinBoolean() const
       
   431 {
       
   432   return m_Boolean;
       
   433 }
       
   434 
       
   435 JSObject *Interpreter::builtinString() const
       
   436 {
       
   437   return m_String;
       
   438 }
       
   439 
       
   440 JSObject *Interpreter::builtinNumber() const
       
   441 {
       
   442   return m_Number;
       
   443 }
       
   444 
       
   445 JSObject *Interpreter::builtinDate() const
       
   446 {
       
   447   return m_Date;
       
   448 }
       
   449 
       
   450 JSObject *Interpreter::builtinRegExp() const
       
   451 {
       
   452   return m_RegExp;
       
   453 }
       
   454 
       
   455 JSObject *Interpreter::builtinError() const
       
   456 {
       
   457   return m_Error;
       
   458 }
       
   459 
       
   460 EXPORT
       
   461 JSObject *Interpreter::builtinObjectPrototype() const
       
   462 {
       
   463   return m_ObjectPrototype;
       
   464 }
       
   465 
       
   466 EXPORT
       
   467 JSObject *Interpreter::builtinFunctionPrototype() const
       
   468 {
       
   469   return m_FunctionPrototype;
       
   470 }
       
   471 
       
   472 JSObject *Interpreter::builtinArrayPrototype() const
       
   473 {
       
   474   return m_ArrayPrototype;
       
   475 }
       
   476 
       
   477 JSObject *Interpreter::builtinBooleanPrototype() const
       
   478 {
       
   479   return m_BooleanPrototype;
       
   480 }
       
   481 
       
   482 EXPORT
       
   483 JSObject *Interpreter::builtinStringPrototype() const
       
   484 {
       
   485   return m_StringPrototype;
       
   486 }
       
   487 
       
   488 JSObject *Interpreter::builtinNumberPrototype() const
       
   489 {
       
   490   return m_NumberPrototype;
       
   491 }
       
   492 
       
   493 JSObject *Interpreter::builtinDatePrototype() const
       
   494 {
       
   495   return m_DatePrototype;
       
   496 }
       
   497 
       
   498 JSObject *Interpreter::builtinRegExpPrototype() const
       
   499 {
       
   500   return m_RegExpPrototype;
       
   501 }
       
   502 
       
   503 JSObject *Interpreter::builtinErrorPrototype() const
       
   504 {
       
   505   return m_ErrorPrototype;
       
   506 }
       
   507 
       
   508 JSObject *Interpreter::builtinEvalError() const
       
   509 {
       
   510   return m_EvalError;
       
   511 }
       
   512 
       
   513 JSObject *Interpreter::builtinRangeError() const
       
   514 {
       
   515   return m_RangeError;
       
   516 }
       
   517 
       
   518 JSObject *Interpreter::builtinReferenceError() const
       
   519 {
       
   520   return m_ReferenceError;
       
   521 }
       
   522 
       
   523 JSObject *Interpreter::builtinSyntaxError() const
       
   524 {
       
   525   return m_SyntaxError;
       
   526 }
       
   527 
       
   528 JSObject *Interpreter::builtinTypeError() const
       
   529 {
       
   530   return m_TypeError;
       
   531 }
       
   532 
       
   533 JSObject *Interpreter::builtinURIError() const
       
   534 {
       
   535   return m_UriError;
       
   536 }
       
   537 
       
   538 JSObject *Interpreter::builtinEvalErrorPrototype() const
       
   539 {
       
   540   return m_EvalErrorPrototype;
       
   541 }
       
   542 
       
   543 JSObject *Interpreter::builtinRangeErrorPrototype() const
       
   544 {
       
   545   return m_RangeErrorPrototype;
       
   546 }
       
   547 
       
   548 JSObject *Interpreter::builtinReferenceErrorPrototype() const
       
   549 {
       
   550   return m_ReferenceErrorPrototype;
       
   551 }
       
   552 
       
   553 JSObject *Interpreter::builtinSyntaxErrorPrototype() const
       
   554 {
       
   555   return m_SyntaxErrorPrototype;
       
   556 }
       
   557 
       
   558 JSObject *Interpreter::builtinTypeErrorPrototype() const
       
   559 {
       
   560   return m_TypeErrorPrototype;
       
   561 }
       
   562 
       
   563 JSObject *Interpreter::builtinURIErrorPrototype() const
       
   564 {
       
   565   return m_UriErrorPrototype;
       
   566 }
       
   567 
       
   568 EXPORT
       
   569 void Interpreter::mark()
       
   570 {
       
   571     if (m_context)
       
   572         m_context->mark();
       
   573 
       
   574     if (m_globalExec.exception() && !m_globalExec.exception()->marked())
       
   575         m_globalExec.exception()->mark();
       
   576 
       
   577     if (m_globalObject && !m_globalObject->marked())
       
   578         m_globalObject->mark();
       
   579 
       
   580     if (m_Object && !m_Object->marked())
       
   581         m_Object->mark();
       
   582     if (m_Function && !m_Function->marked())
       
   583         m_Function->mark();
       
   584     if (m_Array && !m_Array->marked())
       
   585         m_Array->mark();
       
   586     if (m_Boolean && !m_Boolean->marked())
       
   587         m_Boolean->mark();
       
   588     if (m_String && !m_String->marked())
       
   589         m_String->mark();
       
   590     if (m_Number && !m_Number->marked())
       
   591         m_Number->mark();
       
   592     if (m_Date && !m_Date->marked())
       
   593         m_Date->mark();
       
   594     if (m_RegExp && !m_RegExp->marked())
       
   595         m_RegExp->mark();
       
   596     if (m_Error && !m_Error->marked())
       
   597         m_Error->mark();
       
   598     
       
   599     if (m_ObjectPrototype && !m_ObjectPrototype->marked())
       
   600         m_ObjectPrototype->mark();
       
   601     if (m_FunctionPrototype && !m_FunctionPrototype->marked())
       
   602         m_FunctionPrototype->mark();
       
   603     if (m_ArrayPrototype && !m_ArrayPrototype->marked())
       
   604         m_ArrayPrototype->mark();
       
   605     if (m_BooleanPrototype && !m_BooleanPrototype->marked())
       
   606         m_BooleanPrototype->mark();
       
   607     if (m_StringPrototype && !m_StringPrototype->marked())
       
   608         m_StringPrototype->mark();
       
   609     if (m_NumberPrototype && !m_NumberPrototype->marked())
       
   610         m_NumberPrototype->mark();
       
   611     if (m_DatePrototype && !m_DatePrototype->marked())
       
   612         m_DatePrototype->mark();
       
   613     if (m_RegExpPrototype && !m_RegExpPrototype->marked())
       
   614         m_RegExpPrototype->mark();
       
   615     if (m_ErrorPrototype && !m_ErrorPrototype->marked())
       
   616         m_ErrorPrototype->mark();
       
   617     
       
   618     if (m_EvalError && !m_EvalError->marked())
       
   619         m_EvalError->mark();
       
   620     if (m_RangeError && !m_RangeError->marked())
       
   621         m_RangeError->mark();
       
   622     if (m_ReferenceError && !m_ReferenceError->marked())
       
   623         m_ReferenceError->mark();
       
   624     if (m_SyntaxError && !m_SyntaxError->marked())
       
   625         m_SyntaxError->mark();
       
   626     if (m_TypeError && !m_TypeError->marked())
       
   627         m_TypeError->mark();
       
   628     if (m_UriError && !m_UriError->marked())
       
   629         m_UriError->mark();
       
   630     
       
   631     if (m_EvalErrorPrototype && !m_EvalErrorPrototype->marked())
       
   632         m_EvalErrorPrototype->mark();
       
   633     if (m_RangeErrorPrototype && !m_RangeErrorPrototype->marked())
       
   634         m_RangeErrorPrototype->mark();
       
   635     if (m_ReferenceErrorPrototype && !m_ReferenceErrorPrototype->marked())
       
   636         m_ReferenceErrorPrototype->mark();
       
   637     if (m_SyntaxErrorPrototype && !m_SyntaxErrorPrototype->marked())
       
   638         m_SyntaxErrorPrototype->mark();
       
   639     if (m_TypeErrorPrototype && !m_TypeErrorPrototype->marked())
       
   640         m_TypeErrorPrototype->mark();
       
   641     if (m_UriErrorPrototype && !m_UriErrorPrototype->marked())
       
   642         m_UriErrorPrototype->mark();
       
   643 }
       
   644 
       
   645 Interpreter* Interpreter::interpreterWithGlobalObject(JSObject* globalObject)
       
   646 {
       
   647     return interpreterMap().get(globalObject);
       
   648 }
       
   649 
       
   650 #ifdef KJS_DEBUG_MEM
       
   651 #include "lexer.h"
       
   652 void Interpreter::finalCheck()
       
   653 {
       
   654   fprintf(stderr,"Interpreter::finalCheck()\n");
       
   655   Collector::collect();
       
   656 
       
   657   Node::finalCheck();
       
   658   Collector::finalCheck();
       
   659   Lexer::globalClear();
       
   660   UString::globalClear();
       
   661 }
       
   662 #endif
       
   663 
       
   664 static bool printExceptions = false;
       
   665 
       
   666 EXPORT
       
   667 bool Interpreter::shouldPrintExceptions()
       
   668 {
       
   669   return printExceptions;
       
   670 }
       
   671 
       
   672 EXPORT
       
   673 void Interpreter::setShouldPrintExceptions(bool print)
       
   674 {
       
   675   printExceptions = print;
       
   676 }
       
   677 
       
   678 EXPORT
       
   679 void Interpreter::saveBuiltins (SavedBuiltins& builtins) const
       
   680 {
       
   681     if (!builtins._internal)
       
   682         builtins._internal = new SavedBuiltinsInternal;
       
   683     
       
   684     builtins._internal->m_Object = m_Object;
       
   685     builtins._internal->m_Function = m_Function;
       
   686     builtins._internal->m_Array = m_Array;
       
   687     builtins._internal->m_Boolean = m_Boolean;
       
   688     builtins._internal->m_String = m_String;
       
   689     builtins._internal->m_Number = m_Number;
       
   690     builtins._internal->m_Date = m_Date;
       
   691     builtins._internal->m_RegExp = m_RegExp;
       
   692     builtins._internal->m_Error = m_Error;
       
   693     
       
   694     builtins._internal->m_ObjectPrototype = m_ObjectPrototype;
       
   695     builtins._internal->m_FunctionPrototype = m_FunctionPrototype;
       
   696     builtins._internal->m_ArrayPrototype = m_ArrayPrototype;
       
   697     builtins._internal->m_BooleanPrototype = m_BooleanPrototype;
       
   698     builtins._internal->m_StringPrototype = m_StringPrototype;
       
   699     builtins._internal->m_NumberPrototype = m_NumberPrototype;
       
   700     builtins._internal->m_DatePrototype = m_DatePrototype;
       
   701     builtins._internal->m_RegExpPrototype = m_RegExpPrototype;
       
   702     builtins._internal->m_ErrorPrototype = m_ErrorPrototype;
       
   703     
       
   704     builtins._internal->m_EvalError = m_EvalError;
       
   705     builtins._internal->m_RangeError = m_RangeError;
       
   706     builtins._internal->m_ReferenceError = m_ReferenceError;
       
   707     builtins._internal->m_SyntaxError = m_SyntaxError;
       
   708     builtins._internal->m_TypeError = m_TypeError;
       
   709     builtins._internal->m_UriError = m_UriError;
       
   710     
       
   711     builtins._internal->m_EvalErrorPrototype = m_EvalErrorPrototype;
       
   712     builtins._internal->m_RangeErrorPrototype = m_RangeErrorPrototype;
       
   713     builtins._internal->m_ReferenceErrorPrototype = m_ReferenceErrorPrototype;
       
   714     builtins._internal->m_SyntaxErrorPrototype = m_SyntaxErrorPrototype;
       
   715     builtins._internal->m_TypeErrorPrototype = m_TypeErrorPrototype;
       
   716     builtins._internal->m_UriErrorPrototype = m_UriErrorPrototype;
       
   717 }
       
   718 
       
   719 EXPORT
       
   720 void Interpreter::restoreBuiltins (const SavedBuiltins& builtins)
       
   721 {
       
   722     if (!builtins._internal)
       
   723         return;
       
   724 
       
   725     m_Object = builtins._internal->m_Object;
       
   726     m_Function = builtins._internal->m_Function;
       
   727     m_Array = builtins._internal->m_Array;
       
   728     m_Boolean = builtins._internal->m_Boolean;
       
   729     m_String = builtins._internal->m_String;
       
   730     m_Number = builtins._internal->m_Number;
       
   731     m_Date = builtins._internal->m_Date;
       
   732     m_RegExp = builtins._internal->m_RegExp;
       
   733     m_Error = builtins._internal->m_Error;
       
   734     
       
   735     m_ObjectPrototype = builtins._internal->m_ObjectPrototype;
       
   736     m_FunctionPrototype = builtins._internal->m_FunctionPrototype;
       
   737     m_ArrayPrototype = builtins._internal->m_ArrayPrototype;
       
   738     m_BooleanPrototype = builtins._internal->m_BooleanPrototype;
       
   739     m_StringPrototype = builtins._internal->m_StringPrototype;
       
   740     m_NumberPrototype = builtins._internal->m_NumberPrototype;
       
   741     m_DatePrototype = builtins._internal->m_DatePrototype;
       
   742     m_RegExpPrototype = builtins._internal->m_RegExpPrototype;
       
   743     m_ErrorPrototype = builtins._internal->m_ErrorPrototype;
       
   744     
       
   745     m_EvalError = builtins._internal->m_EvalError;
       
   746     m_RangeError = builtins._internal->m_RangeError;
       
   747     m_ReferenceError = builtins._internal->m_ReferenceError;
       
   748     m_SyntaxError = builtins._internal->m_SyntaxError;
       
   749     m_TypeError = builtins._internal->m_TypeError;
       
   750     m_UriError = builtins._internal->m_UriError;
       
   751     
       
   752     m_EvalErrorPrototype = builtins._internal->m_EvalErrorPrototype;
       
   753     m_RangeErrorPrototype = builtins._internal->m_RangeErrorPrototype;
       
   754     m_ReferenceErrorPrototype = builtins._internal->m_ReferenceErrorPrototype;
       
   755     m_SyntaxErrorPrototype = builtins._internal->m_SyntaxErrorPrototype;
       
   756     m_TypeErrorPrototype = builtins._internal->m_TypeErrorPrototype;
       
   757     m_UriErrorPrototype = builtins._internal->m_UriErrorPrototype;
       
   758 }
       
   759 
       
   760 EXPORT
       
   761 void Interpreter::startTimeoutCheck()
       
   762 {
       
   763     if (m_timeoutCheckCount == 0)
       
   764         resetTimeoutCheck();
       
   765     
       
   766     m_timeoutCheckCount++;
       
   767 }
       
   768 
       
   769 EXPORT
       
   770 void Interpreter::stopTimeoutCheck()
       
   771 {
       
   772     m_timeoutCheckCount--;
       
   773 }
       
   774 
       
   775 void Interpreter::resetTimeoutCheck()
       
   776 {
       
   777     m_tickCount = 0;
       
   778     m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
       
   779     m_timeAtLastCheckTimeout = 0;
       
   780     m_timeExecuting = 0;
       
   781 }
       
   782 
       
   783 // Returns the current time in milliseconds
       
   784 // It doesn't matter what "current time" is here, just as long as
       
   785 // it's possible to measure the time difference correctly.
       
   786 static inline unsigned getCurrentTime() {
       
   787 #if HAVE(SYS_TIME_H)
       
   788     struct timeval tv;
       
   789     gettimeofday(&tv, 0);
       
   790     return tv.tv_sec * 1000 + tv.tv_usec / 1000;
       
   791 #elif PLATFORM(QT)
       
   792     QDateTime t = QDateTime::currentDateTime();
       
   793     return t.toTime_t() * 1000 + t.time().msec();
       
   794 #elif PLATFORM(WIN_OS)
       
   795     return timeGetTime();
       
   796 #else
       
   797 #error Platform does not have getCurrentTime function
       
   798 #endif
       
   799 }
       
   800 
       
   801 bool Interpreter::checkTimeout()
       
   802 {    
       
   803     m_tickCount = 0;
       
   804     
       
   805     unsigned currentTime = getCurrentTime();
       
   806 
       
   807     if (!m_timeAtLastCheckTimeout) {
       
   808         // Suspicious amount of looping in a script -- start timing it
       
   809         m_timeAtLastCheckTimeout = currentTime;
       
   810         return false;
       
   811     }
       
   812 
       
   813     unsigned timeDiff = currentTime - m_timeAtLastCheckTimeout;
       
   814 
       
   815     if (timeDiff == 0)
       
   816         timeDiff = 1;
       
   817     
       
   818     m_timeExecuting += timeDiff;
       
   819     m_timeAtLastCheckTimeout = currentTime;
       
   820     
       
   821     // Adjust the tick threshold so we get the next checkTimeout call in the interval specified in 
       
   822     // preferredScriptCheckTimeInterval
       
   823     m_ticksUntilNextTimeoutCheck = (unsigned)((float)preferredScriptCheckTimeInterval / timeDiff) * m_ticksUntilNextTimeoutCheck;
       
   824 
       
   825     // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the
       
   826     // preferred script check time interval.
       
   827     if (m_ticksUntilNextTimeoutCheck == 0)
       
   828         m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
       
   829 
       
   830     if (m_timeoutTime && m_timeExecuting > m_timeoutTime) {
       
   831         if (shouldInterruptScript())
       
   832             return true;
       
   833         
       
   834         resetTimeoutCheck();
       
   835     }
       
   836     
       
   837     return false;
       
   838 }
       
   839 
       
   840 
       
   841 EXPORT
       
   842 SavedBuiltins::SavedBuiltins() : 
       
   843   _internal(0)
       
   844 {
       
   845 }
       
   846 
       
   847 EXPORT
       
   848 SavedBuiltins::~SavedBuiltins()
       
   849 {
       
   850   delete _internal;
       
   851 }
       
   852 
       
   853 }