From 9c7a073f857ddbb1a8b35556ecc6e8f3f9a5ac50 Mon Sep 17 00:00:00 2001 From: "rogerl%netscape.com" Date: Thu, 27 Mar 2003 23:58:21 +0000 Subject: [PATCH] !!! BROKEN !!! Added definitions under new layout. --- js2/src/epimetheus.cpp | 30 -------- js2/src/js2array.cpp | 17 +++-- js2/src/js2eval.cpp | 55 -------------- js2/src/js2metadata.cpp | 134 +++++++++++------------------------ js2/src/js2metadata.h | 21 +++--- js2/src/js2op_arithmetic.cpp | 20 +++--- js2/src/js2op_invocation.cpp | 86 ++++++++++------------ js2/src/parser.h | 1 - 8 files changed, 110 insertions(+), 254 deletions(-) diff --git a/js2/src/epimetheus.cpp b/js2/src/epimetheus.cpp index c2a62254e776..e00722d3ef2f 100644 --- a/js2/src/epimetheus.cpp +++ b/js2/src/epimetheus.cpp @@ -298,36 +298,6 @@ js2val dump(JS2Metadata *meta, const js2val /* thisValue */, js2val argv[], uint } } } - else { - if (fObj->kind == PrototypeInstanceKind) { - PrototypeInstance *pInst = checked_cast(fObj); - stdOut << "Prototype Instance\n"; - if (pInst->parent) - printFormat(stdOut, "Parent @ 0x%08X\n", pInst->parent); - else - stdOut << " Null Parent\n"; - if (pInst->type) - stdOut << " Type: " << *pInst->type->getName() << "\n"; - else - stdOut << " Null Type\n"; - - stdOut << " Dynamic Properties:\n"; - for (DynamicPropertyIterator dpi = pInst->dynamicProperties.begin(), dpend = pInst->dynamicProperties.end(); (dpi != dpend); dpi++) { - DynamicPropertyBinding *dpb = *dpi; - stdOut << "\t" << dpb->name << " = " << *meta->toString(dpb->v.value) << "\n"; - } - if (pInst->type == meta->functionClass) { - FunctionWrapper *fWrap = (checked_cast(fObj))->fWrap; - stdOut << "Function:" << "\n"; - if (fWrap) { - stdOut << "Environment depth " << fWrap->env->getSize() << "\n"; - dumpBytecode(fWrap->bCon); - } - else - stdOut << "<>\n"; - } - } - } } } } diff --git a/js2/src/js2array.cpp b/js2/src/js2array.cpp index 76ea4b5e1f35..b5ee66526da8 100644 --- a/js2/src/js2array.cpp +++ b/js2/src/js2array.cpp @@ -61,7 +61,8 @@ uint32 getLength(JS2Metadata *meta, JS2Object *obj) LookupKind lookup(false, JS2VAL_NULL); uint32 length = 0; js2val result; - if (meta->readDynamicProperty(obj, meta->engine->length_StringAtom, &lookup, RunPhase, &result)) + meta->mn1->name = meta->engine->length_StringAtom; + if (meta->readDynamicProperty(obj, meta->mn1, &lookup, RunPhase, &result)) length = toUInt32(meta->toInteger(result)); return length; } @@ -88,6 +89,7 @@ js2val setLength(JS2Metadata *meta, JS2Object *obj, uint32 newLength) if (obj->kind == SimpleInstanceKind) { // Can't call 'writeDynamicProperty' as that'll just cycle back here for // ArrayInstances. +/* DynamicPropertyMap *dMap = &checked_cast(obj)->dynamicProperties; DynamicPropertyBinding **dpbP = (*dMap)[*meta->engine->length_StringAtom]; if (dpbP) { @@ -96,9 +98,11 @@ js2val setLength(JS2Metadata *meta, JS2Object *obj, uint32 newLength) } DynamicPropertyBinding *dpb = new DynamicPropertyBinding(*meta->engine->length_StringAtom, DynamicPropertyValue(result, DynamicPropertyValue::PERMANENT)); checked_cast(obj)->dynamicProperties.insert(dpb->name, dpb); +*/ } else { - meta->writeDynamicProperty(obj, meta->engine->length_StringAtom, true, result, RunPhase); + meta->mn1->name = meta->engine->length_StringAtom; + meta->writeDynamicProperty(obj, meta->mn1, true, result, RunPhase); } return result; } @@ -118,16 +122,15 @@ js2val Array_Constructor(JS2Metadata *meta, const js2val /*thisValue*/, js2val * meta->reportError(Exception::rangeError, "Array length too large", meta->engine->errorPos()); } else { - String *s = meta->engine->numberToString((int32)0); - RootKeeper rk(&s); - meta->writeDynamicProperty(arrInst, s, true, argv[0], RunPhase); + meta->mn1->name = meta->engine->numberToString((int32)0); + meta->writeDynamicProperty(arrInst, meta->mn1, true, argv[0], RunPhase); } } else { uint32 i; for (i = 0; i < argc; i++) { - DynamicPropertyBinding *dpb = new DynamicPropertyBinding(*meta->engine->numberToString(i), DynamicPropertyValue(argv[i], DynamicPropertyValue::ENUMERATE)); - arrInst->dynamicProperties.insert(dpb->name, dpb); +// DynamicPropertyBinding *dpb = new DynamicPropertyBinding(*meta->engine->numberToString(i), DynamicPropertyValue(argv[i], DynamicPropertyValue::ENUMERATE)); +// arrInst->dynamicProperties.insert(dpb->name, dpb); } setLength(meta, arrInst, i); } diff --git a/js2/src/js2eval.cpp b/js2/src/js2eval.cpp index a878ce5cad98..34aedd15da35 100644 --- a/js2/src/js2eval.cpp +++ b/js2/src/js2eval.cpp @@ -210,56 +210,6 @@ namespace MetaData { JS2Object *fnObj = JS2VAL_TO_OBJECT(fnVal); result = invokeFunction(fnObj, thisValue, NULL, 0); return true; -/* - FunctionWrapper *fWrap = NULL; - if ((fnObj->kind == SimpleInstanceKind) - && (objectType(fnVal) == functionClass)) { - fWrap = (checked_cast(fnObj))->fWrap; - } - else - if ((fnObj->kind == PrototypeInstanceKind) - && ((checked_cast(fnObj))->type == functionClass)) { - fWrap = (checked_cast(fnObj))->fWrap; - } - else - if (fnObj->kind == MethodClosureKind) { - // XXX here we ignore the bound this, can that be right? - MethodClosure *mc = checked_cast(fnObj); - fWrap = mc->method->fInst->fWrap; - } - if (fWrap) { - if (fWrap->code) { - result = (fWrap->code)(this, thisValue, NULL, 0); - return true; - } - else { - uint8 *savePC = NULL; - BytecodeContainer *bCon = fWrap->bCon; - - CompilationData *oldData = startCompilationUnit(bCon, bCon->mSource, bCon->mSourceLocation); - ParameterFrame *runtimeFrame = new ParameterFrame(fWrap->compileFrame); - runtimeFrame->instantiate(env); - runtimeFrame->thisObject = thisValue; - Frame *oldTopFrame = env->getTopFrame(); - env->addFrame(runtimeFrame); - try { - savePC = engine->pc; - engine->pc = NULL; - result = engine->interpret(RunPhase, bCon); - } - catch (Exception &x) { - engine->pc = savePC; - restoreCompilationUnit(oldData); - env->setTopFrame(oldTopFrame); - throw x; - } - engine->pc = savePC; - restoreCompilationUnit(oldData); - env->setTopFrame(oldTopFrame); - return true; - } - } -*/ } } return false; @@ -304,11 +254,6 @@ namespace MetaData { fWrap = (checked_cast(fnObj))->fWrap; } else - if ((fnObj->kind == PrototypeInstanceKind) - && ((checked_cast(fnObj))->type == functionClass)) { - fWrap = (checked_cast(fnObj))->fWrap; - } - else if (fnObj->kind == MethodClosureKind) { // XXX here we ignore the bound this, can that be right? MethodClosure *mc = checked_cast(fnObj); diff --git a/js2/src/js2metadata.cpp b/js2/src/js2metadata.cpp index 5e967bf44a46..79e91fe5d7f1 100644 --- a/js2/src/js2metadata.cpp +++ b/js2/src/js2metadata.cpp @@ -2715,7 +2715,7 @@ doUnary: * JS2Metadata * ************************************************************************************/ -#if 0 + // - Define namespaces::id (for all namespaces or at least 'public') in the top frame // unless it's there already. // - If the binding exists (not forbidden) in lower frames in the regional environment, it's an error. @@ -2725,18 +2725,15 @@ doUnary: Attribute::OverrideModifier overrideMod, bool xplicit, Access access, LocalMember *m, size_t pos) { - NamespaceList publicNamespaceList; - - FrameListIterator fi = env->getBegin(); - NonWithFrame *localFrame = checked_cast(*fi); - if ((overrideMod != Attribute::NoOverride) || (xplicit && localFrame->kind != PackageKind)) + NonWithFrame *innerFrame = checked_cast(*(env->getBegin())); + if ((overrideMod != Attribute::NoOverride) || (xplicit && innerFrame->kind != PackageKind)) reportError(Exception::definitionError, "Illegal definition", pos); - if ((namespaces == NULL) || namespaces->empty()) { - publicNamespaceList.push_back(publicNamespace); - namespaces = &publicNamespaceList; - } - Multiname *mn = new Multiname(id); - mn->addNamespace(namespaces); + + Multiname *multiname = new Multiname(id); + if (namespaces->empty()) + multiname->addNamespace(publicNamespace); + else + multiname->addNamespace(namespaces); // Search the local frame for an overlapping definition LocalBindingEntry **lbeP = localFrame->localBindings[*id]; @@ -2910,41 +2907,41 @@ doUnary: } if (mOverridden->final || !goodKind) reportError(Exception::definitionError, "Illegal override", pos); - - InstanceBindingEntry **ibeP = c->instanceBindings[*id]; - if (ibeP) { - for (InstanceBindingEntry::NS_Iterator i = (*ibeP)->begin(), end = (*ibeP)->end(); (i != end); i++) { - InstanceBindingEntry::NamespaceBinding &ns = *i; - if ((ns.second->accesses & access) && (ns.first == *nli)) - reportError(Exception::definitionError, "Illegal override", pos); - } - } - } - + InstanceBindingEntry **ibeP = c->instanceBindings[*id]; + if (ibeP) { + for (InstanceBindingEntry::NS_Iterator i = (*ibeP)->begin(), end = (*ibeP)->end(); (i != end); i++) { + InstanceBindingEntry::NamespaceBinding &ns = *i; + if (access & m2->instanceMemberAccess()) && (definedMultiname->listContaines(ns.first))) + reportError(Exception::definitionError, "Illegal override", pos); + } + } + switch (overrideMod) { + case Attribute::NoOverride: + if (mBase || searchForOverrides(c, openMultiname, access)) + reportError(Exception::definitionError, "Illegal override", pos); + break; + case Attribute::DoOverride: + if (mBase) + reportError(Exception::definitionError, "Illegal override", pos); + break; + case Attribute::DontOverride: + if (mBase == NULL) + reportError(Exception::definitionError, "Illegal override", pos); + break; + } + m->multiname = new Multiname(definedMultiname); + InstanceBinding *ib = new LocalBinding(access, m); + if (ibeP) { + for (NamespaceListIterator nli = definedMultiname.nsList->begin(), nlend = definedMultiname.nsList->end(); (nli != nlend); nli++) { + *ibeP->bindingList.push_back(InstanceBindingEntry::NamespaceBinding(*nli, ib); + } + } + return mOverridden; } -if mOverridden.final or not goodKind then throw definitionError end if -end if; -if some m2 OE c.instanceMembers satisfies m2.multiname « definedMultiname ! {} and -accessesOverlap(instanceMemberAccesses(m2), accesses) then -throw definitionError -end if; -case overrideMod of -{ none } do -if mBase ! none or searchForOverrides(c, openMultiname, accesses) ! none then -throw definitionError -end if; -{ false } do if mBase ! none then throw definitionError end if; -{ true } do if mBase = none then throw definitionError end if; -{ undefined } do nothing -end case; -m.multiname ¨ definedMultiname; -c.instanceMembers ¨ c.instanceMembers » {m}; -return mOverridden - - + defineLocalMember // Find the possible override conflicts that arise from the given id and namespaces // Fall back on the currently open namespace list if no others are specified. @@ -3007,58 +3004,7 @@ return mOverridden return os; } - // Define an instance member in the class. Verify that, if any overriding is happening, it's legal. The result pair indicates - // the members being overridden. - OverrideStatusPair *JS2Metadata::defineInstanceMember(JS2Class *c, Context *cxt, const String *id, NamespaceList *namespaces, Attribute::OverrideModifier overrideMod, bool xplicit, Access access, InstanceMember *m, size_t pos) - { - OverrideStatus *readStatus; - OverrideStatus *writeStatus; - if (xplicit) - reportError(Exception::definitionError, "Illegal use of explicit", pos); - if (access & ReadAccess) - readStatus = resolveOverrides(c, cxt, id, namespaces, ReadAccess, (m->kind == InstanceMember::InstanceMethodKind), pos); - else - readStatus = new OverrideStatus(NULL, id); - - if (access & WriteAccess) - writeStatus = resolveOverrides(c, cxt, id, namespaces, WriteAccess, (m->kind == InstanceMember::InstanceMethodKind), pos); - else - writeStatus = new OverrideStatus(NULL, id); - - if ((readStatus->overriddenMember && (readStatus->overriddenMember != POTENTIAL_CONFLICT)) - || (writeStatus->overriddenMember && (writeStatus->overriddenMember != POTENTIAL_CONFLICT))) { - if ((overrideMod != Attribute::DoOverride) && (overrideMod != Attribute::OverrideUndefined)) - reportError(Exception::definitionError, "Illegal override", pos); - } - else { - if ((readStatus->overriddenMember == POTENTIAL_CONFLICT) || (writeStatus->overriddenMember == POTENTIAL_CONFLICT)) { - if ((overrideMod != Attribute::DontOverride) && (overrideMod != Attribute::OverrideUndefined)) - reportError(Exception::definitionError, "Illegal override", pos); - } - } - - NamespaceListIterator nli, nlend; - InstanceBindingEntry **ibeP = c->instanceBindings[*id]; - InstanceBindingEntry *ibe; - if (ibeP == NULL) { - ibe = new InstanceBindingEntry(*id); - c->instanceBindings.insert(*id, ibe); - } - else - ibe = *ibeP; - for (nli = readStatus->multiname.nsList->begin(), nlend = readStatus->multiname.nsList->end(); (nli != nlend); nli++) { - InstanceBinding *ib = new InstanceBinding(ReadAccess, m); - ibe->bindingList.push_back(InstanceBindingEntry::NamespaceBinding(*nli, ib)); - } - - for (nli = writeStatus->multiname.nsList->begin(), nlend = writeStatus->multiname.nsList->end(); (nli != nlend); nli++) { - InstanceBinding *ib = new InstanceBinding(ReadAccess, m); - ibe->bindingList.push_back(InstanceBindingEntry::NamespaceBinding(*nli, ib)); - } - - return new OverrideStatusPair(readStatus, writeStatus);; - } #endif // Define a hoisted var in the current frame (either Package or a Function) // defineHoistedVar(env, id, initialValue) defines a hoisted variable with the name id in the environment env. diff --git a/js2/src/js2metadata.h b/js2/src/js2metadata.h index d8f6d74246f7..d28b8efdb3e0 100644 --- a/js2/src/js2metadata.h +++ b/js2/src/js2metadata.h @@ -51,6 +51,7 @@ class CompoundAttribute; class BytecodeContainer; class Pond; class SimpleInstance; +class LookupKind; typedef void (Invokable)(); @@ -242,27 +243,27 @@ public: // A QualifiedName is the combination of an identifier and a namespace class QualifiedName { public: - QualifiedName() : nameSpace(NULL), id(NULL) { } - QualifiedName(Namespace *nameSpace, const String *id) : nameSpace(nameSpace), id(id) { } + QualifiedName() : nameSpace(NULL), name(NULL) { } + QualifiedName(Namespace *nameSpace, const String *name) : nameSpace(nameSpace), name(name) { } - bool operator ==(const QualifiedName &b) { return (nameSpace == b.nameSpace) && (*id == *b.id); } + bool operator ==(const QualifiedName &b) { return (nameSpace == b.nameSpace) && (*name == *b.name); } Namespace *nameSpace; // The namespace qualifier - const String *id; // The name + const String *name; // The name }; // A MULTINAME is the semantic domain of sets of qualified names. Multinames are used internally in property lookup. // We keep Multinames as a basename and a list of namespace qualifiers (XXX is that right - would the basename // ever be different for the same multiname?) -// XXX can nsList ever be null, or could allow null nsList to indicate public? typedef std::vector NamespaceList; typedef NamespaceList::iterator NamespaceListIterator; + class Multiname : public JS2Object { public: Multiname(const String *name) : JS2Object(MultinameKind), name(name), nsList(new NamespaceList) { } Multiname(const String *name, Namespace *ns) : JS2Object(MultinameKind), name(name), nsList(new NamespaceList) { addNamespace(ns); } - Multiname(QualifiedName& q) : JS2Object(MultinameKind), name(q.name), nsList(q.nameSpace) { } + Multiname(QualifiedName& q) : JS2Object(MultinameKind), name(q.name), nsList(new NamespaceList) { nsList->push_back(q.nameSpace); } Multiname(const Multiname& m) : JS2Object(MultinameKind), name(m.name), nsList(m.nsList) { } @@ -270,7 +271,7 @@ public: void addNamespace(NamespaceList *ns); void addNamespace(Context &cxt); - bool matches(QualifiedName &q) { return (*name == *q.id) && listContains(q.nameSpace); } + bool matches(QualifiedName &q) { return (*name == *q.name) && listContains(q.nameSpace); } bool listContains(Namespace *nameSpace); QualifiedName selectPrimaryName(JS2Metadata *meta); @@ -1157,7 +1158,7 @@ public: bool readProperty(js2val *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval); bool readProperty(Frame *pf, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval); - bool readDynamicProperty(JS2Object *container, const String *name, LookupKind *lookupKind, Phase phase, js2val *rval); + bool readDynamicProperty(JS2Object *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval); bool readLocalMember(LocalMember *m, Phase phase, js2val *rval); bool readInstanceMember(js2val containerVal, JS2Class *c, QualifiedName *qname, Phase phase, js2val *rval); JS2Object *lookupDynamicProperty(JS2Object *obj, const String *name); @@ -1165,13 +1166,13 @@ public: bool writeProperty(js2val container, Multiname *multiname, LookupKind *lookupKind, bool createIfMissing, js2val newValue, Phase phase); bool writeProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, bool createIfMissing, js2val newValue, Phase phase, bool initFlag); - bool writeDynamicProperty(JS2Object *container, const String *name, bool createIfMissing, js2val newValue, Phase phase); + bool writeDynamicProperty(JS2Object *container, Multiname *multiname, bool createIfMissing, js2val newValue, Phase phase); bool writeLocalMember(LocalMember *m, js2val newValue, Phase phase, bool initFlag); bool writeInstanceMember(js2val containerVal, JS2Class *c, QualifiedName *qname, js2val newValue, Phase phase); bool deleteProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, bool *result); bool deleteProperty(js2val container, Multiname *multiname, LookupKind *lookupKind, Phase phase, bool *result); - bool deleteDynamicProperty(JS2Object *container, const String *name, LookupKind *lookupKind, bool *result); + bool deleteDynamicProperty(JS2Object *container, Multiname *multiname, LookupKind *lookupKind, bool *result); bool deleteLocalMember(LocalMember *m, bool *result); bool deleteInstanceMember(JS2Class *c, QualifiedName *qname, bool *result); diff --git a/js2/src/js2op_arithmetic.cpp b/js2/src/js2op_arithmetic.cpp index 425d75a01fca..5d78e8992556 100644 --- a/js2/src/js2op_arithmetic.cpp +++ b/js2/src/js2op_arithmetic.cpp @@ -892,23 +892,23 @@ { Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)]; pc += sizeof(short); - a = meta->env->lexicalRead(meta, mn, phase); + meta->env->lexicalRead(meta, mn, phase, &a); if (JS2VAL_IS_LONG(a)) { int64 i = *JS2VAL_TO_LONG(a); JSLL_ADD(i, i, 1); - meta->env->lexicalWrite(meta, mn, allocLong(i), true, phase); + meta->env->lexicalWrite(meta, mn, allocLong(i), true); push(a); } else { if (JS2VAL_IS_ULONG(a)) { uint64 i = *JS2VAL_TO_ULONG(a); JSLL_ADD(i, i, 1); - meta->env->lexicalWrite(meta, mn, allocULong(i), true, phase); + meta->env->lexicalWrite(meta, mn, allocULong(i), true); push(a); } else { float64 num = meta->toFloat64(a); - meta->env->lexicalWrite(meta, mn, allocNumber(num + 1.0), true, phase); + meta->env->lexicalWrite(meta, mn, allocNumber(num + 1.0), true); pushNumber(num); } } @@ -918,9 +918,9 @@ { Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)]; pc += sizeof(short); - a = meta->env->lexicalRead(meta, mn, phase); + meta->env->lexicalRead(meta, mn, phase, &a); float64 num = meta->toFloat64(a); - meta->env->lexicalWrite(meta, mn, allocNumber(num - 1.0), true, phase); + meta->env->lexicalWrite(meta, mn, allocNumber(num - 1.0), true); pushNumber(num); } break; @@ -928,20 +928,20 @@ { Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)]; pc += sizeof(short); - a = meta->env->lexicalRead(meta, mn, phase); + meta->env->lexicalRead(meta, mn, phase, &a); float64 num = meta->toFloat64(a); a = pushNumber(num + 1.0); - meta->env->lexicalWrite(meta, mn, a, true, phase); + meta->env->lexicalWrite(meta, mn, a, true); } break; case eLexicalPreDec: { Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)]; pc += sizeof(short); - a = meta->env->lexicalRead(meta, mn, phase); + meta->env->lexicalRead(meta, mn, phase, &a); float64 num = meta->toFloat64(a); a = pushNumber(num - 1.0); - meta->env->lexicalWrite(meta, mn, a, true, phase); + meta->env->lexicalWrite(meta, mn, a, true); } break; diff --git a/js2/src/js2op_invocation.cpp b/js2/src/js2op_invocation.cpp index 6d1b9110fa4c..b839c7752927 100644 --- a/js2/src/js2op_invocation.cpp +++ b/js2/src/js2op_invocation.cpp @@ -54,56 +54,48 @@ && (meta->objectType(a) == meta->functionClass)) { fWrap = (checked_cast(obj))->fWrap; } - else - if ((obj->kind == PrototypeInstanceKind) - && ((checked_cast(obj))->type == meta->functionClass)) { - fWrap = (checked_cast(obj))->fWrap; + if (fWrap) { + // XXX - I made this stuff up - extract the 'prototype' property from + // the function being invoked (defaulting to Object.prototype). Then + // construct a new prototypeInstance, setting the acquired prototype + // parent. Finally invoke the function, but insert the constructed + // object at the bottom of the stack to be the 'return' value. + // XXX this won't last - if a non-primitive is returned from the function, + // it's supposed to supplant the constructed object. XXX and I think the + // stack is out of balance anyway... + js2val protoVal; + JS2Object *protoObj = meta->objectClass->prototype; + Multiname mn(prototype_StringAtom); // gc safe because the content is rooted elsewhere + LookupKind lookup(true, JS2VAL_NULL); // make it a lexical lookup since we want it to + // fail if 'prototype' hasn't been defined + // XXX (prototype should always exist for functions) + if (meta->readProperty(&a, &mn, &lookup, RunPhase, &protoVal)) { + if (!JS2VAL_IS_OBJECT(protoVal)) + meta->reportError(Exception::badValueError, "Non-object prototype value", errorPos()); + protoObj = JS2VAL_TO_OBJECT(protoVal); } - if (fWrap) { - // XXX - I made this stuff up - extract the 'prototype' property from - // the function being invoked (defaulting to Object.prototype). Then - // construct a new prototypeInstance, setting the acquired prototype - // parent. Finally invoke the function, but insert the constructed - // object at the bottom of the stack to be the 'return' value. - // XXX this won't last - if a non-primitive is returned from the function, - // it's supposed to supplant the constructed object. XXX and I think the - // stack is out of balance anyway... - js2val protoVal; - JS2Object *protoObj = meta->objectClass->prototype; - Multiname mn(prototype_StringAtom); // gc safe because the content is rooted elsewhere - LookupKind lookup(true, JS2VAL_NULL); // make it a lexical lookup since we want it to - // fail if 'prototype' hasn't been defined - // XXX (prototype should always exist for functions) - if (meta->readProperty(&a, &mn, &lookup, RunPhase, &protoVal)) { - if (!JS2VAL_IS_OBJECT(protoVal)) - meta->reportError(Exception::badValueError, "Non-object prototype value", errorPos()); - protoObj = JS2VAL_TO_OBJECT(protoVal); - } - if (fWrap->code) { // native code, pass pointer to argument base - a = fWrap->code(meta, a, base(argCount), argCount); - pop(argCount + 1); - push(a); - } - else { - pFrame = new ParameterFrame(fWrap->compileFrame); - pFrame->instantiate(meta->env); - if (protoObj->kind == PrototypeInstanceKind) - baseVal = OBJECT_TO_JS2VAL(new PrototypeInstance(meta, protoObj, (checked_cast(protoObj))->type)); - else - baseVal = OBJECT_TO_JS2VAL(new PrototypeInstance(meta, protoObj, meta->objectClass)); - pFrame->thisObject = baseVal; - pFrame->assignArguments(meta, obj, base(argCount), argCount); - jsr(phase, fWrap->bCon, base(argCount + 1) - execStack, baseVal, fWrap->env); // seems out of order, but we need to catch the current top frame - meta->env->addFrame(pFrame); - pFrame = NULL; - } + if (fWrap->code) { // native code, pass pointer to argument base + a = fWrap->code(meta, a, base(argCount), argCount); + pop(argCount + 1); + push(a); } - else - meta->reportError(Exception::typeError, "object is not a constructor", errorPos()); -// } -// else -// meta->reportError(Exception::typeError, "object is not a constructor", errorPos()); + else { + pFrame = new ParameterFrame(fWrap->compileFrame); + pFrame->instantiate(meta->env); + if (protoObj->kind == PrototypeInstanceKind) + baseVal = OBJECT_TO_JS2VAL(new PrototypeInstance(meta, protoObj, (checked_cast(protoObj))->type)); + else + baseVal = OBJECT_TO_JS2VAL(new PrototypeInstance(meta, protoObj, meta->objectClass)); + pFrame->thisObject = baseVal; + pFrame->assignArguments(meta, obj, base(argCount), argCount); + jsr(phase, fWrap->bCon, base(argCount + 1) - execStack, baseVal, fWrap->env); // seems out of order, but we need to catch the current top frame + meta->env->addFrame(pFrame); + pFrame = NULL; + } + } + else + meta->reportError(Exception::typeError, "object is not a constructor", errorPos()); } } break; diff --git a/js2/src/parser.h b/js2/src/parser.h index b8c2a0d3f390..e9d142f4d12a 100644 --- a/js2/src/parser.h +++ b/js2/src/parser.h @@ -152,7 +152,6 @@ namespace JavaScript { #ifdef EPIMETHEUS MetaData::Member *member; // the associated definition... MetaData::Multiname *mn; // ...and name constructed by the semantics phase - MetaData::OverrideStatusPair *osp; // Read & Write status for PreEval stage #endif VariableBinding(size_t pos, const StringAtom *name, ExprNode *type, ExprNode *initializer, bool constant):