diff --git a/js2/src/epimetheus.cpp b/js2/src/epimetheus.cpp index e3793b8ff6e3..72fd3c77cb58 100644 --- a/js2/src/epimetheus.cpp +++ b/js2/src/epimetheus.cpp @@ -97,8 +97,6 @@ const bool showTokens = false; #define INTERPRET_INPUT 1 //#define SHOW_ICODE 1 -MetaData::GlobalObject glob(world); -MetaData::Environment env(new MetaData::SystemFrame(), &glob); MetaData::JS2Metadata *metadata; @@ -140,10 +138,9 @@ static int readEvalPrint(FILE *in) } metadata->setCurrentParser(&p); // for error reporting - MetaData::Context cxt; - metadata->ValidateStmtList(&cxt, &env, parsedStatements); - metadata->EvalStmtList(&env, MetaData::RunPhase, parsedStatements); + metadata->ValidateStmtList(parsedStatements); + metadata->EvalStmtList(MetaData::RunPhase, parsedStatements); } clear(buffer); diff --git a/js2/src/exception.h b/js2/src/exception.h index d82ddfde3cdb..53ed22ee5f66 100644 --- a/js2/src/exception.h +++ b/js2/src/exception.h @@ -59,7 +59,8 @@ namespace JavaScript userException, definitionError, badValueError, - compileExpressionError + compileExpressionError, + propertyAccessError }; Kind kind; // The exception's kind diff --git a/js2/src/js2eval.cpp b/js2/src/js2eval.cpp index 3746d5606d3d..f5ecb165935f 100644 --- a/js2/src/js2eval.cpp +++ b/js2/src/js2eval.cpp @@ -69,20 +69,21 @@ namespace JavaScript { namespace MetaData { - JSRuntime *gMonkeyRuntime; - JSContext *gMonkeyContext; - JSObject *gMonkeyGlobalObject; JSClass gMonkeyGlobalClass = { "MyClass", 0, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub }; - JSClass gMonkeyMultinameClass = - { "Multiname", 0, JS_PropertyStub, JS_PropertyStub, - JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, - JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub }; - - // forward ref. + // forward refs. + static void Multiname_finalize(JSContext *cx, JSObject *obj); static void LexicalReference_finalize(JSContext *cx, JSObject *obj); + static void Namespace_finalize(JSContext *cx, JSObject *obj); + + JSClass gMonkeyMultinameClass = + { "Multiname", JSCLASS_HAS_PRIVATE, + JS_PropertyStub, JS_PropertyStub, + JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, + JS_ResolveStub, JS_ConvertStub, Multiname_finalize }; + JSClass gMonkeyLexicalReferenceClass = { "LexicalReference", JSCLASS_HAS_PRIVATE, @@ -90,6 +91,12 @@ namespace MetaData { JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, LexicalReference_finalize }; + JSClass gMonkeyNamespaceClass = + { "Namespace", JSCLASS_HAS_PRIVATE, + JS_PropertyStub, JS_PropertyStub, + JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, + JS_ResolveStub, JS_ConvertStub, Namespace_finalize }; + // member functions at global scope JSFunctionSpec jsfGlobal [] = { @@ -112,7 +119,7 @@ namespace MetaData { static JSBool LexicalReference_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { - ExecutionState *eState = static_cast(JS_GetContextPrivate(cx)); + JS2Metadata *meta = static_cast(JS_GetContextPrivate(cx)); ASSERT(argc == 2); ASSERT(JSVAL_IS_BOOLEAN(argv[0])); // the 'strict' flag (XXX what's that for?) @@ -122,7 +129,7 @@ namespace MetaData { ASSERT(OBJ_GET_CLASS(cx, multiNameObj) == &gMonkeyMultinameClass); Multiname *mName = static_cast(JS_GetPrivate(cx, multiNameObj)); - if (!JS_SetPrivate(cx, obj, new LexicalReference(mName, eState->env, (JSVAL_TO_BOOLEAN(argv[0])) == JS_TRUE) )) + if (!JS_SetPrivate(cx, obj, new LexicalReference(mName, &meta->env, (JSVAL_TO_BOOLEAN(argv[0])) == JS_TRUE) )) return JS_FALSE; return JS_TRUE; @@ -142,10 +149,10 @@ namespace MetaData { readLexicalReference(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { ASSERT(OBJ_GET_CLASS(cx, obj) == &gMonkeyLexicalReferenceClass); - ExecutionState *eState = static_cast(JS_GetContextPrivate(cx)); + JS2Metadata *meta = static_cast(JS_GetContextPrivate(cx)); LexicalReference *lRef = static_cast(JS_GetPrivate(cx, obj)); - eState->env->lexicalRead(eState, lRef->variableMultiname, RunPhase); + meta->env.lexicalRead(meta, lRef->variableMultiname, RunPhase); return JS_TRUE; } @@ -154,7 +161,7 @@ namespace MetaData { writeLexicalReference(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { ASSERT(OBJ_GET_CLASS(cx, obj) == &gMonkeyLexicalReferenceClass); - ExecutionState *eState = static_cast(JS_GetContextPrivate(cx)); + JS2Metadata *meta = static_cast(JS_GetContextPrivate(cx)); LexicalReference *lRef = static_cast(JS_GetPrivate(cx, obj)); @@ -179,35 +186,67 @@ namespace MetaData { static JSBool Multiname_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { + JS2Metadata *meta = static_cast(JS_GetContextPrivate(cx)); + ASSERT(argc >= 1); // could be just the base name ASSERT(OBJ_GET_CLASS(cx, obj) == &gMonkeyMultinameClass); ASSERT(JSVAL_IS_STRING(argv[0])); + JSString *str = JSVAL_TO_STRING(argv[0]); - // XXX use reserved slots instead - if (!JS_SetProperty(cx, obj, "name", &argv[0])) + Multiname *mName = new Multiname(meta->world.identifiers[String(JS_GetStringChars(str), JS_GetStringLength(str))]); + if (!JS_SetPrivate(cx, obj, mName)) return JS_FALSE; - jsval qualifierVal = JSVAL_NULL; - if (argc > 1) { - JSObject *qualArray = JS_NewArrayObject(cx, argc - 1, &argv[1]); - if (!qualArray) - return JS_FALSE; - qualifierVal = OBJECT_TO_JSVAL(qualArray); + for (uintN i = 1; i < argc; i++) { + ASSERT(JSVAL_IS_OBJECT(argv[i])); + JSObject *obj = JSVAL_TO_OBJECT(argv[i]); + ASSERT(OBJ_GET_CLASS(cx, obj) == &gMonkeyNamespaceClass); + Namespace *ns = static_cast(JS_GetPrivate(cx, obj)); + mName->addNamespace(ns); } - if (!JS_SetProperty(cx, obj, "qualifiers", &qualifierVal)) - return JS_FALSE; return JS_TRUE; } - // member functions in a Multiname - JSFunctionSpec jsfMultiname [] = + // finalize a Multiname - called by Monkey gc + static void + Multiname_finalize(JSContext *cx, JSObject *obj) { - { 0 } - }; + ASSERT(OBJ_GET_CLASS(cx, obj) == &gMonkeyMultinameClass); + Multiname *mName = static_cast(JS_GetPrivate(cx, obj)); + if (mName) delete mName; + } + /****************************************************************************** + Namespace + ******************************************************************************/ + + // finish constructing a Namespace + static JSBool + Namespace_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) + { + JS2Metadata *meta = static_cast(JS_GetContextPrivate(cx)); + ASSERT(argc == 1); + ASSERT(JSVAL_IS_STRING(argv[0])); + JSString *str = JSVAL_TO_STRING(argv[0]); + + Namespace *ns = new Namespace(meta->world.identifiers[String(JS_GetStringChars(str), JS_GetStringLength(str))]); + if (!JS_SetPrivate(cx, obj, ns)) + return JS_FALSE; + return JS_TRUE; + } + + // finalize a Namespace - called by Monkey gc + static void + Namespace_finalize(JSContext *cx, JSObject *obj) + { + ASSERT(OBJ_GET_CLASS(cx, obj) == &gMonkeyNamespaceClass); + Namespace *ns = static_cast(JS_GetPrivate(cx, obj)); + if (ns) delete ns; + } + @@ -216,45 +255,50 @@ namespace MetaData { // Initialize the SpiderMonkey engine void JS2Metadata::initializeMonkey() { - gMonkeyRuntime = JS_NewRuntime( 1000000L ); - if (!gMonkeyRuntime) + monkeyRuntime = JS_NewRuntime(1000000L); + if (!monkeyRuntime) throw "Monkey start failure"; - gMonkeyContext = JS_NewContext( gMonkeyRuntime, 8192 ); - if (!gMonkeyContext) + monkeyContext = JS_NewContext(monkeyRuntime, 8192); + if (!monkeyContext) throw "Monkey start failure"; - gMonkeyGlobalObject = JS_NewObject(gMonkeyContext, &gMonkeyGlobalClass, NULL, NULL); - if (!gMonkeyGlobalObject) + monkeyGlobalObject = JS_NewObject(monkeyContext, &gMonkeyGlobalClass, NULL, NULL); + if (!monkeyGlobalObject) throw "Monkey start failure"; - JS_SetErrorReporter(gMonkeyContext, MonkeyError); + JS_SetErrorReporter(monkeyContext, MonkeyError); - JS_InitStandardClasses(gMonkeyContext, gMonkeyGlobalObject); + if (!JS_InitStandardClasses(monkeyContext, monkeyGlobalObject)) + throw "Monkey start failure"; - JS_InitClass(gMonkeyContext, gMonkeyGlobalObject, NULL, + JS_InitClass(monkeyContext, monkeyGlobalObject, NULL, &gMonkeyLexicalReferenceClass, LexicalReference_constructor, 0, NULL, jsfLexicalReference, NULL, NULL); - JS_InitClass(gMonkeyContext, gMonkeyGlobalObject, NULL, + JS_InitClass(monkeyContext, monkeyGlobalObject, NULL, &gMonkeyMultinameClass, Multiname_constructor, 0, - NULL, jsfMultiname, NULL, NULL); + NULL, NULL, NULL, NULL); - JS_DefineFunctions(gMonkeyContext, gMonkeyGlobalObject, jsfGlobal); + JS_InitClass(monkeyContext, monkeyGlobalObject, NULL, + &gMonkeyNamespaceClass, Namespace_constructor, 0, + NULL, NULL, NULL, NULL); + if (!JS_DefineFunctions(monkeyContext, monkeyGlobalObject, jsfGlobal)) + throw "Monkey start failure"; } // Execute a JS string against the given environment // Errors are thrown back to C++ by the error handler - jsval JS2Metadata::execute(String *str, Environment *env, JS2Metadata *meta, size_t pos) + jsval JS2Metadata::execute(String *str, size_t pos) { jsval retval; - ExecutionState eState(gMonkeyContext, env, meta, pos); - JS_SetContextPrivate(gMonkeyContext, &eState); + errorPos = pos; + JS_SetContextPrivate(monkeyContext, this); - JS_EvaluateUCScript(gMonkeyContext, gMonkeyGlobalObject, str->c_str(), str->length(), "file", 1, &retval); + JS_EvaluateUCScript(monkeyContext, monkeyGlobalObject, str->c_str(), str->length(), "file", 1, &retval); return retval; } diff --git a/js2/src/js2metadata.cpp b/js2/src/js2metadata.cpp index 40eca4cbcbd7..7f4de056a9f4 100644 --- a/js2/src/js2metadata.cpp +++ b/js2/src/js2metadata.cpp @@ -61,6 +61,15 @@ namespace MetaData { /* * Validate the linked list of statement nodes beginning at 'p' */ + void JS2Metadata::ValidateStmtList(StmtNode *p) { + cxt.openNamespaces.clear(); + cxt.openNamespaces.push_back(publicNamespace); + while (p) { + ValidateStmt(&cxt, &env, p); + p = p->next; + } + } + void JS2Metadata::ValidateStmtList(Context *cxt, Environment *env, StmtNode *p) { while (p) { ValidateStmt(cxt, env, p); @@ -92,10 +101,10 @@ namespace MetaData { Attribute *attr = NULL; VariableStmtNode *vs = checked_cast(p); - ValidateAttributeExpression(cxt, env, vs->attributes); - if (vs->attributes) + if (vs->attributes) { + ValidateAttributeExpression(cxt, env, vs->attributes); attr = EvalAttributeExpression(env, CompilePhase, vs->attributes); - + } VariableBinding *v = vs->bindings; Frame *regionalFrame = env->getRegionalFrame(); @@ -130,10 +139,10 @@ namespace MetaData { /* * Evaluate the linked list of statement nodes beginning at 'p' */ - jsval JS2Metadata::EvalStmtList(Environment *env, Phase phase, StmtNode *p) { + jsval JS2Metadata::EvalStmtList(Phase phase, StmtNode *p) { jsval retval = JSVAL_VOID; while (p) { - retval = EvalStmt(env, phase, p); + retval = EvalStmt(&env, phase, p); p = p->next; } return retval; @@ -150,7 +159,7 @@ namespace MetaData { case StmtNode::group: { BlockStmtNode *b = checked_cast(p); - retval = EvalStmtList(env, phase, b->statements); + retval = EvalStmtList(phase, b->statements); } break; case StmtNode::label: @@ -438,9 +447,10 @@ namespace MetaData { jsval JS2Metadata::EvalExpression(Environment *env, Phase phase, ExprNode *p) { String s; - EvalExprNode(env, phase, p, s); + if (EvalExprNode(env, phase, p, s)) + s += ".readReference()"; try { - return execute(&s, env, this, p->pos); + return execute(&s, p->pos); } catch (const char *err) { reportError(Exception::internalError, err, p->pos); @@ -495,10 +505,10 @@ namespace MetaData { { if (phase == CompilePhase) reportError(Exception::compileExpressionError, "Inappropriate compile time expression", p->pos); UnaryExprNode *u = checked_cast(p); - // rather than inserting "(r = , a = readRef(), r.writeRef(a + 1), a)" with - // all the attendant performance overhead and temp. handling issues. if (!EvalExprNode(env, phase, u->op, s)) ASSERT(false); // not an lvalue + // rather than inserting "(r = , a = readRef(), r.writeRef(a + 1), a)" with + // all the attendant performance overhead and temp. handling issues. s += ".postIncrement()"; returningRef = true; } @@ -512,11 +522,14 @@ namespace MetaData { case ExprNode::identifier: { IdentifierExprNode *i = checked_cast(p); - s += "new LexicalReference(" + (i->cxt->strict) ? "true, " : "false, "; + s += "new LexicalReference("; + s += (i->cxt->strict) ? "true, " : "false, "; s += "new Multiname(\"" + i->name + "\""; for (NamespaceListIterator nli = i->cxt->openNamespaces.begin(), end = i->cxt->openNamespaces.end(); (nli != end); nli++) { - s += ", " + (*nli)->name; + s += ", new Namespace(\"" + s += (*nli)->name; + s += "\")"; } s += "))"; returningRef = true; @@ -584,32 +597,27 @@ namespace MetaData { return JSVAL_VOID; } - // Slightly varies from spec. - the multiname is actually the list of - // qualifiers to apply to the name - jsval Environment::lexicalRead(ExecutionState *eState, Multiname *multiname, Phase phase) + // Read the value of a lexical reference - it's an error if that reference + // doesn't have a binding somewhere + jsval Environment::lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase) { LookupKind lookup(true, findThis(false)); Frame *pf = firstFrame; while (pf) { jsval rval; - if (readProperty(eState, pf, multiname, &lookup, phase, &rval)) + // have to wrap the frame in a Monkey object in order + // to have readProperty handle it... + if (meta->readProperty(pf, multiname, &lookup, phase, &rval)) return rval; pf = pf->nextFrame; } - eState->meta->reportError(Exception::referenceError, "{0} is undefined", eState->pos, multiname->name); + meta->reportError(Exception::referenceError, "{0} is undefined", meta->errorPos, multiname->name); return JSVAL_VOID; } - bool Environment::readProperty(ExecutionState *eState, jsval container, Multiname *multinameVal, LookupKind *lookupKind, Phase phase, jsval *rval) - { - } - - - - /************************************************************************************ * * Context @@ -620,6 +628,21 @@ namespace MetaData { { } +/************************************************************************************ + * + * Multiname + * + ************************************************************************************/ + + // return true if the given namespace is on the namespace list + bool Multiname::onList(Namespace *nameSpace) + { + for (NamespaceListIterator n = nsList.begin(), end = nsList.end(); (n != end); n++) { + if (*n == nameSpace) + return true; + } + return false; + } /************************************************************************************ * @@ -679,7 +702,10 @@ namespace MetaData { } JS2Metadata::JS2Metadata(World &world) : - publicNamespace(new Namespace(world.identifiers["public"])) + world(world), + publicNamespace(new Namespace(world.identifiers["public"])), + glob(world), + env(new MetaData::SystemFrame(), &glob) { initializeMonkey(); } @@ -701,6 +727,8 @@ namespace MetaData { else return stringClass; } + ASSERT(JSVAL_IS_OBJECT(obj)); + return NULL; /* NAMESPACE do return namespaceClass; COMPOUNDATTRIBUTE do return attributeClass; @@ -712,6 +740,68 @@ namespace MetaData { */ } + bool JS2Metadata::readDynamicProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase) + { + return true; + } + + bool JS2Metadata::readStaticMember(StaticMember *m, Phase phase) + { + return true; + } + + // Read the value of a property in the container. Return true/false if that container has + // the property or not. If it does, return it's value + bool JS2Metadata::readProperty(jsval container, Multiname *multiname, LookupKind *lookupKind, Phase phase, jsval *rval) + { + return true; + } + + // Read the value of a property in the frame. Return true/false if that frame has + // the property or not. If it does, return it's value + bool JS2Metadata::readProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, jsval *rval) + { + StaticMember *m = findFlatMember(container, multiname, ReadAccess, phase); + if (!m && (container->kind == Frame::GlobalObject)) + return readDynamicProperty(container, multiname, lookupKind, phase); + else + return readStaticMember(m, phase); + } + + // Find a binding in the frame that matches the multiname and access + // It's an error if more than one such binding exists. + StaticMember *JS2Metadata::findFlatMember(Frame *container, Multiname *multiname, Access access, Phase phase) + { + StaticMember *found = NULL; + StaticBindingIterator b, end; + if ((access == ReadAccess) || (access == ReadWriteAccess)) { + b = container->staticReadBindings.lower_bound(multiname->name); + end = container->staticReadBindings.upper_bound(multiname->name); + } + else { + b = container->staticWriteBindings.lower_bound(multiname->name); + end = container->staticWriteBindings.upper_bound(multiname->name); + } + while (true) { + if (b == end) { + if (access == ReadWriteAccess) { + access = WriteAccess; + b = container->staticWriteBindings.lower_bound(multiname->name); + end = container->staticWriteBindings.upper_bound(multiname->name); + } + else + break; + } + if (multiname->matches(b->second->qname)) { + if (found) + reportError(Exception::propertyAccessError, "Ambiguous reference to {0}", errorPos, multiname->name); + else + found = b->second->content; + } + b++; + } + return found; + } /* * Throw an exception of the specified kind, indicating the position 'pos' and diff --git a/js2/src/js2metadata.h b/js2/src/js2metadata.h index 05eb3bb3c95c..d9725d557ceb 100644 --- a/js2/src/js2metadata.h +++ b/js2/src/js2metadata.h @@ -46,7 +46,6 @@ namespace MetaData { // forward definitions: -class ExecutionState; class JS2Metadata; class JS2Class; class StaticBinding; @@ -59,7 +58,8 @@ typedef Invokable Callor; typedef Invokable Constructor; -enum Phase { CompilePhase, RunPhase }; +enum Phase { CompilePhase, RunPhase }; +enum Access { ReadAccess, WriteAccess, ReadWriteAccess }; class JS2Object { // Every object is either undefined, null, a Boolean, @@ -105,11 +105,19 @@ public: }; // MULTINAME is the semantic domain of sets of qualified names. Multinames are used internally in property lookup. -typedef std::vector QualifierList; -typedef QualifierList::iterator QualifierListIterator; +// We keep Multinames as a basename and a list of namespace qualifiers +typedef std::vector NamespaceList; +typedef NamespaceList::iterator NamespaceListIterator; class Multiname { public: - QualifierList qList; + + Multiname(StringAtom &name) : name(name) { } + void addNamespace(Namespace *ns) { nsList.push_back(ns); } + + bool matches(QualifiedName &q) { return (name == q.id) && onList(q.nameSpace); } + bool onList(Namespace *nameSpace); + + NamespaceList nsList; StringAtom &name; }; @@ -237,7 +245,9 @@ public: class Frame { public: enum Plurality { Singular, Plural }; - enum FrameKind { GlobalObject, Package, Function, Class, Block }; + enum FrameKind { System, GlobalObject, Package, Function, Class, Block }; + + Frame(FrameKind kind) : kind(kind), nextFrame(NULL) { } StaticBindingMap staticReadBindings; // Map of qualified names to readable static members defined in this frame StaticBindingMap staticWriteBindings; // Map of qualified names to writable static members defined in this frame @@ -252,6 +262,7 @@ public: class JS2Class : public Frame { public: + JS2Class() : Frame(Class) { } InstanceBindingMap instanceReadBindings; // Map of qualified names to readable instance members defined in this class InstanceBindingMap instanceWriteBindings; // Map of qualified names to writable instance members defined in this class @@ -276,7 +287,7 @@ public: class GlobalObject : public Frame { public: - GlobalObject(World &world) : internalNamespace(new Namespace(world.identifiers["internal"])) { } + GlobalObject(World &world) : Frame(Frame::GlobalObject), internalNamespace(new Namespace(world.identifiers["internal"])) { } Namespace *internalNamespace; // This global object's internal namespace DynamicPropertyMap dynamicProperties; // A set of this global object's dynamic properties @@ -369,11 +380,14 @@ public: // The top-level frame containing predefined constants, functions, and classes. class SystemFrame : public Frame { public: + SystemFrame() : Frame(System) { } }; // Frames holding bindings for invoked functions class FunctionFrame : public Frame { public: + FunctionFrame() : Frame(Function) { } + Plurality plurality; jsval thisObject; // The value of this; none if this function doesn't define this; // inaccessible if this function defines this but the value is not @@ -386,6 +400,8 @@ public: class BlockFrame : public Frame { public: + BlockFrame() : Frame(Block) { } + Plurality plurality; }; @@ -410,9 +426,7 @@ public: Frame *getTopFrame() { return firstFrame; } jsval findThis(bool allowPrototypeThis); - jsval lexicalRead(ExecutionState *eState, Multiname *multiname, Phase phase); - - bool readProperty(ExecutionState *eState, jsval container, Multiname *multinameVal, LookupKind *lookupKind, Phase phase, jsval *rval); + jsval lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase); private: @@ -468,32 +482,47 @@ public: void setCurrentParser(Parser *parser) { mParser = parser; } - void ValidateTypeExpression(ExprNode *e); + void ValidateStmtList(StmtNode *p); + jsval EvalStmtList(Phase phase, StmtNode *p); + + void ValidateStmtList(Context *cxt, Environment *env, StmtNode *p); + void ValidateTypeExpression(ExprNode *e); void ValidateStmt(Context *cxt, Environment *env, StmtNode *p); void defineHoistedVar(Environment *env, const StringAtom &id, StmtNode *p); void ValidateExpression(Context *cxt, Environment *env, ExprNode *p); void ValidateAttributeExpression(Context *cxt, Environment *env, ExprNode *p); + jsval EvalStmtList(Environment *env, Phase phase, StmtNode *p); jsval EvalExpression(Environment *env, Phase phase, ExprNode *p); bool EvalExprNode(Environment *env, Phase phase, ExprNode *p, String &s); Attribute *EvalAttributeExpression(Environment *env, Phase phase, ExprNode *p); - jsval EvalStmtList(Environment *env, Phase phase, StmtNode *p); jsval EvalStmt(Environment *env, Phase phase, StmtNode *p); JS2Class *objectType(jsval obj); + bool readProperty(jsval container, Multiname *multiname, LookupKind *lookupKind, Phase phase, jsval *rval); + bool readProperty(Frame *pf, Multiname *multiname, LookupKind *lookupKind, Phase phase, jsval *rval); + StaticMember *findFlatMember(Frame *container, Multiname *multiname, Access access, Phase phase); + + bool readDynamicProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase); + bool readStaticMember(StaticMember *m, Phase phase); + + + void reportError(Exception::Kind kind, const char *message, size_t pos, const char *arg = NULL); void reportError(Exception::Kind kind, const char *message, size_t pos, const String& name); void initializeMonkey(); - jsval execute(String *str, Environment *env, JS2Metadata *meta, size_t pos); + jsval execute(String *str, size_t pos); + // Used for interning strings + World &world; // The one and only 'public' namespace - Namespace *publicNamespace; // XXX is this the right place for this ??? + Namespace *publicNamespace; // The base classes: JS2Class *undefinedClass; @@ -505,21 +534,18 @@ public: Parser *mParser; // used for error reporting + size_t errorPos; -}; -// Captures some metadata-related info. that gets passed back into -// js2metadata routines from executing JS code -// - it's hidden in the Monkey context private -class ExecutionState { -public: - ExecutionState(JSContext *cx, Environment *env, JS2Metadata *meta, size_t pos) : cx(cx), env(env), meta(meta), pos(pos) { } - virtual ~ExecutionState() { } + GlobalObject glob; + Environment env; + Context cxt; + + // SpiderMonkey execution data: + JSRuntime *monkeyRuntime; + JSContext *monkeyContext; + JSObject *monkeyGlobalObject; - JSContext *cx; // the SpiderMonkey context - Environment *env; // the frame array, used for lookups - JS2Metadata *meta; // base class for error reporting - size_t pos; // position from node being executed (vaguely) };