blob: db4f10b4d6c6fd6477b922d67b8517391d395d03 [file] [log] [blame]
/*
* This file is part of the KDE libraries
* Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
* Copyright (C) 2003 Apple Computer, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#ifndef _KJS_INTERPRETER_H_
#define _KJS_INTERPRETER_H_
#include "ExecState.h"
#include "protect.h"
#include "value.h"
#include "types.h"
namespace KJS {
class ArrayObjectImp;
class ArrayPrototype;
class BooleanObjectImp;
class BooleanPrototype;
class Context;
class DateObjectImp;
class DatePrototype;
class Debugger;
class ErrorObjectImp;
class ErrorPrototype;
class EvalError;
class EvalErrorPrototype;
class FunctionObjectImp;
class FunctionPrototype;
class NativeErrorImp;
class NativeErrorPrototype;
class NumberObjectImp;
class NumberPrototype;
class ObjectObjectImp;
class ObjectPrototype;
class RangeError;
class RangeErrorPrototype;
class ReferenceError;
class ReferenceError;
class ReferenceErrorPrototype;
class RegExpObjectImp;
class RegExpPrototype;
class RuntimeMethod;
class SavedBuiltins;
class ScopeChain;
class StringObjectImp;
class StringPrototype;
class SyntaxErrorPrototype;
class TypeError;
class TypeErrorPrototype;
class UriError;
class UriErrorPrototype;
/**
* Interpreter objects can be used to evaluate ECMAScript code. Each
* interpreter has a global object which is used for the purposes of code
* evaluation, and also provides access to built-in properties such as
* " Object" and "Number".
*/
class Interpreter {
friend class Collector;
public:
/**
* Creates a new interpreter. The supplied object will be used as the global
* object for all scripts executed with this interpreter. During
* constuction, all the standard properties such as "Object" and "Number"
* will be added to the global object.
*
* Note: You should not use the same global object for multiple
* interpreters.
*
* This is due do the fact that the built-in properties are set in the
* constructor, and if these objects have been modified from another
* interpreter (e.g. a script modifying String.prototype), the changes will
* be overridden.
*
* @param global The object to use as the global object for this interpreter
*/
Interpreter(JSObject* globalObject);
/**
* Creates a new interpreter. A global object will be created and
* initialized with the standard global properties.
*/
Interpreter();
/**
* Resets the global object's default properties and adds the default object
* prototype to its prototype chain.
*/
void initGlobalObject();
/**
* Returns the object that is used as the global object during all script
* execution performed by this interpreter
*/
JSObject* globalObject() const;
/**
* Returns the execution state object which can be used to execute
* scripts using this interpreter at a the "global" level, i.e. one
* with a execution context that has the global object as the "this"
* value, and who's scope chain contains only the global object.
*
* Note: this pointer remains constant for the life of the interpreter
* and should not be manually deleted.
*
* @return The interpreter global execution state object
*/
virtual ExecState *globalExec();
/**
* Parses the supplied ECMAScript code and checks for syntax errors.
*
* @param code The code to check
* @return A normal completion if there were no syntax errors in the code,
* otherwise a throw completion with the syntax error as its value.
*/
Completion checkSyntax(const UString& sourceURL, int startingLineNumber, const UString& code);
Completion checkSyntax(const UString& sourceURL, int startingLineNumber, const UChar* code, int codeLength);
/**
* Evaluates the supplied ECMAScript code.
*
* Since this method returns a Completion, you should check the type of
* completion to detect an error or before attempting to access the returned
* value. For example, if an error occurs during script execution and is not
* caught by the script, the completion type will be Throw.
*
* If the supplied code is invalid, a SyntaxError will be thrown.
*
* @param code The code to evaluate
* @param thisV The value to pass in as the "this" value for the script
* execution. This should either be jsNull() or an Object.
* @return A completion object representing the result of the execution.
*/
Completion evaluate(const UString& sourceURL, int startingLineNumber, const UChar* code, int codeLength, JSValue* thisV = 0);
Completion evaluate(const UString& sourceURL, int startingLineNumber, const UString& code, JSValue* thisV = 0);
/**
* Returns the builtin "Object" object. This is the object that was set
* as a property of the global object during construction; if the property
* is replaced by script code, this method will still return the original
* object.
*
* @return The builtin "Object" object
*/
JSObject *builtinObject() const;
/**
* Returns the builtin "Function" object.
*/
JSObject *builtinFunction() const;
/**
* Returns the builtin "Array" object.
*/
JSObject *builtinArray() const;
/**
* Returns the builtin "Boolean" object.
*/
JSObject *builtinBoolean() const;
/**
* Returns the builtin "String" object.
*/
JSObject *builtinString() const;
/**
* Returns the builtin "Number" object.
*/
JSObject *builtinNumber() const;
/**
* Returns the builtin "Date" object.
*/
JSObject *builtinDate() const;
/**
* Returns the builtin "RegExp" object.
*/
JSObject *builtinRegExp() const;
/**
* Returns the builtin "Error" object.
*/
JSObject *builtinError() const;
/**
* Returns the builtin "Object.prototype" object.
*/
JSObject *builtinObjectPrototype() const;
/**
* Returns the builtin "Function.prototype" object.
*/
JSObject *builtinFunctionPrototype() const;
/**
* Returns the builtin "Array.prototype" object.
*/
JSObject *builtinArrayPrototype() const;
/**
* Returns the builtin "Boolean.prototype" object.
*/
JSObject *builtinBooleanPrototype() const;
/**
* Returns the builtin "String.prototype" object.
*/
JSObject *builtinStringPrototype() const;
/**
* Returns the builtin "Number.prototype" object.
*/
JSObject *builtinNumberPrototype() const;
/**
* Returns the builtin "Date.prototype" object.
*/
JSObject *builtinDatePrototype() const;
/**
* Returns the builtin "RegExp.prototype" object.
*/
JSObject *builtinRegExpPrototype() const;
/**
* Returns the builtin "Error.prototype" object.
*/
JSObject *builtinErrorPrototype() const;
/**
* The initial value of "Error" global property
*/
JSObject *builtinEvalError() const;
JSObject *builtinRangeError() const;
JSObject *builtinReferenceError() const;
JSObject *builtinSyntaxError() const;
JSObject *builtinTypeError() const;
JSObject *builtinURIError() const;
JSObject *builtinEvalErrorPrototype() const;
JSObject *builtinRangeErrorPrototype() const;
JSObject *builtinReferenceErrorPrototype() const;
JSObject *builtinSyntaxErrorPrototype() const;
JSObject *builtinTypeErrorPrototype() const;
JSObject *builtinURIErrorPrototype() const;
enum CompatMode { NativeMode, IECompat, NetscapeCompat };
/**
* Call this to enable a compatibility mode with another browser.
* (by default konqueror is in "native mode").
* Currently, in KJS, this only changes the behavior of Date::getYear()
* which returns the full year under IE.
*/
void setCompatMode(CompatMode mode) { m_compatMode = mode; }
CompatMode compatMode() const { return m_compatMode; }
/**
* Run the garbage collection. Returns true when at least one object
* was collected; false otherwise.
*/
static bool collect();
/**
* Called during the mark phase of the garbage collector. Subclasses
* implementing custom mark methods must make sure to chain to this one.
*/
virtual void mark();
#ifdef KJS_DEBUG_MEM
/**
* @internal
*/
static void finalCheck();
#endif
static bool shouldPrintExceptions();
static void setShouldPrintExceptions(bool);
void saveBuiltins (SavedBuiltins&) const;
void restoreBuiltins (const SavedBuiltins&);
/**
* Determine if the value is a global object (for any interpreter). This may
* be difficult to determine for multiple uses of JSC in a process that are
* logically independent of each other. In the case of WebCore, this method
* is used to determine if an object is the Window object so we can perform
* security checks.
*/
virtual bool isGlobalObject(JSValue*) { return false; }
/**
* Find the interpreter for a particular global object. This should really
* be a static method, but we can't do that is C++. Again, as with isGlobalObject()
* implementation really need to know about all instances of Interpreter
* created in an application to correctly implement this method. The only
* override of this method is currently in WebCore.
*/
virtual Interpreter* interpreterForGlobalObject(const JSValue*) { return 0; }
/**
* Determine if the it is 'safe' to execute code in the target interpreter from an
* object that originated in this interpreter. This check is used to enforce WebCore
* cross frame security rules. In particular, attempts to access 'bound' objects are
* not allowed unless isSafeScript returns true.
*/
virtual bool isSafeScript(const Interpreter*) { return true; }
// Chained list of interpreters (ring)
static Interpreter* firstInterpreter() { return s_hook; }
Interpreter* nextInterpreter() const { return next; }
Interpreter* prevInterpreter() const { return prev; }
Debugger* debugger() const { return m_debugger; }
void setDebugger(Debugger* d) { m_debugger = d; }
void setContext(Context* c) { m_context = c; }
Context* context() const { return m_context; }
static Interpreter* interpreterWithGlobalObject(JSObject*);
void setTimeoutTime(unsigned timeoutTime) { m_timeoutTime = timeoutTime; }
void startTimeoutCheck();
void stopTimeoutCheck();
bool timedOut();
void ref() { ++m_refCount; }
void deref() { if (--m_refCount <= 0) delete this; }
int refCount() const { return m_refCount; }
protected:
virtual ~Interpreter(); // only deref should delete us
virtual bool shouldInterruptScript() const { return true; }
unsigned m_timeoutTime;
private:
void init();
void resetTimeoutCheck();
bool checkTimeout();
// Uncopyable
Interpreter(const Interpreter&);
Interpreter operator=(const Interpreter&);
int m_refCount;
ExecState m_globalExec;
// Chained list of interpreters (ring) - for collector
static Interpreter* s_hook;
Interpreter *next, *prev;
int m_recursion;
Debugger* m_debugger;
Context* m_context;
CompatMode m_compatMode;
unsigned m_timeAtLastCheckTimeout;
unsigned m_timeExecuting;
unsigned m_timeoutCheckCount;
unsigned m_tickCount;
unsigned m_ticksUntilNextTimeoutCheck;
JSObject* m_globalObject;
ObjectObjectImp* m_Object;
FunctionObjectImp* m_Function;
ArrayObjectImp* m_Array;
BooleanObjectImp* m_Boolean;
StringObjectImp* m_String;
NumberObjectImp* m_Number;
DateObjectImp* m_Date;
RegExpObjectImp* m_RegExp;
ErrorObjectImp* m_Error;
ObjectPrototype* m_ObjectPrototype;
FunctionPrototype* m_FunctionPrototype;
ArrayPrototype* m_ArrayPrototype;
BooleanPrototype* m_BooleanPrototype;
StringPrototype* m_StringPrototype;
NumberPrototype* m_NumberPrototype;
DatePrototype* m_DatePrototype;
RegExpPrototype* m_RegExpPrototype;
ErrorPrototype* m_ErrorPrototype;
NativeErrorImp* m_EvalError;
NativeErrorImp* m_RangeError;
NativeErrorImp* m_ReferenceError;
NativeErrorImp* m_SyntaxError;
NativeErrorImp* m_TypeError;
NativeErrorImp* m_UriError;
NativeErrorPrototype* m_EvalErrorPrototype;
NativeErrorPrototype* m_RangeErrorPrototype;
NativeErrorPrototype* m_ReferenceErrorPrototype;
NativeErrorPrototype* m_SyntaxErrorPrototype;
NativeErrorPrototype* m_TypeErrorPrototype;
NativeErrorPrototype* m_UriErrorPrototype;
};
inline bool Interpreter::timedOut()
{
m_tickCount++;
if (m_tickCount != m_ticksUntilNextTimeoutCheck)
return false;
return checkTimeout();
}
} // namespace
#endif // _KJS_INTERPRETER_H_