blob: 20e4f520d1e91740c983a55392315792719ddedb [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 Steet, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#ifndef _KJS_INTERPRETER_H_
#define _KJS_INTERPRETER_H_
#include "value.h"
#include "types.h"
namespace KJS {
class ContextImp;
class InterpreterImp;
class RuntimeMethodImp;
class ScopeChain;
namespace Bindings {
class RootObject;
}
/**
* Represents an execution context, as specified by section 10 of the ECMA
* spec.
*
* An execution context contains information about the current state of the
* script - the scope for variable lookup, the value of "this", etc. A new
* execution context is entered whenever global code is executed (e.g. with
* Interpreter::evaluate()), a function is called (see
* Object::call()), or the builtin "eval" function is executed.
*
* Most inheritable functions in the KJS api take a ExecState pointer as
* their first parameter. This can be used to obtain a handle to the current
* execution context.
*
* Note: Context objects are wrapper classes/smart pointers for the internal
* KJS ContextImp type. When one context variable is assigned to another, it
* is still referencing the same internal object.
*/
class Context {
public:
Context(ContextImp *i) : rep(i) { }
ContextImp *imp() const { return rep; }
/**
* Returns the scope chain for this execution context. This is used for
* variable lookup, with the list being searched from start to end until a
* variable is found.
*
* @return The execution context's scope chain
*/
const ScopeChain &scopeChain() const;
/**
* Returns the variable object for the execution context. This contains a
* property for each variable declared in the execution context.
*
* @return The execution context's variable object
*/
ObjectImp *variableObject() const;
/**
* Returns the "this" value for the execution context. This is the value
* returned when a script references the special variable "this". It should
* always be an Object, unless application-specific code has passed in a
* different type.
*
* The object that is used as the "this" value depends on the type of
* execution context - for global contexts, the global object is used. For
* function objewcts, the value is given by the caller (e.g. in the case of
* obj.func(), obj would be the "this" value). For code executed by the
* built-in "eval" function, the this value is the same as the calling
* context.
*
* @return The execution context's "this" value
*/
ObjectImp *thisValue() const;
/**
* Returns the context from which the current context was invoked. For
* global code this will be a null context (i.e. one for which
* isNull() returns true). You should check isNull() on the returned
* value before calling any of it's methods.
*
* @return The calling execution context
*/
const Context callingContext() const;
/**
* The line number on which the current statement begins
* NOTE: Only for source compatibility, JSC does not support this method.
*/
int curStmtFirstLine() const { return 0; }
private:
ContextImp *rep;
};
class SavedBuiltinsInternal;
class SavedBuiltins {
friend class InterpreterImp;
public:
SavedBuiltins();
~SavedBuiltins();
private:
SavedBuiltinsInternal *_internal;
};
/**
* 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 {
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(ObjectImp *global);
/**
* Creates a new interpreter. A global object will be created and
* initialized with the standard global properties.
*/
Interpreter();
virtual ~Interpreter();
/**
* Returns the object that is used as the global object during all script
* execution performed by this interpreter
*/
ObjectImp *globalObject() const;
void initGlobalObject();
static void lock();
static void unlock();
static int lockCount();
/**
* 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
*/
ExecState *globalExec();
/**
* Parses the supplied ECMAScript code and checks for syntax errors.
*
* @param code The code to check
* @return true if there were no syntax errors in the code, otherwise false
*/
bool checkSyntax(const UString &code);
/**
* 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 Null() or an Object.
* @return A completion object representing the result of the execution.
*/
Completion evaluate(const UString &sourceURL, int startingLineNumber, const UString &code, ValueImp *thisV = NULL);
// Overload of evaluate to keep JavaScriptGlue both source and binary compatible.
Completion evaluate(const UString &code, ValueImp *thisV = NULL, const UString &sourceFilename = UString());
/**
* @internal
*
* Returns the implementation object associated with this interpreter.
* Only useful for internal KJS operations.
*/
InterpreterImp *imp() const { return rep; }
/**
* 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
*/
ObjectImp *builtinObject() const;
/**
* Returns the builtin "Function" object.
*/
ObjectImp *builtinFunction() const;
/**
* Returns the builtin "Array" object.
*/
ObjectImp *builtinArray() const;
/**
* Returns the builtin "Boolean" object.
*/
ObjectImp *builtinBoolean() const;
/**
* Returns the builtin "String" object.
*/
ObjectImp *builtinString() const;
/**
* Returns the builtin "Number" object.
*/
ObjectImp *builtinNumber() const;
/**
* Returns the builtin "Date" object.
*/
ObjectImp *builtinDate() const;
/**
* Returns the builtin "RegExp" object.
*/
ObjectImp *builtinRegExp() const;
/**
* Returns the builtin "Error" object.
*/
ObjectImp *builtinError() const;
/**
* Returns the builtin "Object.prototype" object.
*/
ObjectImp *builtinObjectPrototype() const;
/**
* Returns the builtin "Function.prototype" object.
*/
ObjectImp *builtinFunctionPrototype() const;
/**
* Returns the builtin "Array.prototype" object.
*/
ObjectImp *builtinArrayPrototype() const;
/**
* Returns the builtin "Boolean.prototype" object.
*/
ObjectImp *builtinBooleanPrototype() const;
/**
* Returns the builtin "String.prototype" object.
*/
ObjectImp *builtinStringPrototype() const;
/**
* Returns the builtin "Number.prototype" object.
*/
ObjectImp *builtinNumberPrototype() const;
/**
* Returns the builtin "Date.prototype" object.
*/
ObjectImp *builtinDatePrototype() const;
/**
* Returns the builtin "RegExp.prototype" object.
*/
ObjectImp *builtinRegExpPrototype() const;
/**
* Returns the builtin "Error.prototype" object.
*/
ObjectImp *builtinErrorPrototype() const;
/**
* The initial value of "Error" global property
*/
ObjectImp *builtinEvalError() const;
ObjectImp *builtinRangeError() const;
ObjectImp *builtinReferenceError() const;
ObjectImp *builtinSyntaxError() const;
ObjectImp *builtinTypeError() const;
ObjectImp *builtinURIError() const;
ObjectImp *builtinEvalErrorPrototype() const;
ObjectImp *builtinRangeErrorPrototype() const;
ObjectImp *builtinReferenceErrorPrototype() const;
ObjectImp *builtinSyntaxErrorPrototype() const;
ObjectImp *builtinTypeErrorPrototype() const;
ObjectImp *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);
CompatMode compatMode() const;
/**
* Called by InterpreterImp during the mark phase of the garbage collector
* Default implementation does nothing, this exist for classes that reimplement Interpreter.
*/
virtual void mark() {}
/**
* Provides a way to distinguish derived classes.
* Only useful if you reimplement Interpreter and if different kind of
* interpreters are created in the same process.
* The base class returns 0, the ECMA-bindings interpreter returns 1.
*/
virtual int rtti() { return 0; }
#ifdef KJS_DEBUG_MEM
/**
* @internal
*/
static void finalCheck();
#endif
#if APPLE_CHANGES
static bool shouldPrintExceptions();
static void setShouldPrintExceptions(bool);
#endif
void saveBuiltins (SavedBuiltins &) const;
void restoreBuiltins (const SavedBuiltins &);
#if APPLE_CHANGES
/**
* 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(ValueImp *v) { 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 ValueImp *imp) { 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 *target) { return true; }
virtual void *createLanguageInstanceForValue (ExecState *exec, int language, ObjectImp *value, const Bindings::RootObject *origin, const Bindings::RootObject *current);
#endif
// This is a workaround to avoid accessing the global variables for these identifiers in
// important property lookup functions, to avoid taking PIC branches in Mach-O binaries
const Identifier& argumentsIdentifier() { return *m_argumentsPropertyName; }
const Identifier& specialPrototypeIdentifier() { return *m_specialPrototypePropertyName; }
private:
InterpreterImp *rep;
const Identifier *m_argumentsPropertyName;
const Identifier *m_specialPrototypePropertyName;
/**
* This constructor is not implemented, in order to prevent
* copy-construction of Interpreter objects. You should always pass around
* pointers to an interpreter instance instead.
*/
Interpreter(const Interpreter&);
/**
* This constructor is not implemented, in order to prevent assignment of
* Interpreter objects. You should always pass around pointers to an
* interpreter instance instead.
*/
Interpreter operator=(const Interpreter&);
protected:
virtual void virtual_hook( int id, void* data );
};
/**
* Represents the current state of script execution. This object allows you
* obtain a handle the interpreter that is currently executing the script,
* and also the current execution state context.
*/
class ExecState {
friend class InterpreterImp;
friend class FunctionImp;
#if APPLE_CHANGES
friend class RuntimeMethodImp;
#endif
friend class GlobalFuncImp;
public:
/**
* Returns the interpreter associated with this execution state
*
* @return The interpreter executing the script
*/
Interpreter *dynamicInterpreter() const { return _interpreter; }
// for compatibility
Interpreter *interpreter() const { return dynamicInterpreter(); }
/**
* Returns the interpreter associated with the current scope's
* global object
*
* @return The interpreter currently in scope
*/
Interpreter *lexicalInterpreter() const;
/**
* Returns the execution context associated with this execution state
*
* @return The current execution state context
*/
Context context() const { return _context; }
void setException(ValueImp *e) { _exception = e; }
void clearException() { _exception = NULL; }
ValueImp *exception() const { return _exception; }
bool hadException() const { return _exception; }
private:
ExecState(Interpreter *interp, ContextImp *con)
: _interpreter(interp), _context(con), _exception(NULL) { }
Interpreter *_interpreter;
ContextImp *_context;
ValueImp *_exception;
};
class InterpreterLock
{
public:
InterpreterLock() { Interpreter::lock(); }
~InterpreterLock() { Interpreter::unlock(); }
private:
InterpreterLock(const InterpreterLock &);
InterpreterLock &operator =(const InterpreterLock &);
};
} // namespace
#endif // _KJS_INTERPRETER_H_