From 7b8898dcf1123198289604260b633f86310c0422 Mon Sep 17 00:00:00 2001 From: "rogerl%netscape.com" Date: Fri, 3 Nov 2000 02:42:01 +0000 Subject: [PATCH] Fixed adding setter to virtual inherited field. --- js/js2/icodegenerator.cpp | 20 ++++++++++++++++---- js/js2/interpreter.cpp | 3 +++ js/js2/js2.cpp | 14 ++++++++++++-- js/js2/jsclasses.h | 33 +++++++++++++++++++++------------ js2/src/icodegenerator.cpp | 20 ++++++++++++++++---- js2/src/interpreter.cpp | 3 +++ js2/src/jsclasses.h | 33 +++++++++++++++++++++------------ js2/tests/cpp/js2_shell.cpp | 14 ++++++++++++-- 8 files changed, 104 insertions(+), 36 deletions(-) diff --git a/js/js2/icodegenerator.cpp b/js/js2/icodegenerator.cpp index ed21c83e18e..d0c86871f5e 100644 --- a/js/js2/icodegenerator.cpp +++ b/js/js2/icodegenerator.cpp @@ -1613,6 +1613,16 @@ static bool hasAttribute(const IdentifierList* identifiers, Token::Kind tokenKin return false; } +static bool hasAttribute(const IdentifierList* identifiers, StringAtom &name) +{ + while (identifiers) { + if (identifiers->name == name) + return true; + identifiers = identifiers->next; + } + return false; +} + JSType *ICodeGenerator::extractType(ExprNode *t) { JSType* type = &Any_Type; @@ -1799,7 +1809,10 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet) if (isStatic) thisClass->defineStatic(idExpr->name, type); else { - thisClass->defineSlot(idExpr->name, type); + if (hasAttribute(vs->attributes, mContext->getWorld().identifiers["virtual"])) + thisClass->defineSlot(idExpr->name, type, JSSlot::kIsVirtual); + else + thisClass->defineSlot(idExpr->name, type); if (v->initializer) needsInstanceInitializer = true; } @@ -1823,12 +1836,11 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet) thisClass->defineStatic(name, &Function_Type); else { switch (f->function.prefix) { - // XXXX these dummy place holders for the getters/setters are leaking case FunctionName::Get: - thisClass->setGetter(name, new JSFunction(), extractType(f->function.resultType)); + thisClass->setGetter(name, NULL, extractType(f->function.resultType)); break; case FunctionName::Set: - thisClass->setSetter(name, new JSFunction(), extractType(f->function.resultType)); + thisClass->setSetter(name, NULL, extractType(f->function.resultType)); break; case FunctionName::normal: thisClass->defineMethod(name, NULL); diff --git a/js/js2/interpreter.cpp b/js/js2/interpreter.cpp index 3726926914e..80185b04ff8 100644 --- a/js/js2/interpreter.cpp +++ b/js/js2/interpreter.cpp @@ -710,6 +710,9 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args) ICodeModule *icm = target->getICode(); ArgumentList *args = op4(call); + // if all the parameters are positional +// if (icm->itsParameters->mPositionalCount == icm->itsParameters->size()) + // the parameter count includes 'this' and any named rest parameter // uint32 pCount = icm->itsParameters->size() - 1; // we won't be passing 'this' via the arg list array diff --git a/js/js2/js2.cpp b/js/js2/js2.cpp index 27c3ef6f743..d16177044df 100644 --- a/js/js2/js2.cpp +++ b/js/js2/js2.cpp @@ -171,6 +171,15 @@ static JSValue load(Context *cx, const JSValues &argv) return result; } +static bool goGeorge = false; + +static JSValue george(Context *cx, const JSValues &argv) +{ + goGeorge = !goGeorge; + + return JSValue(new JSString(goGeorge ? "George is going" : "George is taking a break")); +} + #if 0 // need a XP version of this, rip off from Monkey? #include static JSValue time(Context *cx, const JSValues &argv) @@ -189,7 +198,7 @@ class Tracer : public Context::Listener { typedef InstructionStream::difference_type InstructionOffset; void listen(Context* context, Context::Event event) { - if (event & Context::EV_STEP) { + if (goGeorge && (event & Context::EV_STEP)) { ICodeModule *iCode = context->getICode(); JSValues ®isters = context->getRegisters(); InstructionIterator pc = context->getPC(); @@ -212,7 +221,7 @@ class Tracer : public Context::Listener { } }; -//#define HAVE_GEORGE_TRACE_IT +#define HAVE_GEORGE_TRACE_IT //#define TEST_XML_LOADER static void readEvalPrint(FILE *in, World &world) @@ -225,6 +234,7 @@ static void readEvalPrint(FILE *in, World &world) global.defineNativeFunction(world.identifiers["print"], print); global.defineNativeFunction(world.identifiers["dump"], dump); global.defineNativeFunction(world.identifiers["load"], load); + global.defineNativeFunction(world.identifiers["george"], george); // global.defineNativeFunction(world.identifiers["time"], time); String buffer; diff --git a/js/js2/jsclasses.h b/js/js2/jsclasses.h index cc1b5556f69..ce11898ea92 100644 --- a/js/js2/jsclasses.h +++ b/js/js2/jsclasses.h @@ -50,7 +50,7 @@ namespace JSClasses { struct JSSlot { - typedef enum { kNoFlag = 0, kIsConstructor = 0x01 } SlotFlags; // <-- readonly, enumerable etc + typedef enum { kNoFlag = 0, kIsConstructor = 0x01, kIsVirtual = 0x02 } SlotFlags; // <-- readonly, enumerable etc // a slot may have a getter or a setter or both, but NOT either if mActual JSType* mType; @@ -65,6 +65,7 @@ namespace JSClasses { } bool isConstructor() const { return (mFlags & kIsConstructor) != 0; } + bool isVirtual() const { return (mFlags & kIsVirtual) != 0; } }; typedef gc_map_allocator(JSSlot) gc_slot_allocator; @@ -104,9 +105,12 @@ namespace JSClasses { { if (superClass) { // inherit superclass methods - JSMethods::iterator end = superClass->mMethods.end(); - for (JSMethods::iterator i = superClass->mMethods.begin(); i != end; i++) - mMethods.push_back(*i); + mMethods = JSMethods(superClass->mMethods); + // and virtual fields + JSSlots::iterator sEnd = superClass->mSlots.end(); + for (JSSlots::iterator si = superClass->mSlots.begin(); si != sEnd; si++) + if (si->second.isVirtual()) + mSlots[si->first] = si->second; } } @@ -120,14 +124,14 @@ namespace JSClasses { return mScope; } - const JSSlot& defineSlot(const String& name, JSType* type, JSFunction* getter = 0, JSFunction* setter = 0) + const JSSlot& defineSlot(const String& name, JSType* type, JSSlot::SlotFlags flags = JSSlot::kNoFlag, JSFunction* getter = 0, JSFunction* setter = 0) { JSSlot& slot = mSlots[name]; - ASSERT(slot.mType == 0); slot.mType = type; slot.mIndex = mSlotCount++; // starts at 0. slot.mSetter = setter; slot.mGetter = getter; + slot.mFlags = flags; if (setter || getter) slot.mActual = false; return slot; @@ -137,11 +141,13 @@ namespace JSClasses { { JSSlots::iterator slti = mSlots.find(name); if (slti == mSlots.end()) - defineSlot(name, type, getter, 0); + defineSlot(name, type, JSSlot::kNoFlag, getter, 0); else { - ASSERT(!slti->second.mActual); + if (slti->second.mActual) + ASSERT(slti->second.isVirtual()); ASSERT(slti->second.mGetter == 0); slti->second.mGetter = getter; + slti->second.mActual = false; } mHasGetters = true; } @@ -150,11 +156,14 @@ namespace JSClasses { { JSSlots::iterator slti = mSlots.find(name); if (slti == mSlots.end()) - defineSlot(name, type, 0, setter); + defineSlot(name, type, JSSlot::kNoFlag, 0, setter); else { - ASSERT(!slti->second.mActual); - ASSERT(slti->second.mSetter == 0); - slti->second.mSetter = setter; + JSSlot &s = slti->second; + if (s.mActual) + ASSERT(s.isVirtual()); + ASSERT(s.mSetter == 0); + s.mSetter = setter; + s.mActual = false; } mHasSetters = true; } diff --git a/js2/src/icodegenerator.cpp b/js2/src/icodegenerator.cpp index ed21c83e18e..d0c86871f5e 100644 --- a/js2/src/icodegenerator.cpp +++ b/js2/src/icodegenerator.cpp @@ -1613,6 +1613,16 @@ static bool hasAttribute(const IdentifierList* identifiers, Token::Kind tokenKin return false; } +static bool hasAttribute(const IdentifierList* identifiers, StringAtom &name) +{ + while (identifiers) { + if (identifiers->name == name) + return true; + identifiers = identifiers->next; + } + return false; +} + JSType *ICodeGenerator::extractType(ExprNode *t) { JSType* type = &Any_Type; @@ -1799,7 +1809,10 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet) if (isStatic) thisClass->defineStatic(idExpr->name, type); else { - thisClass->defineSlot(idExpr->name, type); + if (hasAttribute(vs->attributes, mContext->getWorld().identifiers["virtual"])) + thisClass->defineSlot(idExpr->name, type, JSSlot::kIsVirtual); + else + thisClass->defineSlot(idExpr->name, type); if (v->initializer) needsInstanceInitializer = true; } @@ -1823,12 +1836,11 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet) thisClass->defineStatic(name, &Function_Type); else { switch (f->function.prefix) { - // XXXX these dummy place holders for the getters/setters are leaking case FunctionName::Get: - thisClass->setGetter(name, new JSFunction(), extractType(f->function.resultType)); + thisClass->setGetter(name, NULL, extractType(f->function.resultType)); break; case FunctionName::Set: - thisClass->setSetter(name, new JSFunction(), extractType(f->function.resultType)); + thisClass->setSetter(name, NULL, extractType(f->function.resultType)); break; case FunctionName::normal: thisClass->defineMethod(name, NULL); diff --git a/js2/src/interpreter.cpp b/js2/src/interpreter.cpp index 3726926914e..80185b04ff8 100644 --- a/js2/src/interpreter.cpp +++ b/js2/src/interpreter.cpp @@ -710,6 +710,9 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args) ICodeModule *icm = target->getICode(); ArgumentList *args = op4(call); + // if all the parameters are positional +// if (icm->itsParameters->mPositionalCount == icm->itsParameters->size()) + // the parameter count includes 'this' and any named rest parameter // uint32 pCount = icm->itsParameters->size() - 1; // we won't be passing 'this' via the arg list array diff --git a/js2/src/jsclasses.h b/js2/src/jsclasses.h index cc1b5556f69..ce11898ea92 100644 --- a/js2/src/jsclasses.h +++ b/js2/src/jsclasses.h @@ -50,7 +50,7 @@ namespace JSClasses { struct JSSlot { - typedef enum { kNoFlag = 0, kIsConstructor = 0x01 } SlotFlags; // <-- readonly, enumerable etc + typedef enum { kNoFlag = 0, kIsConstructor = 0x01, kIsVirtual = 0x02 } SlotFlags; // <-- readonly, enumerable etc // a slot may have a getter or a setter or both, but NOT either if mActual JSType* mType; @@ -65,6 +65,7 @@ namespace JSClasses { } bool isConstructor() const { return (mFlags & kIsConstructor) != 0; } + bool isVirtual() const { return (mFlags & kIsVirtual) != 0; } }; typedef gc_map_allocator(JSSlot) gc_slot_allocator; @@ -104,9 +105,12 @@ namespace JSClasses { { if (superClass) { // inherit superclass methods - JSMethods::iterator end = superClass->mMethods.end(); - for (JSMethods::iterator i = superClass->mMethods.begin(); i != end; i++) - mMethods.push_back(*i); + mMethods = JSMethods(superClass->mMethods); + // and virtual fields + JSSlots::iterator sEnd = superClass->mSlots.end(); + for (JSSlots::iterator si = superClass->mSlots.begin(); si != sEnd; si++) + if (si->second.isVirtual()) + mSlots[si->first] = si->second; } } @@ -120,14 +124,14 @@ namespace JSClasses { return mScope; } - const JSSlot& defineSlot(const String& name, JSType* type, JSFunction* getter = 0, JSFunction* setter = 0) + const JSSlot& defineSlot(const String& name, JSType* type, JSSlot::SlotFlags flags = JSSlot::kNoFlag, JSFunction* getter = 0, JSFunction* setter = 0) { JSSlot& slot = mSlots[name]; - ASSERT(slot.mType == 0); slot.mType = type; slot.mIndex = mSlotCount++; // starts at 0. slot.mSetter = setter; slot.mGetter = getter; + slot.mFlags = flags; if (setter || getter) slot.mActual = false; return slot; @@ -137,11 +141,13 @@ namespace JSClasses { { JSSlots::iterator slti = mSlots.find(name); if (slti == mSlots.end()) - defineSlot(name, type, getter, 0); + defineSlot(name, type, JSSlot::kNoFlag, getter, 0); else { - ASSERT(!slti->second.mActual); + if (slti->second.mActual) + ASSERT(slti->second.isVirtual()); ASSERT(slti->second.mGetter == 0); slti->second.mGetter = getter; + slti->second.mActual = false; } mHasGetters = true; } @@ -150,11 +156,14 @@ namespace JSClasses { { JSSlots::iterator slti = mSlots.find(name); if (slti == mSlots.end()) - defineSlot(name, type, 0, setter); + defineSlot(name, type, JSSlot::kNoFlag, 0, setter); else { - ASSERT(!slti->second.mActual); - ASSERT(slti->second.mSetter == 0); - slti->second.mSetter = setter; + JSSlot &s = slti->second; + if (s.mActual) + ASSERT(s.isVirtual()); + ASSERT(s.mSetter == 0); + s.mSetter = setter; + s.mActual = false; } mHasSetters = true; } diff --git a/js2/tests/cpp/js2_shell.cpp b/js2/tests/cpp/js2_shell.cpp index 27c3ef6f743..d16177044df 100644 --- a/js2/tests/cpp/js2_shell.cpp +++ b/js2/tests/cpp/js2_shell.cpp @@ -171,6 +171,15 @@ static JSValue load(Context *cx, const JSValues &argv) return result; } +static bool goGeorge = false; + +static JSValue george(Context *cx, const JSValues &argv) +{ + goGeorge = !goGeorge; + + return JSValue(new JSString(goGeorge ? "George is going" : "George is taking a break")); +} + #if 0 // need a XP version of this, rip off from Monkey? #include static JSValue time(Context *cx, const JSValues &argv) @@ -189,7 +198,7 @@ class Tracer : public Context::Listener { typedef InstructionStream::difference_type InstructionOffset; void listen(Context* context, Context::Event event) { - if (event & Context::EV_STEP) { + if (goGeorge && (event & Context::EV_STEP)) { ICodeModule *iCode = context->getICode(); JSValues ®isters = context->getRegisters(); InstructionIterator pc = context->getPC(); @@ -212,7 +221,7 @@ class Tracer : public Context::Listener { } }; -//#define HAVE_GEORGE_TRACE_IT +#define HAVE_GEORGE_TRACE_IT //#define TEST_XML_LOADER static void readEvalPrint(FILE *in, World &world) @@ -225,6 +234,7 @@ static void readEvalPrint(FILE *in, World &world) global.defineNativeFunction(world.identifiers["print"], print); global.defineNativeFunction(world.identifiers["dump"], dump); global.defineNativeFunction(world.identifiers["load"], load); + global.defineNativeFunction(world.identifiers["george"], george); // global.defineNativeFunction(world.identifiers["time"], time); String buffer;