2006-06-12 Geoffrey Garen <ggaren@apple.com>
+ Reviewed by TimO, Maciej.
+
+ - Merged InterpreterImp code into Interpreter, which implements
+ all interpreter functionality now. This is part of my continuing quest
+ to create an external notion of JS "execution context" that is unified and simple --
+ something to replace the mix of Context, ContextImp, ExecState, Interpreter,
+ InterpreterImp, and JSRun.
+
+ All tests pass. Leaks test has not regressed from its baseline ~207 leaks
+ with ~3460 leaked nodes.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * bindings/NP_jsobject.cpp:
+ * bindings/objc/WebScriptObject.mm:
+ (+[WebScriptObject throwException:]):
+ * bindings/runtime_root.cpp:
+ * bindings/runtime_root.h:
+ * kjs/Context.cpp:
+ (KJS::Context::Context):
+ * kjs/ExecState.cpp: Added.
+ (KJS::ExecState::lexicalInterpreter):
+ * kjs/ExecState.h: Added.
+ (KJS::ExecState::dynamicInterpreter):
+ * kjs/SavedBuiltins.h: Added.
+ * kjs/bool_object.cpp:
+ (BooleanPrototype::BooleanPrototype):
+ * kjs/collector.cpp:
+ (KJS::Collector::collect):
+ (KJS::Collector::numInterpreters):
+ * kjs/context.h:
+ * kjs/debugger.cpp:
+ (Debugger::attach):
+ (Debugger::detach):
+ * kjs/function.cpp:
+ (KJS::FunctionImp::callAsFunction):
+ (KJS::GlobalFuncImp::callAsFunction):
+ * kjs/function_object.cpp:
+ (FunctionObjectImp::construct):
+ * kjs/internal.cpp:
+ * kjs/internal.h:
+ * kjs/interpreter.cpp:
+ (KJS::interpreterMap):
+ (KJS::Interpreter::Interpreter):
+ (KJS::Interpreter::init):
+ (KJS::Interpreter::~Interpreter):
+ (KJS::Interpreter::globalObject):
+ (KJS::Interpreter::initGlobalObject):
+ (KJS::Interpreter::globalExec):
+ (KJS::Interpreter::checkSyntax):
+ (KJS::Interpreter::evaluate):
+ (KJS::Interpreter::builtinObject):
+ (KJS::Interpreter::builtinFunction):
+ (KJS::Interpreter::builtinArray):
+ (KJS::Interpreter::builtinBoolean):
+ (KJS::Interpreter::builtinString):
+ (KJS::Interpreter::builtinNumber):
+ (KJS::Interpreter::builtinDate):
+ (KJS::Interpreter::builtinRegExp):
+ (KJS::Interpreter::builtinError):
+ (KJS::Interpreter::builtinObjectPrototype):
+ (KJS::Interpreter::builtinFunctionPrototype):
+ (KJS::Interpreter::builtinArrayPrototype):
+ (KJS::Interpreter::builtinBooleanPrototype):
+ (KJS::Interpreter::builtinStringPrototype):
+ (KJS::Interpreter::builtinNumberPrototype):
+ (KJS::Interpreter::builtinDatePrototype):
+ (KJS::Interpreter::builtinRegExpPrototype):
+ (KJS::Interpreter::builtinErrorPrototype):
+ (KJS::Interpreter::builtinEvalError):
+ (KJS::Interpreter::builtinRangeError):
+ (KJS::Interpreter::builtinReferenceError):
+ (KJS::Interpreter::builtinSyntaxError):
+ (KJS::Interpreter::builtinTypeError):
+ (KJS::Interpreter::builtinURIError):
+ (KJS::Interpreter::builtinEvalErrorPrototype):
+ (KJS::Interpreter::builtinRangeErrorPrototype):
+ (KJS::Interpreter::builtinReferenceErrorPrototype):
+ (KJS::Interpreter::builtinSyntaxErrorPrototype):
+ (KJS::Interpreter::builtinTypeErrorPrototype):
+ (KJS::Interpreter::builtinURIErrorPrototype):
+ (KJS::Interpreter::mark):
+ (KJS::Interpreter::interpreterWithGlobalObject):
+ (KJS::Interpreter::saveBuiltins):
+ (KJS::Interpreter::restoreBuiltins):
+ * kjs/interpreter.h:
+ (KJS::Interpreter::setCompatMode):
+ (KJS::Interpreter::compatMode):
+ (KJS::Interpreter::firstInterpreter):
+ (KJS::Interpreter::nextInterpreter):
+ (KJS::Interpreter::prevInterpreter):
+ (KJS::Interpreter::debugger):
+ (KJS::Interpreter::setDebugger):
+ (KJS::Interpreter::setContext):
+ (KJS::Interpreter::context):
+ * kjs/nodes.cpp:
+ (StatementNode::hitStatement):
+ (RegExpNode::evaluate):
+ * kjs/protect.h:
+
+2006-06-12 Geoffrey Garen <ggaren@apple.com>
+
Reviewed by Maciej.
- Have *.lut.h files #include lookup.h to eliminate surprising header
>
</File>
<File
+ RelativePath="..\..\kjs\ExecState.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\kjs\ExecState.h"
+ >
+ </File>
+ <File
RelativePath="..\..\kjs\fpconst.cpp"
>
</File>
>
</File>
<File
+ RelativePath="..\..\kjs\SavedBuiltins.h"
+ >
+ </File>
+ <File
RelativePath="..\..\kjs\scope_chain.cpp"
>
</File>
148A1627095D16BB00666D0D /* ListRefPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 148A1626095D16BB00666D0D /* ListRefPtr.h */; };
14ABB36F099C076400E2A24F /* value.h in Headers */ = {isa = PBXBuildFile; fileRef = 14ABB36E099C076400E2A24F /* value.h */; settings = {ATTRIBUTES = (Private, ); }; };
14ABB455099C2A0F00E2A24F /* JSType.h in Headers */ = {isa = PBXBuildFile; fileRef = 14ABB454099C2A0F00E2A24F /* JSType.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 14BD534C0A3E0AEA00BAF59C /* SavedBuiltins.h in Headers */ = {isa = PBXBuildFile; fileRef = 14BD534A0A3E0AEA00BAF59C /* SavedBuiltins.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 14BD53F50A3E12D800BAF59C /* ExecState.h in Headers */ = {isa = PBXBuildFile; fileRef = 14BD53F30A3E12D800BAF59C /* ExecState.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 14BD53F60A3E12D800BAF59C /* ExecState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14BD53F40A3E12D800BAF59C /* ExecState.cpp */; };
14F137590A3A727E00F26F90 /* Context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14F137580A3A727E00F26F90 /* Context.cpp */; };
14F137830A3A765B00F26F90 /* context.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F137820A3A765B00F26F90 /* context.h */; settings = {ATTRIBUTES = (Private, ); }; };
652C107F08DA7B1E0020887D /* protected_reference.h in Headers */ = {isa = PBXBuildFile; fileRef = 652C107E08DA7B1E0020887D /* protected_reference.h */; };
148A1626095D16BB00666D0D /* ListRefPtr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ListRefPtr.h; sourceTree = "<group>"; };
14ABB36E099C076400E2A24F /* value.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = value.h; sourceTree = "<group>"; };
14ABB454099C2A0F00E2A24F /* JSType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSType.h; sourceTree = "<group>"; };
+ 14BD534A0A3E0AEA00BAF59C /* SavedBuiltins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SavedBuiltins.h; sourceTree = "<group>"; };
+ 14BD53F30A3E12D800BAF59C /* ExecState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecState.h; sourceTree = "<group>"; };
+ 14BD53F40A3E12D800BAF59C /* ExecState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecState.cpp; sourceTree = "<group>"; };
14F137580A3A727E00F26F90 /* Context.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Context.cpp; sourceTree = "<group>"; };
14F137820A3A765B00F26F90 /* context.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = context.h; sourceTree = "<group>"; };
45E12D8806A49B0F00E9DF84 /* testkjs.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = testkjs.cpp; sourceTree = "<group>"; tabWidth = 8; };
F692A8860255597D01FF60F7 /* ustring.h */,
F692A8870255597D01FF60F7 /* value.cpp */,
14ABB36E099C076400E2A24F /* value.h */,
+ 14BD534A0A3E0AEA00BAF59C /* SavedBuiltins.h */,
+ 14BD53F30A3E12D800BAF59C /* ExecState.h */,
+ 14BD53F40A3E12D800BAF59C /* ExecState.cpp */,
);
path = kjs;
sourceTree = "<group>";
935AF46E09E9D9DB00ACD1D8 /* UnusedParam.h in Headers */,
BCF655590A2049710038A194 /* MathExtras.h in Headers */,
14F137830A3A765B00F26F90 /* context.h in Headers */,
+ 14BD534C0A3E0AEA00BAF59C /* SavedBuiltins.h in Headers */,
+ 14BD53F50A3E12D800BAF59C /* ExecState.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
93F0B3AB09BB4DC00068FCE3 /* Parser.cpp in Sources */,
65FB3F5009D11B2400F49DEB /* grammar.cpp in Sources */,
14F137590A3A727E00F26F90 /* Context.cpp in Sources */,
+ 14BD53F60A3E12D800BAF59C /* ExecState.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
#include "c_utility.h"
#include "npruntime_impl.h"
#include "npruntime_priv.h"
+#include "object.h"
#include "runtime_root.h"
using namespace KJS;
+ (BOOL)throwException:(NSString *)exceptionMessage
{
- InterpreterImp *first, *interp = InterpreterImp::firstInterpreter();
+ Interpreter *first, *interp = Interpreter::firstInterpreter();
// This code assumes that we only ever have one running interpreter. A
// good assumption for now, as we depend on that elsewhere. However,
// in the future we may have the ability to run multiple interpreters,
// in which case this will have to change.
- first = interp;
do {
ExecState *exec = interp->globalExec();
// If the interpreter has a context, we set the exception.
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
-#include <jni_jsobject.h>
-#include <runtime_root.h>
+#include "jni_jsobject.h"
+#include "object.h"
+#include "runtime_root.h"
using namespace KJS;
using namespace KJS::Bindings;
#ifndef RUNTIME_ROOT_H_
#define RUNTIME_ROOT_H_
-#include <JavaScriptCore/protect.h>
-#include <JavaScriptCore/jni_jsobject.h>
-#include <JavaScriptCore/protect.h>
+#include "Interpreter.h"
+#include "jni_jsobject.h"
+#include "protect.h"
namespace KJS {
namespace KJS {
// ECMA 10.2
-Context::Context(JSObject* glob, InterpreterImp* interpreter, JSObject* thisV,
+Context::Context(JSObject* glob, Interpreter* interpreter, JSObject* thisV,
FunctionBodyNode* currentBody, CodeType type, Context* callingCon,
FunctionImp* func, const List* args)
: m_interpreter(interpreter)
--- /dev/null
+// -*- c-basic-offset: 2 -*-
+/*
+ * 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.
+ *
+ */
+
+#include "Context.h"
+#include "ExecState.h"
+#include "internal.h"
+
+namespace KJS {
+
+Interpreter* ExecState::lexicalInterpreter() const
+{
+ if (!m_context)
+ return dynamicInterpreter();
+
+ Interpreter* result = Interpreter::interpreterWithGlobalObject(m_context->scopeChain().bottom());
+
+ if (!result)
+ return dynamicInterpreter();
+
+ return result;
+}
+
+} // namespace KJS
--- /dev/null
+/*
+ * 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 ExecState_H
+#define ExecState_H
+
+#include "value.h"
+#include "types.h"
+
+namespace KJS {
+ class Context;
+
+ /**
+ * 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 ExecState {
+ friend class Interpreter;
+ friend class FunctionImp;
+ friend class RuntimeMethodImp;
+ 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;
+
+ /**
+ * Returns the execution context associated with this execution state
+ *
+ * @return The current execution state context
+ */
+ Context* context() const { return m_context; }
+
+ void setException(JSValue* e) { m_exception = e; }
+ void clearException() { m_exception = 0; }
+ JSValue* exception() const { return m_exception; }
+ bool hadException() const { return m_exception; }
+
+ private:
+ ExecState(Interpreter* interp, Context* con)
+ : m_interpreter(interp)
+ , m_context(con)
+ , m_exception(0)
+ {
+ }
+ Interpreter* m_interpreter;
+ Context* m_context;
+ JSValue* m_exception;
+ };
+
+} // namespace KJS
+
+#endif // ExecState_H
--- /dev/null
+// -*- c-basic-offset: 2 -*-
+/*
+ * 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, 2004, 2005, 2006 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 SavedBuiltins_H
+#define SavedBuiltins_H
+
+namespace KJS {
+
+class SavedBuiltinsInternal;
+
+class SavedBuiltins {
+ friend class Interpreter;
+public:
+ SavedBuiltins();
+ ~SavedBuiltins();
+private:
+ SavedBuiltinsInternal *_internal;
+};
+
+class SavedBuiltinsInternal {
+ friend class Interpreter;
+private:
+ ProtectedPtr<JSObject> m_Object;
+ ProtectedPtr<JSObject> m_Function;
+ ProtectedPtr<JSObject> m_Array;
+ ProtectedPtr<JSObject> m_Boolean;
+ ProtectedPtr<JSObject> m_String;
+ ProtectedPtr<JSObject> m_Number;
+ ProtectedPtr<JSObject> m_Date;
+ ProtectedPtr<JSObject> m_RegExp;
+ ProtectedPtr<JSObject> m_Error;
+
+ ProtectedPtr<JSObject> m_ObjectPrototype;
+ ProtectedPtr<JSObject> m_FunctionPrototype;
+ ProtectedPtr<JSObject> m_ArrayPrototype;
+ ProtectedPtr<JSObject> m_BooleanPrototype;
+ ProtectedPtr<JSObject> m_StringPrototype;
+ ProtectedPtr<JSObject> m_NumberPrototype;
+ ProtectedPtr<JSObject> m_DatePrototype;
+ ProtectedPtr<JSObject> m_RegExpPrototype;
+ ProtectedPtr<JSObject> m_ErrorPrototype;
+
+ ProtectedPtr<JSObject> m_EvalError;
+ ProtectedPtr<JSObject> m_RangeError;
+ ProtectedPtr<JSObject> m_ReferenceError;
+ ProtectedPtr<JSObject> m_SyntaxError;
+ ProtectedPtr<JSObject> m_TypeError;
+ ProtectedPtr<JSObject> m_UriError;
+
+ ProtectedPtr<JSObject> m_EvalErrorPrototype;
+ ProtectedPtr<JSObject> m_RangeErrorPrototype;
+ ProtectedPtr<JSObject> m_ReferenceErrorPrototype;
+ ProtectedPtr<JSObject> m_SyntaxErrorPrototype;
+ ProtectedPtr<JSObject> m_TypeErrorPrototype;
+ ProtectedPtr<JSObject> m_UriErrorPrototype;
+};
+
+} // namespace
+
+#endif // SavedBuiltins_H
BooleanPrototype::BooleanPrototype(ExecState* exec, ObjectPrototype* objectProto, FunctionPrototype* funcProto)
: BooleanInstance(objectProto)
{
- // The constructor will be added later by InterpreterImp::InterpreterImp()
+ // The constructor will be added later by Interpreter::Interpreter()
putDirectFunction(new BooleanProtoFunc(exec, funcProto, BooleanProtoFunc::ToString, 0, toStringPropertyName), DontEnum);
putDirectFunction(new BooleanProtoFunc(exec, funcProto, BooleanProtoFunc::ValueOf, 0, valueOfPropertyName), DontEnum);
bool currentThreadIsMainThread = true;
#endif
- if (InterpreterImp::s_hook) {
- InterpreterImp *scr = InterpreterImp::s_hook;
+ if (Interpreter::s_hook) {
+ Interpreter* scr = Interpreter::s_hook;
do {
scr->mark(currentThreadIsMainThread);
scr = scr->next;
- } while (scr != InterpreterImp::s_hook);
+ } while (scr != Interpreter::s_hook);
}
// MARK: first mark all referenced objects recursively starting out from the set of root objects
size_t Collector::numInterpreters()
{
size_t count = 0;
- if (InterpreterImp::s_hook) {
- InterpreterImp *scr = InterpreterImp::s_hook;
+ if (Interpreter::s_hook) {
+ Interpreter* scr = Interpreter::s_hook;
do {
++count;
scr = scr->next;
- } while (scr != InterpreterImp::s_hook);
+ } while (scr != Interpreter::s_hook);
}
return count;
}
*/
class Context {
public:
- Context(JSObject* global, InterpreterImp*, JSObject* thisV,
+ Context(JSObject* global, Interpreter*, JSObject* thisV,
FunctionBodyNode* currentBody, CodeType type = GlobalCode,
Context* callingContext = 0, FunctionImp* function = 0, const List* args = 0);
~Context();
// Contexts are always stack-allocated, and the garbage collector
// marks the stack, so we don't need to protect the objects below from GC.
- InterpreterImp* m_interpreter;
+ Interpreter* m_interpreter;
Context* m_callingContext;
FunctionBodyNode* m_currentBody;
delete rep;
}
-void Debugger::attach(Interpreter *interp)
+void Debugger::attach(Interpreter* interp)
{
- Debugger *other = interp->imp()->debugger();
+ Debugger *other = interp->debugger();
if (other == this)
return;
if (other)
other->detach(interp);
- interp->imp()->setDebugger(this);
+ interp->setDebugger(this);
rep->interps = new AttachedInterpreter(interp, rep->interps);
}
-void Debugger::detach(Interpreter *interp)
+void Debugger::detach(Interpreter* interp)
{
- if (interp && interp->imp()->debugger() == this)
- interp->imp()->setDebugger(0);
+ if (interp && interp->debugger() == this)
+ interp->setDebugger(0);
// iterate the addresses where AttachedInterpreter pointers are stored
// so we can unlink items from the list
JSObject *globalObj = exec->dynamicInterpreter()->globalObject();
// enter a new execution context
- Context ctx(globalObj, exec->dynamicInterpreter()->imp(), thisObj, body.get(),
+ Context ctx(globalObj, exec->dynamicInterpreter(), thisObj, body.get(),
codeType(), exec->context(), this, &args);
ExecState newExec(exec->dynamicInterpreter(), &ctx);
newExec.setException(exec->exception()); // could be null
// add variable declarations (initialized to undefined)
processVarDecls(&newExec);
- Debugger *dbg = exec->dynamicInterpreter()->imp()->debugger();
+ Debugger *dbg = exec->dynamicInterpreter()->debugger();
int sid = -1;
int lineno = -1;
if (dbg) {
UString errMsg;
RefPtr<ProgramNode> progNode(Parser::parse(UString(), 0, s.data(),s.size(),&sid,&errLine,&errMsg));
- Debugger *dbg = exec->dynamicInterpreter()->imp()->debugger();
+ Debugger *dbg = exec->dynamicInterpreter()->debugger();
if (dbg) {
bool cont = dbg->sourceParsed(exec, sid, UString(), s, errLine);
if (!cont)
// enter a new execution context
JSObject *thisVal = static_cast<JSObject *>(exec->context()->thisValue());
Context ctx(exec->dynamicInterpreter()->globalObject(),
- exec->dynamicInterpreter()->imp(),
+ exec->dynamicInterpreter(),
thisVal,
progNode.get(),
EvalCode,
RefPtr<ProgramNode> progNode = Parser::parse(sourceURL, lineNumber, body.data(),body.size(),&sid,&errLine,&errMsg);
// notify debugger that source has been parsed
- Debugger *dbg = exec->dynamicInterpreter()->imp()->debugger();
+ Debugger *dbg = exec->dynamicInterpreter()->debugger();
if (dbg) {
// send empty sourceURL to indicate constructed code
bool cont = dbg->sourceParsed(exec,sid,UString(),body,errLine);
return false;
}
-// ------------------------------ InterpreterImp -------------------------------
-
-InterpreterImp* InterpreterImp::s_hook = 0L;
-
-typedef HashMap<JSObject *, InterpreterImp *> InterpreterMap;
-
-static inline InterpreterMap &interpreterMap()
-{
- static InterpreterMap *map = new InterpreterMap;
- return *map;
-}
-
-InterpreterImp::InterpreterImp(Interpreter *interp, JSObject *glob)
- : globExec(interp, 0)
- , _context(0)
-{
- // add this interpreter to the global chain
- // as a root set for garbage collection
- JSLock lock;
-
- m_interpreter = interp;
- if (s_hook) {
- prev = s_hook;
- next = s_hook->next;
- s_hook->next->prev = this;
- s_hook->next = this;
- } else {
- // This is the first interpreter
- s_hook = next = prev = this;
- }
-
- interpreterMap().set(glob, this);
-
- global = glob;
- dbg = 0;
- m_compatMode = Interpreter::NativeMode;
-
- // initialize properties of the global object
- initGlobalObject();
-
- recursion = 0;
-}
-
-void InterpreterImp::initGlobalObject()
-{
- Identifier::init();
-
- // Contructor prototype objects (Object.prototype, Array.prototype etc)
-
- FunctionPrototype *funcProto = new FunctionPrototype(&globExec);
- b_FunctionPrototype = funcProto;
- ObjectPrototype *objProto = new ObjectPrototype(&globExec, funcProto);
- b_ObjectPrototype = objProto;
- funcProto->setPrototype(b_ObjectPrototype);
-
- ArrayPrototype *arrayProto = new ArrayPrototype(&globExec, objProto);
- b_ArrayPrototype = arrayProto;
- StringPrototype *stringProto = new StringPrototype(&globExec, objProto);
- b_StringPrototype = stringProto;
- BooleanPrototype *booleanProto = new BooleanPrototype(&globExec, objProto, funcProto);
- b_BooleanPrototype = booleanProto;
- NumberPrototype *numberProto = new NumberPrototype(&globExec, objProto, funcProto);
- b_NumberPrototype = numberProto;
- DatePrototype *dateProto = new DatePrototype(&globExec, objProto);
- b_DatePrototype = dateProto;
- RegExpPrototype *regexpProto = new RegExpPrototype(&globExec, objProto, funcProto);
- b_RegExpPrototype = regexpProto;
- ErrorPrototype *errorProto = new ErrorPrototype(&globExec, objProto, funcProto);
- b_ErrorPrototype = errorProto;
-
- JSObject* o = global;
- while (o->prototype()->isObject())
- o = static_cast<JSObject*>(o->prototype());
- o->setPrototype(b_ObjectPrototype);
-
- // Constructors (Object, Array, etc.)
- b_Object = new ObjectObjectImp(&globExec, objProto, funcProto);
- b_Function = new FunctionObjectImp(&globExec, funcProto);
- b_Array = new ArrayObjectImp(&globExec, funcProto, arrayProto);
- b_String = new StringObjectImp(&globExec, funcProto, stringProto);
- b_Boolean = new BooleanObjectImp(&globExec, funcProto, booleanProto);
- b_Number = new NumberObjectImp(&globExec, funcProto, numberProto);
- b_Date = new DateObjectImp(&globExec, funcProto, dateProto);
- b_RegExp = new RegExpObjectImp(&globExec, funcProto, regexpProto);
- b_Error = new ErrorObjectImp(&globExec, funcProto, errorProto);
-
- // Error object prototypes
- b_evalErrorPrototype = new NativeErrorPrototype(&globExec, errorProto, EvalError, "EvalError", "EvalError");
- b_rangeErrorPrototype = new NativeErrorPrototype(&globExec, errorProto, RangeError, "RangeError", "RangeError");
- b_referenceErrorPrototype = new NativeErrorPrototype(&globExec, errorProto, ReferenceError, "ReferenceError", "ReferenceError");
- b_syntaxErrorPrototype = new NativeErrorPrototype(&globExec, errorProto, SyntaxError, "SyntaxError", "SyntaxError");
- b_typeErrorPrototype = new NativeErrorPrototype(&globExec, errorProto, TypeError, "TypeError", "TypeError");
- b_uriErrorPrototype = new NativeErrorPrototype(&globExec, errorProto, URIError, "URIError", "URIError");
-
- // Error objects
- b_evalError = new NativeErrorImp(&globExec, funcProto, b_evalErrorPrototype);
- b_rangeError = new NativeErrorImp(&globExec, funcProto, b_rangeErrorPrototype);
- b_referenceError = new NativeErrorImp(&globExec, funcProto, b_referenceErrorPrototype);
- b_syntaxError = new NativeErrorImp(&globExec, funcProto, b_syntaxErrorPrototype);
- b_typeError = new NativeErrorImp(&globExec, funcProto, b_typeErrorPrototype);
- b_uriError = new NativeErrorImp(&globExec, funcProto, b_uriErrorPrototype);
-
- // ECMA 15.3.4.1
- funcProto->put(&globExec, constructorPropertyName, b_Function, DontEnum);
-
- global->put(&globExec, "Object", b_Object, DontEnum);
- global->put(&globExec, "Function", b_Function, DontEnum);
- global->put(&globExec, "Array", b_Array, DontEnum);
- global->put(&globExec, "Boolean", b_Boolean, DontEnum);
- global->put(&globExec, "String", b_String, DontEnum);
- global->put(&globExec, "Number", b_Number, DontEnum);
- global->put(&globExec, "Date", b_Date, DontEnum);
- global->put(&globExec, "RegExp", b_RegExp, DontEnum);
- global->put(&globExec, "Error", b_Error, DontEnum);
- // Using Internal for those to have something != 0
- // (see kjs_window). Maybe DontEnum would be ok too ?
- global->put(&globExec, "EvalError",b_evalError, Internal);
- global->put(&globExec, "RangeError",b_rangeError, Internal);
- global->put(&globExec, "ReferenceError",b_referenceError, Internal);
- global->put(&globExec, "SyntaxError",b_syntaxError, Internal);
- global->put(&globExec, "TypeError",b_typeError, Internal);
- global->put(&globExec, "URIError",b_uriError, Internal);
-
- // Set the constructorPropertyName property of all builtin constructors
- objProto->put(&globExec, constructorPropertyName, b_Object, DontEnum | DontDelete | ReadOnly);
- funcProto->put(&globExec, constructorPropertyName, b_Function, DontEnum | DontDelete | ReadOnly);
- arrayProto->put(&globExec, constructorPropertyName, b_Array, DontEnum | DontDelete | ReadOnly);
- booleanProto->put(&globExec, constructorPropertyName, b_Boolean, DontEnum | DontDelete | ReadOnly);
- stringProto->put(&globExec, constructorPropertyName, b_String, DontEnum | DontDelete | ReadOnly);
- numberProto->put(&globExec, constructorPropertyName, b_Number, DontEnum | DontDelete | ReadOnly);
- dateProto->put(&globExec, constructorPropertyName, b_Date, DontEnum | DontDelete | ReadOnly);
- regexpProto->put(&globExec, constructorPropertyName, b_RegExp, DontEnum | DontDelete | ReadOnly);
- errorProto->put(&globExec, constructorPropertyName, b_Error, DontEnum | DontDelete | ReadOnly);
- b_evalErrorPrototype->put(&globExec, constructorPropertyName, b_evalError, DontEnum | DontDelete | ReadOnly);
- b_rangeErrorPrototype->put(&globExec, constructorPropertyName, b_rangeError, DontEnum | DontDelete | ReadOnly);
- b_referenceErrorPrototype->put(&globExec, constructorPropertyName, b_referenceError, DontEnum | DontDelete | ReadOnly);
- b_syntaxErrorPrototype->put(&globExec, constructorPropertyName, b_syntaxError, DontEnum | DontDelete | ReadOnly);
- b_typeErrorPrototype->put(&globExec, constructorPropertyName, b_typeError, DontEnum | DontDelete | ReadOnly);
- b_uriErrorPrototype->put(&globExec, constructorPropertyName, b_uriError, DontEnum | DontDelete | ReadOnly);
-
- // built-in values
- global->put(&globExec, "NaN", jsNaN(), DontEnum|DontDelete);
- global->put(&globExec, "Infinity", jsNumber(Inf), DontEnum|DontDelete);
- global->put(&globExec, "undefined", jsUndefined(), DontEnum|DontDelete);
-
- // built-in functions
- global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::Eval, 1, "eval"), DontEnum);
- global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::ParseInt, 2, "parseInt"), DontEnum);
- global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::ParseFloat, 1, "parseFloat"), DontEnum);
- global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::IsNaN, 1, "isNaN"), DontEnum);
- global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::IsFinite, 1, "isFinite"), DontEnum);
- global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::Escape, 1, "escape"), DontEnum);
- global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::UnEscape, 1, "unescape"), DontEnum);
- global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::DecodeURI, 1, "decodeURI"), DontEnum);
- global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::DecodeURIComponent, 1, "decodeURIComponent"), DontEnum);
- global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::EncodeURI, 1, "encodeURI"), DontEnum);
- global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::EncodeURIComponent, 1, "encodeURIComponent"), DontEnum);
-#ifndef NDEBUG
- global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::KJSPrint, 1, "kjsprint"), DontEnum);
-#endif
-
- // built-in objects
- global->put(&globExec, "Math", new MathObjectImp(&globExec, objProto), DontEnum);
-}
-
-InterpreterImp::~InterpreterImp()
-{
- if (dbg)
- dbg->detach(m_interpreter);
- clear();
-}
-
-void InterpreterImp::clear()
-{
- //fprintf(stderr,"InterpreterImp::clear\n");
- // remove from global chain (see init())
- JSLock lock;
-
- next->prev = prev;
- prev->next = next;
- s_hook = next;
- if (s_hook == this)
- {
- // This was the last interpreter
- s_hook = 0L;
- }
- interpreterMap().remove(global);
-}
-
-void InterpreterImp::mark(bool currentThreadIsMainThread)
-{
- if (m_interpreter)
- m_interpreter->mark(currentThreadIsMainThread);
- if (_context)
- _context->mark();
- if (global)
- global->mark();
- if (globExec.exception())
- globExec.exception()->mark();
-}
-
-bool InterpreterImp::checkSyntax(const UString &code)
-{
- JSLock lock;
-
- // Parser::parse() returns 0 in a syntax error occurs, so we just check for that
- RefPtr<ProgramNode> progNode = Parser::parse(UString(), 0, code.data(), code.size(), 0, 0, 0);
- return progNode;
-}
-
-Completion InterpreterImp::evaluate(const UChar* code, int codeLength, JSValue* thisV, const UString& sourceURL, int startingLineNumber)
-{
- JSLock lock;
-
- // prevent against infinite recursion
- if (recursion >= 20)
- return Completion(Throw, Error::create(&globExec, GeneralError, "Recursion too deep"));
-
- // parse the source code
- int sid;
- int errLine;
- UString errMsg;
- RefPtr<ProgramNode> progNode = Parser::parse(sourceURL, startingLineNumber, code, codeLength, &sid, &errLine, &errMsg);
-
- // notify debugger that source has been parsed
- if (dbg) {
- bool cont = dbg->sourceParsed(&globExec, sid, sourceURL, UString(code, codeLength), errLine);
- if (!cont)
- return Completion(Break);
- }
-
- // no program node means a syntax error occurred
- if (!progNode)
- return Completion(Throw, Error::create(&globExec, SyntaxError, errMsg, errLine, sid, &sourceURL));
-
- globExec.clearException();
-
- recursion++;
-
- JSObject* globalObj = globalObject();
- JSObject* thisObj = globalObj;
-
- // "this" must be an object... use same rules as Function.prototype.apply()
- if (thisV && !thisV->isUndefinedOrNull())
- thisObj = thisV->toObject(&globExec);
-
- Completion res;
- if (globExec.hadException())
- // the thisV->toObject() conversion above might have thrown an exception - if so, propagate it
- res = Completion(Throw, globExec.exception());
- else {
- // execute the code
- Context ctx(globalObj, this, thisObj, progNode.get());
- ExecState newExec(m_interpreter, &ctx);
- progNode->processVarDecls(&newExec);
- res = progNode->execute(&newExec);
- }
-
- recursion--;
-
- return res;
-}
-
-void InterpreterImp::saveBuiltins (SavedBuiltins &builtins) const
-{
- if (!builtins._internal) {
- builtins._internal = new SavedBuiltinsInternal;
- }
-
- builtins._internal->b_Object = b_Object;
- builtins._internal->b_Function = b_Function;
- builtins._internal->b_Array = b_Array;
- builtins._internal->b_Boolean = b_Boolean;
- builtins._internal->b_String = b_String;
- builtins._internal->b_Number = b_Number;
- builtins._internal->b_Date = b_Date;
- builtins._internal->b_RegExp = b_RegExp;
- builtins._internal->b_Error = b_Error;
-
- builtins._internal->b_ObjectPrototype = b_ObjectPrototype;
- builtins._internal->b_FunctionPrototype = b_FunctionPrototype;
- builtins._internal->b_ArrayPrototype = b_ArrayPrototype;
- builtins._internal->b_BooleanPrototype = b_BooleanPrototype;
- builtins._internal->b_StringPrototype = b_StringPrototype;
- builtins._internal->b_NumberPrototype = b_NumberPrototype;
- builtins._internal->b_DatePrototype = b_DatePrototype;
- builtins._internal->b_RegExpPrototype = b_RegExpPrototype;
- builtins._internal->b_ErrorPrototype = b_ErrorPrototype;
-
- builtins._internal->b_evalError = b_evalError;
- builtins._internal->b_rangeError = b_rangeError;
- builtins._internal->b_referenceError = b_referenceError;
- builtins._internal->b_syntaxError = b_syntaxError;
- builtins._internal->b_typeError = b_typeError;
- builtins._internal->b_uriError = b_uriError;
-
- builtins._internal->b_evalErrorPrototype = b_evalErrorPrototype;
- builtins._internal->b_rangeErrorPrototype = b_rangeErrorPrototype;
- builtins._internal->b_referenceErrorPrototype = b_referenceErrorPrototype;
- builtins._internal->b_syntaxErrorPrototype = b_syntaxErrorPrototype;
- builtins._internal->b_typeErrorPrototype = b_typeErrorPrototype;
- builtins._internal->b_uriErrorPrototype = b_uriErrorPrototype;
-}
-
-void InterpreterImp::restoreBuiltins (const SavedBuiltins &builtins)
-{
- if (!builtins._internal) {
- return;
- }
-
- b_Object = builtins._internal->b_Object;
- b_Function = builtins._internal->b_Function;
- b_Array = builtins._internal->b_Array;
- b_Boolean = builtins._internal->b_Boolean;
- b_String = builtins._internal->b_String;
- b_Number = builtins._internal->b_Number;
- b_Date = builtins._internal->b_Date;
- b_RegExp = builtins._internal->b_RegExp;
- b_Error = builtins._internal->b_Error;
-
- b_ObjectPrototype = builtins._internal->b_ObjectPrototype;
- b_FunctionPrototype = builtins._internal->b_FunctionPrototype;
- b_ArrayPrototype = builtins._internal->b_ArrayPrototype;
- b_BooleanPrototype = builtins._internal->b_BooleanPrototype;
- b_StringPrototype = builtins._internal->b_StringPrototype;
- b_NumberPrototype = builtins._internal->b_NumberPrototype;
- b_DatePrototype = builtins._internal->b_DatePrototype;
- b_RegExpPrototype = builtins._internal->b_RegExpPrototype;
- b_ErrorPrototype = builtins._internal->b_ErrorPrototype;
-
- b_evalError = builtins._internal->b_evalError;
- b_rangeError = builtins._internal->b_rangeError;
- b_referenceError = builtins._internal->b_referenceError;
- b_syntaxError = builtins._internal->b_syntaxError;
- b_typeError = builtins._internal->b_typeError;
- b_uriError = builtins._internal->b_uriError;
-
- b_evalErrorPrototype = builtins._internal->b_evalErrorPrototype;
- b_rangeErrorPrototype = builtins._internal->b_rangeErrorPrototype;
- b_referenceErrorPrototype = builtins._internal->b_referenceErrorPrototype;
- b_syntaxErrorPrototype = builtins._internal->b_syntaxErrorPrototype;
- b_typeErrorPrototype = builtins._internal->b_typeErrorPrototype;
- b_uriErrorPrototype = builtins._internal->b_uriErrorPrototype;
-}
-
-InterpreterImp *InterpreterImp::interpreterWithGlobalObject(JSObject *global)
-{
- return interpreterMap().get(global);
-}
-
-
// ------------------------------ InternalFunctionImp --------------------------
const ClassInfo InternalFunctionImp::info = {"Function", 0, 0, 0};
namespace KJS {
- class Debugger;
class FunctionPrototype;
// ---------------------------------------------------------------------------
class NumberImp : public JSCell {
friend class ConstantValues;
- friend class InterpreterImp;
friend JSValue *jsNumberCell(double);
public:
double value() const { return val; }
FunctionCode,
AnonymousCode };
- class SavedBuiltinsInternal {
- friend class InterpreterImp;
- private:
- ProtectedPtr<JSObject> b_Object;
- ProtectedPtr<JSObject> b_Function;
- ProtectedPtr<JSObject> b_Array;
- ProtectedPtr<JSObject> b_Boolean;
- ProtectedPtr<JSObject> b_String;
- ProtectedPtr<JSObject> b_Number;
- ProtectedPtr<JSObject> b_Date;
- ProtectedPtr<JSObject> b_RegExp;
- ProtectedPtr<JSObject> b_Error;
-
- ProtectedPtr<JSObject> b_ObjectPrototype;
- ProtectedPtr<JSObject> b_FunctionPrototype;
- ProtectedPtr<JSObject> b_ArrayPrototype;
- ProtectedPtr<JSObject> b_BooleanPrototype;
- ProtectedPtr<JSObject> b_StringPrototype;
- ProtectedPtr<JSObject> b_NumberPrototype;
- ProtectedPtr<JSObject> b_DatePrototype;
- ProtectedPtr<JSObject> b_RegExpPrototype;
- ProtectedPtr<JSObject> b_ErrorPrototype;
-
- ProtectedPtr<JSObject> b_evalError;
- ProtectedPtr<JSObject> b_rangeError;
- ProtectedPtr<JSObject> b_referenceError;
- ProtectedPtr<JSObject> b_syntaxError;
- ProtectedPtr<JSObject> b_typeError;
- ProtectedPtr<JSObject> b_uriError;
-
- ProtectedPtr<JSObject> b_evalErrorPrototype;
- ProtectedPtr<JSObject> b_rangeErrorPrototype;
- ProtectedPtr<JSObject> b_referenceErrorPrototype;
- ProtectedPtr<JSObject> b_syntaxErrorPrototype;
- ProtectedPtr<JSObject> b_typeErrorPrototype;
- ProtectedPtr<JSObject> b_uriErrorPrototype;
- };
-
- class InterpreterImp {
- friend class Collector;
- public:
- InterpreterImp(Interpreter *interp, JSObject *glob);
- ~InterpreterImp();
-
- JSObject *globalObject() { return global; }
- Interpreter *interpreter() const { return m_interpreter; }
-
- void initGlobalObject();
-
- void mark(bool currentThreadIsMainThread);
-
- ExecState *globalExec() { return &globExec; }
- bool checkSyntax(const UString &code);
- Completion evaluate(const UChar* code, int codeLength, JSValue* thisV, const UString& sourceURL, int startingLineNumber);
- Debugger *debugger() const { return dbg; }
- void setDebugger(Debugger *d) { dbg = d; }
-
- JSObject *builtinObject() const { return b_Object; }
- JSObject *builtinFunction() const { return b_Function; }
- JSObject *builtinArray() const { return b_Array; }
- JSObject *builtinBoolean() const { return b_Boolean; }
- JSObject *builtinString() const { return b_String; }
- JSObject *builtinNumber() const { return b_Number; }
- JSObject *builtinDate() const { return b_Date; }
- JSObject *builtinRegExp() const { return b_RegExp; }
- JSObject *builtinError() const { return b_Error; }
-
- JSObject *builtinObjectPrototype() const { return b_ObjectPrototype; }
- JSObject *builtinFunctionPrototype() const { return b_FunctionPrototype; }
- JSObject *builtinArrayPrototype() const { return b_ArrayPrototype; }
- JSObject *builtinBooleanPrototype() const { return b_BooleanPrototype; }
- JSObject *builtinStringPrototype() const { return b_StringPrototype; }
- JSObject *builtinNumberPrototype() const { return b_NumberPrototype; }
- JSObject *builtinDatePrototype() const { return b_DatePrototype; }
- JSObject *builtinRegExpPrototype() const { return b_RegExpPrototype; }
- JSObject *builtinErrorPrototype() const { return b_ErrorPrototype; }
-
- JSObject *builtinEvalError() const { return b_evalError; }
- JSObject *builtinRangeError() const { return b_rangeError; }
- JSObject *builtinReferenceError() const { return b_referenceError; }
- JSObject *builtinSyntaxError() const { return b_syntaxError; }
- JSObject *builtinTypeError() const { return b_typeError; }
- JSObject *builtinURIError() const { return b_uriError; }
-
- JSObject *builtinEvalErrorPrototype() const { return b_evalErrorPrototype; }
- JSObject *builtinRangeErrorPrototype() const { return b_rangeErrorPrototype; }
- JSObject *builtinReferenceErrorPrototype() const { return b_referenceErrorPrototype; }
- JSObject *builtinSyntaxErrorPrototype() const { return b_syntaxErrorPrototype; }
- JSObject *builtinTypeErrorPrototype() const { return b_typeErrorPrototype; }
- JSObject *builtinURIErrorPrototype() const { return b_uriErrorPrototype; }
-
- void setCompatMode(Interpreter::CompatMode mode) { m_compatMode = mode; }
- Interpreter::CompatMode compatMode() const { return m_compatMode; }
-
- // Chained list of interpreters (ring)
- static InterpreterImp* firstInterpreter() { return s_hook; }
- InterpreterImp *nextInterpreter() const { return next; }
- InterpreterImp *prevInterpreter() const { return prev; }
-
- static InterpreterImp *interpreterWithGlobalObject(JSObject *);
-
- void setContext(Context *c) { _context = c; }
- Context *context() const { return _context; }
-
- void saveBuiltins (SavedBuiltins &builtins) const;
- void restoreBuiltins (const SavedBuiltins &builtins);
-
- private:
- void clear();
- Interpreter *m_interpreter;
- JSObject *global;
- Debugger *dbg;
-
- // Built-in properties of the object prototype. These are accessible
- // from here even if they are replaced by js code (e.g. assigning to
- // Array.prototype)
-
- ProtectedPtr<JSObject> b_Object;
- ProtectedPtr<JSObject> b_Function;
- ProtectedPtr<JSObject> b_Array;
- ProtectedPtr<JSObject> b_Boolean;
- ProtectedPtr<JSObject> b_String;
- ProtectedPtr<JSObject> b_Number;
- ProtectedPtr<JSObject> b_Date;
- ProtectedPtr<JSObject> b_RegExp;
- ProtectedPtr<JSObject> b_Error;
-
- ProtectedPtr<JSObject> b_ObjectPrototype;
- ProtectedPtr<JSObject> b_FunctionPrototype;
- ProtectedPtr<JSObject> b_ArrayPrototype;
- ProtectedPtr<JSObject> b_BooleanPrototype;
- ProtectedPtr<JSObject> b_StringPrototype;
- ProtectedPtr<JSObject> b_NumberPrototype;
- ProtectedPtr<JSObject> b_DatePrototype;
- ProtectedPtr<JSObject> b_RegExpPrototype;
- ProtectedPtr<JSObject> b_ErrorPrototype;
-
- ProtectedPtr<JSObject> b_evalError;
- ProtectedPtr<JSObject> b_rangeError;
- ProtectedPtr<JSObject> b_referenceError;
- ProtectedPtr<JSObject> b_syntaxError;
- ProtectedPtr<JSObject> b_typeError;
- ProtectedPtr<JSObject> b_uriError;
-
- ProtectedPtr<JSObject> b_evalErrorPrototype;
- ProtectedPtr<JSObject> b_rangeErrorPrototype;
- ProtectedPtr<JSObject> b_referenceErrorPrototype;
- ProtectedPtr<JSObject> b_syntaxErrorPrototype;
- ProtectedPtr<JSObject> b_typeErrorPrototype;
- ProtectedPtr<JSObject> b_uriErrorPrototype;
-
- ExecState globExec;
- Interpreter::CompatMode m_compatMode;
-
- // Chained list of interpreters (ring) - for collector
- static InterpreterImp* s_hook;
- InterpreterImp *next, *prev;
-
- Context *_context;
-
- int recursion;
- };
-
class AttachedInterpreter;
class DebuggerImp {
public:
#include "config.h"
#include "interpreter.h"
-#include <assert.h>
-#include <math.h>
-#include <stdio.h>
-
+#include "SavedBuiltins.h"
+#include "array_object.h"
+#include "bool_object.h"
#include "collector.h"
#include "context.h"
+#include "date_object.h"
+#include "debugger.h"
#include "error_object.h"
+#include "function_object.h"
#include "internal.h"
+#include "math_object.h"
#include "nodes.h"
+#include "number_object.h"
#include "object.h"
+#include "object_object.h"
#include "operations.h"
+#include "regexp_object.h"
+#include "string_object.h"
#include "types.h"
#include "value.h"
#include "runtime.h"
#endif
-namespace KJS {
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
-// ------------------------------ Interpreter ----------------------------------
+namespace KJS {
-Interpreter::Interpreter(JSObject *global)
- : rep(0)
- , m_argumentsPropertyName(&argumentsPropertyName)
- , m_specialPrototypePropertyName(&specialPrototypePropertyName)
+Interpreter* Interpreter::s_hook = 0;
+
+typedef HashMap<JSObject*, Interpreter*> InterpreterMap;
+static inline InterpreterMap &interpreterMap()
+{
+ static InterpreterMap* map = new InterpreterMap;
+ return* map;
+}
+
+Interpreter::Interpreter(JSObject* globalObject)
+ : m_globalExec(this, 0)
+ , m_globalObject(globalObject)
+ , m_argumentsPropertyName(&argumentsPropertyName)
+ , m_specialPrototypePropertyName(&specialPrototypePropertyName)
{
- rep = new InterpreterImp(this, global);
+ init();
}
Interpreter::Interpreter()
- : rep(0)
- , m_argumentsPropertyName(&argumentsPropertyName)
- , m_specialPrototypePropertyName(&specialPrototypePropertyName)
+ : m_globalExec(this, 0)
+ , m_globalObject(new JSObject())
+ , m_argumentsPropertyName(&argumentsPropertyName)
+ , m_specialPrototypePropertyName(&specialPrototypePropertyName)
{
- rep = new InterpreterImp(this, new JSObject);
+ init();
+}
+
+void Interpreter::init()
+{
+ JSLock lock;
+
+ m_recursion = 0;
+ m_debugger= 0;
+ m_context = 0;
+ m_compatMode = NativeMode;
+
+ interpreterMap().set(m_globalObject, this);
+
+ if (s_hook) {
+ prev = s_hook;
+ next = s_hook->next;
+ s_hook->next->prev = this;
+ s_hook->next = this;
+ } else {
+ // This is the first interpreter
+ s_hook = next = prev = this;
+ }
+
+ initGlobalObject();
}
Interpreter::~Interpreter()
{
- delete rep;
+ JSLock lock;
+
+ if (m_debugger)
+ m_debugger->detach(this);
+
+ next->prev = prev;
+ prev->next = next;
+ s_hook = next;
+ if (s_hook == this)
+ {
+ // This was the last interpreter
+ s_hook = 0;
+ }
+
+ interpreterMap().remove(m_globalObject);
}
-JSObject *Interpreter::globalObject() const
+JSObject* Interpreter::globalObject() const
{
- return rep->globalObject();
+ return m_globalObject;
}
void Interpreter::initGlobalObject()
{
- rep->initGlobalObject();
+ Identifier::init();
+
+ FunctionPrototype *funcProto = new FunctionPrototype(&m_globalExec);
+ m_FunctionPrototype = funcProto;
+ ObjectPrototype *objProto = new ObjectPrototype(&m_globalExec, funcProto);
+ m_ObjectPrototype = objProto;
+ funcProto->setPrototype(m_ObjectPrototype);
+
+ ArrayPrototype *arrayProto = new ArrayPrototype(&m_globalExec, objProto);
+ m_ArrayPrototype = arrayProto;
+ StringPrototype *stringProto = new StringPrototype(&m_globalExec, objProto);
+ m_StringPrototype = stringProto;
+ BooleanPrototype *booleanProto = new BooleanPrototype(&m_globalExec, objProto, funcProto);
+ m_BooleanPrototype = booleanProto;
+ NumberPrototype *numberProto = new NumberPrototype(&m_globalExec, objProto, funcProto);
+ m_NumberPrototype = numberProto;
+ DatePrototype *dateProto = new DatePrototype(&m_globalExec, objProto);
+ m_DatePrototype = dateProto;
+ RegExpPrototype *regexpProto = new RegExpPrototype(&m_globalExec, objProto, funcProto);
+ m_RegExpPrototype = regexpProto;
+ ErrorPrototype *errorProto = new ErrorPrototype(&m_globalExec, objProto, funcProto);
+ m_ErrorPrototype = errorProto;
+
+ JSObject* o = m_globalObject;
+ while (o->prototype()->isObject())
+ o = static_cast<JSObject*>(o->prototype());
+ o->setPrototype(m_ObjectPrototype);
+
+ // Constructors (Object, Array, etc.)
+ m_Object = new ObjectObjectImp(&m_globalExec, objProto, funcProto);
+ m_Function = new FunctionObjectImp(&m_globalExec, funcProto);
+ m_Array = new ArrayObjectImp(&m_globalExec, funcProto, arrayProto);
+ m_String = new StringObjectImp(&m_globalExec, funcProto, stringProto);
+ m_Boolean = new BooleanObjectImp(&m_globalExec, funcProto, booleanProto);
+ m_Number = new NumberObjectImp(&m_globalExec, funcProto, numberProto);
+ m_Date = new DateObjectImp(&m_globalExec, funcProto, dateProto);
+ m_RegExp = new RegExpObjectImp(&m_globalExec, funcProto, regexpProto);
+ m_Error = new ErrorObjectImp(&m_globalExec, funcProto, errorProto);
+
+ // Error object prototypes
+ m_EvalErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, EvalError, "EvalError", "EvalError");
+ m_RangeErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, RangeError, "RangeError", "RangeError");
+ m_ReferenceErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, ReferenceError, "ReferenceError", "ReferenceError");
+ m_SyntaxErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, SyntaxError, "SyntaxError", "SyntaxError");
+ m_TypeErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, TypeError, "TypeError", "TypeError");
+ m_UriErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, URIError, "URIError", "URIError");
+
+ // Error objects
+ m_EvalError = new NativeErrorImp(&m_globalExec, funcProto, m_EvalErrorPrototype);
+ m_RangeError = new NativeErrorImp(&m_globalExec, funcProto, m_RangeErrorPrototype);
+ m_ReferenceError = new NativeErrorImp(&m_globalExec, funcProto, m_ReferenceErrorPrototype);
+ m_SyntaxError = new NativeErrorImp(&m_globalExec, funcProto, m_SyntaxErrorPrototype);
+ m_TypeError = new NativeErrorImp(&m_globalExec, funcProto, m_TypeErrorPrototype);
+ m_UriError = new NativeErrorImp(&m_globalExec, funcProto, m_UriErrorPrototype);
+
+ // ECMA 15.3.4.1
+ funcProto->put(&m_globalExec, constructorPropertyName, m_Function, DontEnum);
+
+ m_globalObject->put(&m_globalExec, "Object", m_Object, DontEnum);
+ m_globalObject->put(&m_globalExec, "Function", m_Function, DontEnum);
+ m_globalObject->put(&m_globalExec, "Array", m_Array, DontEnum);
+ m_globalObject->put(&m_globalExec, "Boolean", m_Boolean, DontEnum);
+ m_globalObject->put(&m_globalExec, "String", m_String, DontEnum);
+ m_globalObject->put(&m_globalExec, "Number", m_Number, DontEnum);
+ m_globalObject->put(&m_globalExec, "Date", m_Date, DontEnum);
+ m_globalObject->put(&m_globalExec, "RegExp", m_RegExp, DontEnum);
+ m_globalObject->put(&m_globalExec, "Error", m_Error, DontEnum);
+ // Using Internal for those to have something != 0
+ // (see kjs_window). Maybe DontEnum would be ok too ?
+ m_globalObject->put(&m_globalExec, "EvalError",m_EvalError, Internal);
+ m_globalObject->put(&m_globalExec, "RangeError",m_RangeError, Internal);
+ m_globalObject->put(&m_globalExec, "ReferenceError",m_ReferenceError, Internal);
+ m_globalObject->put(&m_globalExec, "SyntaxError",m_SyntaxError, Internal);
+ m_globalObject->put(&m_globalExec, "TypeError",m_TypeError, Internal);
+ m_globalObject->put(&m_globalExec, "URIError",m_UriError, Internal);
+
+ // Set the constructorPropertyName property of all builtin constructors
+ objProto->put(&m_globalExec, constructorPropertyName, m_Object, DontEnum | DontDelete | ReadOnly);
+ funcProto->put(&m_globalExec, constructorPropertyName, m_Function, DontEnum | DontDelete | ReadOnly);
+ arrayProto->put(&m_globalExec, constructorPropertyName, m_Array, DontEnum | DontDelete | ReadOnly);
+ booleanProto->put(&m_globalExec, constructorPropertyName, m_Boolean, DontEnum | DontDelete | ReadOnly);
+ stringProto->put(&m_globalExec, constructorPropertyName, m_String, DontEnum | DontDelete | ReadOnly);
+ numberProto->put(&m_globalExec, constructorPropertyName, m_Number, DontEnum | DontDelete | ReadOnly);
+ dateProto->put(&m_globalExec, constructorPropertyName, m_Date, DontEnum | DontDelete | ReadOnly);
+ regexpProto->put(&m_globalExec, constructorPropertyName, m_RegExp, DontEnum | DontDelete | ReadOnly);
+ errorProto->put(&m_globalExec, constructorPropertyName, m_Error, DontEnum | DontDelete | ReadOnly);
+ m_EvalErrorPrototype->put(&m_globalExec, constructorPropertyName, m_EvalError, DontEnum | DontDelete | ReadOnly);
+ m_RangeErrorPrototype->put(&m_globalExec, constructorPropertyName, m_RangeError, DontEnum | DontDelete | ReadOnly);
+ m_ReferenceErrorPrototype->put(&m_globalExec, constructorPropertyName, m_ReferenceError, DontEnum | DontDelete | ReadOnly);
+ m_SyntaxErrorPrototype->put(&m_globalExec, constructorPropertyName, m_SyntaxError, DontEnum | DontDelete | ReadOnly);
+ m_TypeErrorPrototype->put(&m_globalExec, constructorPropertyName, m_TypeError, DontEnum | DontDelete | ReadOnly);
+ m_UriErrorPrototype->put(&m_globalExec, constructorPropertyName, m_UriError, DontEnum | DontDelete | ReadOnly);
+
+ // built-in values
+ m_globalObject->put(&m_globalExec, "NaN", jsNaN(), DontEnum|DontDelete);
+ m_globalObject->put(&m_globalExec, "Infinity", jsNumber(Inf), DontEnum|DontDelete);
+ m_globalObject->put(&m_globalExec, "undefined", jsUndefined(), DontEnum|DontDelete);
+
+ // built-in functions
+ m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::Eval, 1, "eval"), DontEnum);
+ m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::ParseInt, 2, "parseInt"), DontEnum);
+ m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::ParseFloat, 1, "parseFloat"), DontEnum);
+ m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::IsNaN, 1, "isNaN"), DontEnum);
+ m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::IsFinite, 1, "isFinite"), DontEnum);
+ m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::Escape, 1, "escape"), DontEnum);
+ m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::UnEscape, 1, "unescape"), DontEnum);
+ m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::DecodeURI, 1, "decodeURI"), DontEnum);
+ m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::DecodeURIComponent, 1, "decodeURIComponent"), DontEnum);
+ m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::EncodeURI, 1, "encodeURI"), DontEnum);
+ m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::EncodeURIComponent, 1, "encodeURIComponent"), DontEnum);
+#ifndef NDEBUG
+ m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::KJSPrint, 1, "kjsprint"), DontEnum);
+#endif
+
+ // built-in objects
+ m_globalObject->put(&m_globalExec, "Math", new MathObjectImp(&m_globalExec, objProto), DontEnum);
}
-ExecState *Interpreter::globalExec()
+ExecState* Interpreter::globalExec()
{
- return rep->globalExec();
+ return &m_globalExec;
}
bool Interpreter::checkSyntax(const UString &code)
{
- return rep->checkSyntax(code);
+ JSLock lock;
+
+ // Parser::parse() returns 0 in a syntax error occurs
+ RefPtr<ProgramNode> progNode = Parser::parse(UString(), 0, code.data(), code.size(), 0, 0, 0);
+ return progNode;
}
Completion Interpreter::evaluate(const UString& sourceURL, int startingLineNumber, const UString& code, JSValue*)
Completion Interpreter::evaluate(const UString& sourceURL, int startingLineNumber, const UChar* code, int codeLength, JSValue* thisV)
{
- Completion comp = rep->evaluate(code, codeLength, thisV, sourceURL, startingLineNumber);
-
- if (shouldPrintExceptions() && comp.complType() == Throw) {
+ JSLock lock;
+
+ // prevent against infinite recursion
+ if (m_recursion >= 20)
+ return Completion(Throw, Error::create(&m_globalExec, GeneralError, "Recursion too deep"));
+
+ // parse the source code
+ int sid;
+ int errLine;
+ UString errMsg;
+ RefPtr<ProgramNode> progNode = Parser::parse(sourceURL, startingLineNumber, code, codeLength, &sid, &errLine, &errMsg);
+
+ // notify debugger that source has been parsed
+ if (m_debugger) {
+ bool cont = m_debugger->sourceParsed(&m_globalExec, sid, sourceURL, UString(code, codeLength), errLine);
+ if (!cont)
+ return Completion(Break);
+ }
+
+ // no program node means a syntax error occurred
+ if (!progNode)
+ return Completion(Throw, Error::create(&m_globalExec, SyntaxError, errMsg, errLine, sid, &sourceURL));
+
+ m_globalExec.clearException();
+
+ m_recursion++;
+
+ JSObject* globalObj = m_globalObject;
+ JSObject* thisObj = globalObj;
+
+ // "this" must be an object... use same rules as Function.prototype.apply()
+ if (thisV && !thisV->isUndefinedOrNull())
+ thisObj = thisV->toObject(&m_globalExec);
+
+ Completion res;
+ if (m_globalExec.hadException())
+ // the thisV->toObject() conversion above might have thrown an exception - if so, propagate it
+ res = Completion(Throw, m_globalExec.exception());
+ else {
+ // execute the code
+ Context ctx(globalObj, this, thisObj, progNode.get());
+ ExecState newExec(this, &ctx);
+ progNode->processVarDecls(&newExec);
+ res = progNode->execute(&newExec);
+ }
+
+ m_recursion--;
+
+ if (shouldPrintExceptions() && res.complType() == Throw) {
JSLock lock;
- ExecState *exec = rep->globalExec();
+ ExecState* exec = globalExec();
CString f = sourceURL.UTF8String();
- CString message = comp.value()->toObject(exec)->toString(exec).UTF8String();
- int line = comp.value()->toObject(exec)->get(exec, "line")->toUInt32(exec);
+ CString message = res.value()->toObject(exec)->toString(exec).UTF8String();
+ int line = res.value()->toObject(exec)->get(exec, "line")->toUInt32(exec);
#if PLATFORM(WIN_OS)
printf("%s line %d: %s\n", f.c_str(), line, message.c_str());
#else
#endif
}
- return comp;
+ return res;
}
JSObject *Interpreter::builtinObject() const
{
- return rep->builtinObject();
+ return m_Object;
}
JSObject *Interpreter::builtinFunction() const
{
- return rep->builtinFunction();
+ return m_Function;
}
JSObject *Interpreter::builtinArray() const
{
- return rep->builtinArray();
+ return m_Array;
}
JSObject *Interpreter::builtinBoolean() const
{
- return rep->builtinBoolean();
+ return m_Boolean;
}
JSObject *Interpreter::builtinString() const
{
- return rep->builtinString();
+ return m_String;
}
JSObject *Interpreter::builtinNumber() const
{
- return rep->builtinNumber();
+ return m_Number;
}
JSObject *Interpreter::builtinDate() const
{
- return rep->builtinDate();
+ return m_Date;
}
JSObject *Interpreter::builtinRegExp() const
{
- return rep->builtinRegExp();
+ return m_RegExp;
}
JSObject *Interpreter::builtinError() const
{
- return rep->builtinError();
+ return m_Error;
}
JSObject *Interpreter::builtinObjectPrototype() const
{
- return rep->builtinObjectPrototype();
+ return m_ObjectPrototype;
}
JSObject *Interpreter::builtinFunctionPrototype() const
{
- return rep->builtinFunctionPrototype();
+ return m_FunctionPrototype;
}
JSObject *Interpreter::builtinArrayPrototype() const
{
- return rep->builtinArrayPrototype();
+ return m_ArrayPrototype;
}
JSObject *Interpreter::builtinBooleanPrototype() const
{
- return rep->builtinBooleanPrototype();
+ return m_BooleanPrototype;
}
JSObject *Interpreter::builtinStringPrototype() const
{
- return rep->builtinStringPrototype();
+ return m_StringPrototype;
}
JSObject *Interpreter::builtinNumberPrototype() const
{
- return rep->builtinNumberPrototype();
+ return m_NumberPrototype;
}
JSObject *Interpreter::builtinDatePrototype() const
{
- return rep->builtinDatePrototype();
+ return m_DatePrototype;
}
JSObject *Interpreter::builtinRegExpPrototype() const
{
- return rep->builtinRegExpPrototype();
+ return m_RegExpPrototype;
}
JSObject *Interpreter::builtinErrorPrototype() const
{
- return rep->builtinErrorPrototype();
+ return m_ErrorPrototype;
}
JSObject *Interpreter::builtinEvalError() const
{
- return rep->builtinEvalError();
+ return m_EvalError;
}
JSObject *Interpreter::builtinRangeError() const
{
- return rep->builtinRangeError();
+ return m_RangeError;
}
JSObject *Interpreter::builtinReferenceError() const
{
- return rep->builtinReferenceError();
+ return m_ReferenceError;
}
JSObject *Interpreter::builtinSyntaxError() const
{
- return rep->builtinSyntaxError();
+ return m_SyntaxError;
}
JSObject *Interpreter::builtinTypeError() const
{
- return rep->builtinTypeError();
+ return m_TypeError;
}
JSObject *Interpreter::builtinURIError() const
{
- return rep->builtinURIError();
+ return m_UriError;
}
JSObject *Interpreter::builtinEvalErrorPrototype() const
{
- return rep->builtinEvalErrorPrototype();
+ return m_EvalErrorPrototype;
}
JSObject *Interpreter::builtinRangeErrorPrototype() const
{
- return rep->builtinRangeErrorPrototype();
+ return m_RangeErrorPrototype;
}
JSObject *Interpreter::builtinReferenceErrorPrototype() const
{
- return rep->builtinReferenceErrorPrototype();
+ return m_ReferenceErrorPrototype;
}
JSObject *Interpreter::builtinSyntaxErrorPrototype() const
{
- return rep->builtinSyntaxErrorPrototype();
+ return m_SyntaxErrorPrototype;
}
JSObject *Interpreter::builtinTypeErrorPrototype() const
{
- return rep->builtinTypeErrorPrototype();
+ return m_TypeErrorPrototype;
}
JSObject *Interpreter::builtinURIErrorPrototype() const
{
- return rep->builtinURIErrorPrototype();
-}
-
-void Interpreter::setCompatMode(CompatMode mode)
-{
- rep->setCompatMode(mode);
-}
-
-Interpreter::CompatMode Interpreter::compatMode() const
-{
- return rep->compatMode();
+ return m_UriErrorPrototype;
}
bool Interpreter::collect()
void Interpreter::mark(bool)
{
+ if (m_context)
+ m_context->mark();
+ if (m_globalObject && !m_globalObject->marked())
+ m_globalObject->mark();
+ if (m_globalExec.exception() && !m_globalExec.exception()->marked())
+ m_globalExec.exception()->mark();
+}
+
+Interpreter* Interpreter::interpreterWithGlobalObject(JSObject* globalObject)
+{
+ return interpreterMap().get(globalObject);
}
#ifdef KJS_DEBUG_MEM
}
#endif
-void Interpreter::saveBuiltins (SavedBuiltins &builtins) const
-{
- rep->saveBuiltins(builtins);
-}
-
-void Interpreter::restoreBuiltins (const SavedBuiltins &builtins)
-{
- rep->restoreBuiltins(builtins);
+void Interpreter::saveBuiltins (SavedBuiltins& builtins) const
+{
+ if (!builtins._internal)
+ builtins._internal = new SavedBuiltinsInternal;
+
+ builtins._internal->m_Object = m_Object;
+ builtins._internal->m_Function = m_Function;
+ builtins._internal->m_Array = m_Array;
+ builtins._internal->m_Boolean = m_Boolean;
+ builtins._internal->m_String = m_String;
+ builtins._internal->m_Number = m_Number;
+ builtins._internal->m_Date = m_Date;
+ builtins._internal->m_RegExp = m_RegExp;
+ builtins._internal->m_Error = m_Error;
+
+ builtins._internal->m_ObjectPrototype = m_ObjectPrototype;
+ builtins._internal->m_FunctionPrototype = m_FunctionPrototype;
+ builtins._internal->m_ArrayPrototype = m_ArrayPrototype;
+ builtins._internal->m_BooleanPrototype = m_BooleanPrototype;
+ builtins._internal->m_StringPrototype = m_StringPrototype;
+ builtins._internal->m_NumberPrototype = m_NumberPrototype;
+ builtins._internal->m_DatePrototype = m_DatePrototype;
+ builtins._internal->m_RegExpPrototype = m_RegExpPrototype;
+ builtins._internal->m_ErrorPrototype = m_ErrorPrototype;
+
+ builtins._internal->m_EvalError = m_EvalError;
+ builtins._internal->m_RangeError = m_RangeError;
+ builtins._internal->m_ReferenceError = m_ReferenceError;
+ builtins._internal->m_SyntaxError = m_SyntaxError;
+ builtins._internal->m_TypeError = m_TypeError;
+ builtins._internal->m_UriError = m_UriError;
+
+ builtins._internal->m_EvalErrorPrototype = m_EvalErrorPrototype;
+ builtins._internal->m_RangeErrorPrototype = m_RangeErrorPrototype;
+ builtins._internal->m_ReferenceErrorPrototype = m_ReferenceErrorPrototype;
+ builtins._internal->m_SyntaxErrorPrototype = m_SyntaxErrorPrototype;
+ builtins._internal->m_TypeErrorPrototype = m_TypeErrorPrototype;
+ builtins._internal->m_UriErrorPrototype = m_UriErrorPrototype;
+}
+
+void Interpreter::restoreBuiltins (const SavedBuiltins& builtins)
+{
+ if (!builtins._internal)
+ return;
+
+ m_Object = builtins._internal->m_Object;
+ m_Function = builtins._internal->m_Function;
+ m_Array = builtins._internal->m_Array;
+ m_Boolean = builtins._internal->m_Boolean;
+ m_String = builtins._internal->m_String;
+ m_Number = builtins._internal->m_Number;
+ m_Date = builtins._internal->m_Date;
+ m_RegExp = builtins._internal->m_RegExp;
+ m_Error = builtins._internal->m_Error;
+
+ m_ObjectPrototype = builtins._internal->m_ObjectPrototype;
+ m_FunctionPrototype = builtins._internal->m_FunctionPrototype;
+ m_ArrayPrototype = builtins._internal->m_ArrayPrototype;
+ m_BooleanPrototype = builtins._internal->m_BooleanPrototype;
+ m_StringPrototype = builtins._internal->m_StringPrototype;
+ m_NumberPrototype = builtins._internal->m_NumberPrototype;
+ m_DatePrototype = builtins._internal->m_DatePrototype;
+ m_RegExpPrototype = builtins._internal->m_RegExpPrototype;
+ m_ErrorPrototype = builtins._internal->m_ErrorPrototype;
+
+ m_EvalError = builtins._internal->m_EvalError;
+ m_RangeError = builtins._internal->m_RangeError;
+ m_ReferenceError = builtins._internal->m_ReferenceError;
+ m_SyntaxError = builtins._internal->m_SyntaxError;
+ m_TypeError = builtins._internal->m_TypeError;
+ m_UriError = builtins._internal->m_UriError;
+
+ m_EvalErrorPrototype = builtins._internal->m_EvalErrorPrototype;
+ m_RangeErrorPrototype = builtins._internal->m_RangeErrorPrototype;
+ m_ReferenceErrorPrototype = builtins._internal->m_ReferenceErrorPrototype;
+ m_SyntaxErrorPrototype = builtins._internal->m_SyntaxErrorPrototype;
+ m_TypeErrorPrototype = builtins._internal->m_TypeErrorPrototype;
+ m_UriErrorPrototype = builtins._internal->m_UriErrorPrototype;
}
SavedBuiltins::SavedBuiltins() :
delete _internal;
}
-Interpreter *ExecState::lexicalInterpreter() const
-{
- if (!m_context)
- return dynamicInterpreter();
-
- InterpreterImp *result = InterpreterImp::interpreterWithGlobalObject(m_context->scopeChain().bottom());
-
- if (!result)
- return dynamicInterpreter();
-
- return result->interpreter();
-}
-
}
#ifndef _KJS_INTERPRETER_H_
#define _KJS_INTERPRETER_H_
+#include "ExecState.h"
+#include "protect.h"
#include "value.h"
#include "types.h"
namespace KJS {
class Context;
- class InterpreterImp;
+ class Debugger;
class RuntimeMethod;
+ class SavedBuiltins;
class ScopeChain;
namespace Bindings {
class RootObject;
}
- 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
* " Object" and "Number".
*/
class Interpreter {
+ friend class Collector;
public:
/**
* Creates a new interpreter. The supplied object will be used as the global
*
* @param global The object to use as the global object for this interpreter
*/
- Interpreter(JSObject *global);
+ Interpreter(JSObject* globalObject);
/**
* Creates a new interpreter. A global object will be created and
* initialized with the standard global properties.
* Returns the object that is used as the global object during all script
* execution performed by this interpreter
*/
- JSObject *globalObject() const;
-
+ JSObject* globalObject() const;
void initGlobalObject();
/**
Completion evaluate(const UString& sourceURL, int startingLineNumber, const UString& code, JSValue* thisV = 0);
/**
- * @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
* 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;
-
+ 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 by InterpreterImp during the mark phase of the garbage collector
- * Default implementation does nothing, this exist for classes that reimplement Interpreter.
+ * 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(bool currentThreadIsMainThread);
static bool shouldPrintExceptions();
static void setShouldPrintExceptions(bool);
- void saveBuiltins (SavedBuiltins &) const;
- void restoreBuiltins (const SavedBuiltins &);
+ void saveBuiltins (SavedBuiltins&) const;
+ void restoreBuiltins (const SavedBuiltins&);
/**
* Determine if the value is a global object (for any interpreter). This may
const Identifier& argumentsIdentifier() { return *m_argumentsPropertyName; }
const Identifier& specialPrototypeIdentifier() { return *m_specialPrototypePropertyName; }
- private:
- InterpreterImp *rep;
-
- const Identifier *m_argumentsPropertyName;
- const Identifier *m_specialPrototypePropertyName;
+ // 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*);
+private:
+ void init();
+
/**
* 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&);
- };
-
- /**
- * 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;
- friend class RuntimeMethodImp;
- 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;
+
+ ExecState m_globalExec;
+ JSObject* m_globalObject;
- /**
- * Returns the execution context associated with this execution state
- *
- * @return The current execution state context
- */
- Context* context() const { return m_context; }
+ const Identifier *m_argumentsPropertyName;
+ const Identifier *m_specialPrototypePropertyName;
- void setException(JSValue* e) { m_exception = e; }
- void clearException() { m_exception = 0; }
- JSValue* exception() const { return m_exception; }
- bool hadException() const { return m_exception; }
-
- private:
- ExecState(Interpreter* interp, Context* con)
- : m_interpreter(interp)
- , m_context(con)
- , m_exception(0)
- {
- }
- Interpreter* m_interpreter;
+ // Chained list of interpreters (ring) - for collector
+ static Interpreter* s_hook;
+ Interpreter *next, *prev;
+
+ int m_recursion;
+
+ Debugger* m_debugger;
Context* m_context;
- JSValue* m_exception;
+ CompatMode m_compatMode;
+
+ ProtectedPtr<JSObject> m_Object;
+ ProtectedPtr<JSObject> m_Function;
+ ProtectedPtr<JSObject> m_Array;
+ ProtectedPtr<JSObject> m_Boolean;
+ ProtectedPtr<JSObject> m_String;
+ ProtectedPtr<JSObject> m_Number;
+ ProtectedPtr<JSObject> m_Date;
+ ProtectedPtr<JSObject> m_RegExp;
+ ProtectedPtr<JSObject> m_Error;
+
+ ProtectedPtr<JSObject> m_ObjectPrototype;
+ ProtectedPtr<JSObject> m_FunctionPrototype;
+ ProtectedPtr<JSObject> m_ArrayPrototype;
+ ProtectedPtr<JSObject> m_BooleanPrototype;
+ ProtectedPtr<JSObject> m_StringPrototype;
+ ProtectedPtr<JSObject> m_NumberPrototype;
+ ProtectedPtr<JSObject> m_DatePrototype;
+ ProtectedPtr<JSObject> m_RegExpPrototype;
+ ProtectedPtr<JSObject> m_ErrorPrototype;
+
+ ProtectedPtr<JSObject> m_EvalError;
+ ProtectedPtr<JSObject> m_RangeError;
+ ProtectedPtr<JSObject> m_ReferenceError;
+ ProtectedPtr<JSObject> m_SyntaxError;
+ ProtectedPtr<JSObject> m_TypeError;
+ ProtectedPtr<JSObject> m_UriError;
+
+ ProtectedPtr<JSObject> m_EvalErrorPrototype;
+ ProtectedPtr<JSObject> m_RangeErrorPrototype;
+ ProtectedPtr<JSObject> m_ReferenceErrorPrototype;
+ ProtectedPtr<JSObject> m_SyntaxErrorPrototype;
+ ProtectedPtr<JSObject> m_TypeErrorPrototype;
+ ProtectedPtr<JSObject> m_UriErrorPrototype;
};
} // namespace
// return true if the debugger wants us to stop at this point
bool StatementNode::hitStatement(ExecState* exec)
{
- Debugger *dbg = exec->dynamicInterpreter()->imp()->debugger();
+ Debugger *dbg = exec->dynamicInterpreter()->debugger();
if (dbg)
return dbg->atStatement(exec, currentSourceId(exec), firstLine(), lastLine());
else
list.append(jsString(pattern));
list.append(jsString(flags));
- JSObject *reg = exec->lexicalInterpreter()->imp()->builtinRegExp();
+ JSObject *reg = exec->lexicalInterpreter()->builtinRegExp();
return reg->construct(exec,list);
}
#ifndef _KJS_PROTECT_H_
#define _KJS_PROTECT_H_
-#include "reference.h"
#include "value.h"
#include "collector.h"
#include "JSLock.h"
+2006-06-12 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by TimO, Maciej.
+
+ - JSGlue part of merging InterpreterImp into Interpreter.
+
+ Since there's now a kjs forwarding header, I moved all forwarding
+ headers into a "ForwardingHeaders" directory, like in WebCore.
+
+ * ForwardingHeaders: Added.
+ * ForwardingHeaders/kjs: Added.
+ * ForwardingHeaders/kjs/ExecState.h: Added.
+ * ForwardingHeaders/wtf: Added.
+ * JavaScriptGlue.xcodeproj/project.pbxproj:
+ * config.h:
+ * wtf: Removed.
+ * wtf/AlwaysInline.h: Removed.
+ * wtf/Assertions.h: Removed.
+ * wtf/FastMalloc.h: Removed.
+ * wtf/Forward.h: Removed.
+ * wtf/HashCountedSet.h: Removed.
+ * wtf/HashSet.h: Removed.
+ * wtf/Noncopyable.h: Removed.
+ * wtf/OwnArrayPtr.h: Removed.
+ * wtf/OwnPtr.h: Removed.
+ * wtf/PassRefPtr.h: Removed.
+ * wtf/Platform.h: Removed.
+ * wtf/RefPtr.h: Removed.
+ * wtf/Vector.h: Removed.
+
=== JavaScriptGlue-521.10 ===
2006-05-09 Maciej Stachowiak <mjs@apple.com>
--- /dev/null
+#include <JavaScriptCore/ExecState.h>
buildConfigurationList = 1422E8DD09DE3EF500749B87 /* Build configuration list for PBXAggregateTarget "All" */;
buildPhases = (
);
- buildSettings = {
- PRODUCT_NAME = All;
- };
dependencies = (
1422E8CA09DE3EB100749B87 /* PBXTargetDependency */,
1422E8C809DE3EAD00749B87 /* PBXTargetDependency */,
DD66F3F608F7401B00C75FD7 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD66F3F508F7401B00C75FD7 /* JavaScriptCore.framework */; };
/* End PBXBuildFile section */
-/* Begin PBXBuildStyle section */
- 014CEA440018CDF011CA2923 /* Development */ = {
- isa = PBXBuildStyle;
- buildSettings = {
- COPY_PHASE_STRIP = NO;
- GCC_DYNAMIC_NO_PIC = NO;
- GCC_ENABLE_FIX_AND_CONTINUE = YES;
- GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
- GCC_OPTIMIZATION_LEVEL = 0;
- OPTIMIZATION_CFLAGS = "-O0";
- ZERO_LINK = YES;
- };
- name = Development;
- };
- 014CEA450018CDF011CA2923 /* Deployment */ = {
- isa = PBXBuildStyle;
- buildSettings = {
- COPY_PHASE_STRIP = YES;
- GCC_ENABLE_FIX_AND_CONTINUE = NO;
- ZERO_LINK = NO;
- };
- name = Deployment;
- };
-/* End PBXBuildStyle section */
-
/* Begin PBXContainerItemProxy section */
1422E8C709DE3EAD00749B87 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; indentWidth = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
1422E86709DE3BCE00749B87 /* testjsglue.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = testjsglue.cpp; sourceTree = "<group>"; };
- 1422E87709DE3BE800749B87 /* testjsglue */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testjsglue; sourceTree = BUILT_PRODUCTS_DIR; };
+ 1422E87709DE3BE800749B87 /* testjsglue */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = testjsglue; sourceTree = BUILT_PRODUCTS_DIR; };
DD66F3D508F73ED700C75FD7 /* Info.plist */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.xml; path = Info.plist; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
DD66F3D608F73ED700C75FD7 /* JavaScriptGlue.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JavaScriptGlue.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DD66F3F508F7401B00C75FD7 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = JavaScriptCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
);
buildRules = (
);
- buildSettings = {
- GCC_ENABLE_FIX_AND_CONTINUE = YES;
- GCC_MODEL_TUNING = G5;
- INSTALL_PATH = "$(HOME)/bin";
- PREBINDING = NO;
- PRODUCT_NAME = testjsglue;
- ZERO_LINK = YES;
- };
dependencies = (
);
name = testjsglue;
);
buildRules = (
);
- buildSettings = {
- DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 1;
- EXPORTED_SYMBOLS_FILE = JavaScriptGlue.exp;
- FRAMEWORK_SEARCH_PATHS = (
- "$(SYSTEM_LIBRARY_DIR)/Frameworks/WebKit.framework/Frameworks",
- "$(SYSTEM_LIBRARY_DIR)/Frameworks/WebKit.framework/Versions/A/Frameworks",
- );
- FRAMEWORK_VERSION = A;
- HEADER_SEARCH_PATHS = "";
- INSTALL_PATH = "$(NEXT_ROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks";
- LIBRARY_SEARCH_PATHS = "";
- OTHER_CFLAGS = "";
- OTHER_LDFLAGS = "";
- PRODUCT_NAME = JavaScriptGlue;
- SECTORDER_FLAGS = (
- "-sectorder",
- __TEXT,
- __text,
- "$(APPLE_INTERNAL_DIR)/OrderFiles/JavaScriptGlue.order",
- );
- WARNING_CFLAGS = (
- "-Wmost",
- "-Wno-four-char-constants",
- "-Wno-unknown-pragmas",
- );
- WRAPPER_EXTENSION = framework;
- };
dependencies = (
);
name = JavaScriptGlue;
0867D690FE84028FC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 14AC662B08CE7791006915A8 /* Build configuration list for PBXProject "JavaScriptGlue" */;
- buildSettings = {
- };
- buildStyles = (
- 014CEA440018CDF011CA2923 /* Development */,
- 014CEA450018CDF011CA2923 /* Deployment */,
- );
hasScannedForEncodings = 1;
mainGroup = 0867D691FE84028FC02AAC07 /* JavaScriptGlue */;
productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
DYLIB_CURRENT_VERSION = 1;
EXPORTED_SYMBOLS_FILE = JavaScriptGlue.exp;
FRAMEWORK_VERSION = A;
- HEADER_SEARCH_PATHS = .;
+ HEADER_SEARCH_PATHS = ForwardingHeaders;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(BUILT_PRODUCTS_DIR)";
PRODUCT_NAME = JavaScriptGlue;
DYLIB_CURRENT_VERSION = 1;
EXPORTED_SYMBOLS_FILE = JavaScriptGlue.exp;
FRAMEWORK_VERSION = A;
- HEADER_SEARCH_PATHS = .;
+ HEADER_SEARCH_PATHS = ForwardingHeaders;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(BUILT_PRODUCTS_DIR)";
PRODUCT_NAME = JavaScriptGlue;
EXPORTED_SYMBOLS_FILE = JavaScriptGlue.exp;
FRAMEWORK_SEARCH_PATHS = "$(SYSTEM_LIBRARY_DIR)/Frameworks/WebKit.framework/Versions/A/Frameworks";
FRAMEWORK_VERSION = A;
- HEADER_SEARCH_PATHS = .;
+ HEADER_SEARCH_PATHS = ForwardingHeaders;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks";
PRODUCT_NAME = JavaScriptGlue;
#include <wtf/Platform.h>
+#include <kjs/ExecState.h>
+2006-06-12 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by TimO, Maciej.
+
+ - WebCore part of merging InterpreterImp into Interpreter. No test
+ because there's no behavior change.
+
+ A substantive change here is that ScriptInterpreter::mark must now chain to
+ Interpreter::mark, since Interpreter needs to mark the things that
+ InterpreterImp used to mark.
+
+ * WebCore.xcodeproj/project.pbxproj:
+ * bindings/js/kjs_binding.cpp:
+ * bindings/js/kjs_window.cpp:
+ (KJS::Window::put):
+ * bridge/mac/WebCoreFrameBridge.mm:
+ * bridge/mac/WebCoreScriptDebugger.mm:
+ (-[WebCoreScriptCallFrame evaluateWebScript:]):
+ * kwq/KWQPageState.mm:
+
2006-06-12 Brady Eidson <beidson@apple.com>
Reviewed by Maciej.
#include "kjs_dom.h"
#include "kjs_window.h"
#include <kjs/collector.h>
-#include <kjs/internal.h> // for InterpreterImp
#include <wtf/HashMap.h>
using namespace WebCore;
object->mark();
}
}
+
+ Interpreter::mark(currentThreadIsMainThread);
}
ExecState *ScriptInterpreter::globalExec()
void Window::put(ExecState* exec, const Identifier &propertyName, JSValue *value, int attr)
{
- // Called by an internal KJS call (e.g. InterpreterImp's constructor) ?
+ // Called by an internal KJS call.
// If yes, save time and jump directly to JSObject.
if ((attr != None && attr != DontDelete)
// Same thing if we have a local override (e.g. "var location")
#import "xml_tokenizer.h"
#import <JavaScriptCore/date_object.h>
#import <JavaScriptCore/runtime_root.h>
+#import <kjs/SavedBuiltins.h>
@class NSView;
result = eval->call(state, NULL, args);
} else
// no "eval", or no context (i.e. global scope) - use global fallback
- result = interp->imp()->evaluate(code.data(), code.size(), globObj, UString(), 0).value();
+ result = interp->evaluate(UString(), 0, code.data(), code.size(), globObj).value();
if (state->hadException())
result = state->exception(); // (may be redundant depending on which eval path was used)
#import "FoundationExtras.h"
#import "FrameMac.h"
#import "kjs_window.h"
+#import <kjs/SavedBuiltins.h>
using namespace WebCore;
using namespace KJS;