kdelibs/kjs/ExecState.h
Ivailo Monev 39f1e04295 generic: add back khtml and kjs with some changes
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2015-11-09 23:23:53 +02:00

306 lines
11 KiB
C++

/*
* 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, 2007, 2008 Apple Inc. All rights reserved.
* Copyright (C) 2008 Maksim Orlovich (maksim@kde.org)
*
* 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 ExecState_H
#define ExecState_H
#include "completion.h"
#include "value.h"
#include "types.h"
#include "CommonIdentifiers.h"
#include "scope_chain.h"
#include "LocalStorage.h"
#include "wtf/Vector.h"
#include "PropertyNameArray.h"
namespace KJS {
class ActivationImp;
class Interpreter;
class FunctionImp;
class FunctionBodyNode;
class ProgramNode;
class JSGlobalObject;
enum CodeType { GlobalCode, EvalCode, FunctionCode };
/**
* 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 context.
*/
class KJS_EXPORT ExecState : Noncopyable {
friend class Interpreter;
friend class FunctionImp;
friend class GlobalFuncImp;
public:
/**
* Returns the interpreter associated with this execution state
*
* @return The interpreter executing the script
*/
Interpreter* dynamicInterpreter() const { return m_interpreter; }
/**
* Returns the interpreter associated with the current scope's
* global object
*
* @return The interpreter currently in scope
*/
Interpreter* lexicalInterpreter() const;
/**
* This describes how an exception should be handled
*/
enum HandlerType {
JumpToCatch, ///< jump to the specified address
PopScope, ///< remove a scope chain entry, and run the next handler
RemoveDeferred, ///< remove any deferred exception object, and run the next entry
Silent ///< just update the exception object. For debugger-type use only
};
void pushExceptionHandler(HandlerType type, Addr addr = 0);
void popExceptionHandler();
// Cleanup depth entries from the stack, w/o running jumps
void quietUnwind(int depth);
void setMachineRegisters(const unsigned char* pcBase, const unsigned char** pcLoc, LocalStorageEntry** machineLocalStoreLoc) {
m_pcBase = pcBase;
m_pc = pcLoc;
m_machineLocalStore = machineLocalStoreLoc;
}
/**
The below methods deal with deferring of completions inside finally clauses.
Essentially, we clear any set exceptions and memorize any non-normal completion
(including the target addresses for the continue/break statements) on
the m_deferredCompletions stack. If the 'finally' finishes normally,
we will resume the previous completion. If not, finally's abnormal
termination is handled as usually; a RemoveDeferred cleanup stack
entry is added to unwind m_deferredCompletions if that happens.
*/
void deferCompletion() {
pushExceptionHandler(RemoveDeferred);
m_deferredCompletions.append(abruptCompletion());
clearException();
}
/**
This resumes dispatch of a completion that was deferred due to a try ... finally,
handling it as appropriate for whether it's inside an another try-finally.
This will handle all the cases itself except for one: return,
for which it will return the value to return (otherwise returning 0)
*/
JSValue* reactivateCompletion(bool insideTryFinally);
/**
* Set the exception associated with this execution state,
* updating the program counter appropriately, and executing any relevant EH cleanups.
* @param e The JSValue of the exception being set
*/
void setException(JSValue* e);
/**
* Records an abrupt completion of code, and jumps to the closest catch or finally.
* This always happens for exceptions, but can also happen for continue/break/return when
* they're inside try ... finally, since that case gets routed through the EH machinery.
*/
void setAbruptCompletion(Completion comp);
/**
* Clears the exception or other abnormal completion set on this execution state.
*/
void clearException() { m_completion = Completion(); }
/**
* Returns the exception associated with this execution state.
* @return The current execution state exception
*/
JSValue* exception() const { return m_completion.complType() == Throw ? m_completion.value() : 0; }
/**
* Use this to check if an exception was thrown in the current
* execution state.
*
* @return Whether an exception was thrown
*/
bool hadException() const { return m_completion.complType() == Throw; }
Completion abruptCompletion() const { return m_completion; }
/**
* 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 { return scope; }
/**
* 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
*/
JSObject* variableObject() const { return m_variable; }
void setVariableObject(JSObject* v) { m_variable = v; }
/**
* 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
*/
JSObject* thisValue() const { return m_thisVal; }
/**
* 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 its methods.
*
* @return The calling execution context
*/
ExecState* callingExecState() { return m_callingExec; }
/**
* Returns the execState of a previous nested evaluation session, if any.
*/
ExecState* savedExecState() { return m_savedExec; }
JSObject* activationObject() {
assert(m_codeType == FunctionCode);
return m_variable;
}
CodeType codeType() { return m_codeType; }
FunctionBodyNode* currentBody() { return m_currentBody; }
FunctionImp* function() const { return m_function; }
void pushVariableObjectScope(JSVariableObject* s) { scope.pushVariableObject(s); }
void pushScope(JSObject* s) { scope.push(s); }
void popScope() { scope.pop(); }
void mark();
void initLocalStorage(LocalStorageEntry* store, size_t size) {
m_localStore = store;
m_localStoreSize = size;
}
void updateLocalStorage(LocalStorageEntry* newStore) {
m_localStore = newStore;
*m_machineLocalStore = newStore;
}
LocalStorageEntry* localStorage() { return m_localStore; }
// 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 CommonIdentifiers& propertyNames() const { return *m_propertyNames; }
// Compatibility stuff:
ExecState* context() { return this; }
ExecState* callingContext() { return callingExecState(); }
protected:
ExecState(Interpreter* intp, ExecState* save);
~ExecState();
void markSelf();
Interpreter* m_interpreter;
Completion m_completion;
CommonIdentifiers* m_propertyNames;
ExecState* m_callingExec;
ExecState* m_savedExec; // in case of recursion of evaluation. Needed to mark things properly;
// note that this is disjoint from the above, since that's only used for
// eval/function, while this is for global.
FunctionBodyNode* m_currentBody;
FunctionImp* m_function;
ScopeChain scope;
JSObject* m_variable;
JSObject* m_thisVal;
LocalStorageEntry* m_localStore;
size_t m_localStoreSize;
struct ExceptionHandler {
ExceptionHandler() {}
ExceptionHandler(HandlerType type, Addr dest):
type(type), dest(dest) {}
HandlerType type;
Addr dest;
};
const unsigned char* m_pcBase; // The address of pc = 0
const unsigned char** m_pc; // Where the current fetch address is stored
LocalStorageEntry** m_machineLocalStore; // Machine's copy of m_localStore
WTF::Vector<ExceptionHandler, 4> m_exceptionHandlers;
WTF::Vector<Completion, 4> m_deferredCompletions;
CodeType m_codeType;
};
typedef ExecState Context; // Compatibility only
class GlobalExecState : public ExecState {
public:
GlobalExecState(Interpreter* intp, JSGlobalObject* global);
};
class InterpreterExecState : public ExecState {
public:
InterpreterExecState(Interpreter* intp, JSGlobalObject* global, JSObject* thisObject, ProgramNode*);
};
class EvalExecState : public ExecState {
public:
EvalExecState(Interpreter* intp, JSGlobalObject* global, ProgramNode* body, ExecState* callingExecState);
};
// Note: this does not push the activation on the scope chain,
// as the activation is not initialized at this point.
class FunctionExecState : public ExecState {
public:
FunctionExecState(Interpreter* intp, JSObject* thisObject,
FunctionBodyNode*, ExecState* callingExecState, FunctionImp*);
};
} // namespace KJS
#endif // ExecState_H