Fixed adding setter to virtual inherited field.

This commit is contained in:
rogerl%netscape.com 2000-11-03 02:42:01 +00:00
Родитель 5fb5604727
Коммит 7b8898dcf1
8 изменённых файлов: 104 добавлений и 36 удалений

Просмотреть файл

@ -1613,6 +1613,16 @@ static bool hasAttribute(const IdentifierList* identifiers, Token::Kind tokenKin
return false; 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 *ICodeGenerator::extractType(ExprNode *t)
{ {
JSType* type = &Any_Type; JSType* type = &Any_Type;
@ -1799,7 +1809,10 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
if (isStatic) if (isStatic)
thisClass->defineStatic(idExpr->name, type); thisClass->defineStatic(idExpr->name, type);
else { 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) if (v->initializer)
needsInstanceInitializer = true; needsInstanceInitializer = true;
} }
@ -1823,12 +1836,11 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
thisClass->defineStatic(name, &Function_Type); thisClass->defineStatic(name, &Function_Type);
else { else {
switch (f->function.prefix) { switch (f->function.prefix) {
// XXXX these dummy place holders for the getters/setters are leaking
case FunctionName::Get: case FunctionName::Get:
thisClass->setGetter(name, new JSFunction(), extractType(f->function.resultType)); thisClass->setGetter(name, NULL, extractType(f->function.resultType));
break; break;
case FunctionName::Set: case FunctionName::Set:
thisClass->setSetter(name, new JSFunction(), extractType(f->function.resultType)); thisClass->setSetter(name, NULL, extractType(f->function.resultType));
break; break;
case FunctionName::normal: case FunctionName::normal:
thisClass->defineMethod(name, NULL); thisClass->defineMethod(name, NULL);

Просмотреть файл

@ -710,6 +710,9 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
ICodeModule *icm = target->getICode(); ICodeModule *icm = target->getICode();
ArgumentList *args = op4(call); 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 // 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 uint32 pCount = icm->itsParameters->size() - 1; // we won't be passing 'this' via the arg list array

Просмотреть файл

@ -171,6 +171,15 @@ static JSValue load(Context *cx, const JSValues &argv)
return result; 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? #if 0 // need a XP version of this, rip off from Monkey?
#include <sys/timeb.h> #include <sys/timeb.h>
static JSValue time(Context *cx, const JSValues &argv) static JSValue time(Context *cx, const JSValues &argv)
@ -189,7 +198,7 @@ class Tracer : public Context::Listener {
typedef InstructionStream::difference_type InstructionOffset; typedef InstructionStream::difference_type InstructionOffset;
void listen(Context* context, Context::Event event) void listen(Context* context, Context::Event event)
{ {
if (event & Context::EV_STEP) { if (goGeorge && (event & Context::EV_STEP)) {
ICodeModule *iCode = context->getICode(); ICodeModule *iCode = context->getICode();
JSValues &registers = context->getRegisters(); JSValues &registers = context->getRegisters();
InstructionIterator pc = context->getPC(); 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 //#define TEST_XML_LOADER
static void readEvalPrint(FILE *in, World &world) 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["print"], print);
global.defineNativeFunction(world.identifiers["dump"], dump); global.defineNativeFunction(world.identifiers["dump"], dump);
global.defineNativeFunction(world.identifiers["load"], load); global.defineNativeFunction(world.identifiers["load"], load);
global.defineNativeFunction(world.identifiers["george"], george);
// global.defineNativeFunction(world.identifiers["time"], time); // global.defineNativeFunction(world.identifiers["time"], time);
String buffer; String buffer;

Просмотреть файл

@ -50,7 +50,7 @@ namespace JSClasses {
struct JSSlot { 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 // a slot may have a getter or a setter or both, but NOT either if mActual
JSType* mType; JSType* mType;
@ -65,6 +65,7 @@ namespace JSClasses {
} }
bool isConstructor() const { return (mFlags & kIsConstructor) != 0; } bool isConstructor() const { return (mFlags & kIsConstructor) != 0; }
bool isVirtual() const { return (mFlags & kIsVirtual) != 0; }
}; };
typedef gc_map_allocator(JSSlot) gc_slot_allocator; typedef gc_map_allocator(JSSlot) gc_slot_allocator;
@ -104,9 +105,12 @@ namespace JSClasses {
{ {
if (superClass) { if (superClass) {
// inherit superclass methods // inherit superclass methods
JSMethods::iterator end = superClass->mMethods.end(); mMethods = JSMethods(superClass->mMethods);
for (JSMethods::iterator i = superClass->mMethods.begin(); i != end; i++) // and virtual fields
mMethods.push_back(*i); 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; 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]; JSSlot& slot = mSlots[name];
ASSERT(slot.mType == 0);
slot.mType = type; slot.mType = type;
slot.mIndex = mSlotCount++; // starts at 0. slot.mIndex = mSlotCount++; // starts at 0.
slot.mSetter = setter; slot.mSetter = setter;
slot.mGetter = getter; slot.mGetter = getter;
slot.mFlags = flags;
if (setter || getter) if (setter || getter)
slot.mActual = false; slot.mActual = false;
return slot; return slot;
@ -137,11 +141,13 @@ namespace JSClasses {
{ {
JSSlots::iterator slti = mSlots.find(name); JSSlots::iterator slti = mSlots.find(name);
if (slti == mSlots.end()) if (slti == mSlots.end())
defineSlot(name, type, getter, 0); defineSlot(name, type, JSSlot::kNoFlag, getter, 0);
else { else {
ASSERT(!slti->second.mActual); if (slti->second.mActual)
ASSERT(slti->second.isVirtual());
ASSERT(slti->second.mGetter == 0); ASSERT(slti->second.mGetter == 0);
slti->second.mGetter = getter; slti->second.mGetter = getter;
slti->second.mActual = false;
} }
mHasGetters = true; mHasGetters = true;
} }
@ -150,11 +156,14 @@ namespace JSClasses {
{ {
JSSlots::iterator slti = mSlots.find(name); JSSlots::iterator slti = mSlots.find(name);
if (slti == mSlots.end()) if (slti == mSlots.end())
defineSlot(name, type, 0, setter); defineSlot(name, type, JSSlot::kNoFlag, 0, setter);
else { else {
ASSERT(!slti->second.mActual); JSSlot &s = slti->second;
ASSERT(slti->second.mSetter == 0); if (s.mActual)
slti->second.mSetter = setter; ASSERT(s.isVirtual());
ASSERT(s.mSetter == 0);
s.mSetter = setter;
s.mActual = false;
} }
mHasSetters = true; mHasSetters = true;
} }

Просмотреть файл

@ -1613,6 +1613,16 @@ static bool hasAttribute(const IdentifierList* identifiers, Token::Kind tokenKin
return false; 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 *ICodeGenerator::extractType(ExprNode *t)
{ {
JSType* type = &Any_Type; JSType* type = &Any_Type;
@ -1799,7 +1809,10 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
if (isStatic) if (isStatic)
thisClass->defineStatic(idExpr->name, type); thisClass->defineStatic(idExpr->name, type);
else { 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) if (v->initializer)
needsInstanceInitializer = true; needsInstanceInitializer = true;
} }
@ -1823,12 +1836,11 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
thisClass->defineStatic(name, &Function_Type); thisClass->defineStatic(name, &Function_Type);
else { else {
switch (f->function.prefix) { switch (f->function.prefix) {
// XXXX these dummy place holders for the getters/setters are leaking
case FunctionName::Get: case FunctionName::Get:
thisClass->setGetter(name, new JSFunction(), extractType(f->function.resultType)); thisClass->setGetter(name, NULL, extractType(f->function.resultType));
break; break;
case FunctionName::Set: case FunctionName::Set:
thisClass->setSetter(name, new JSFunction(), extractType(f->function.resultType)); thisClass->setSetter(name, NULL, extractType(f->function.resultType));
break; break;
case FunctionName::normal: case FunctionName::normal:
thisClass->defineMethod(name, NULL); thisClass->defineMethod(name, NULL);

Просмотреть файл

@ -710,6 +710,9 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
ICodeModule *icm = target->getICode(); ICodeModule *icm = target->getICode();
ArgumentList *args = op4(call); 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 // 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 uint32 pCount = icm->itsParameters->size() - 1; // we won't be passing 'this' via the arg list array

Просмотреть файл

@ -50,7 +50,7 @@ namespace JSClasses {
struct JSSlot { 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 // a slot may have a getter or a setter or both, but NOT either if mActual
JSType* mType; JSType* mType;
@ -65,6 +65,7 @@ namespace JSClasses {
} }
bool isConstructor() const { return (mFlags & kIsConstructor) != 0; } bool isConstructor() const { return (mFlags & kIsConstructor) != 0; }
bool isVirtual() const { return (mFlags & kIsVirtual) != 0; }
}; };
typedef gc_map_allocator(JSSlot) gc_slot_allocator; typedef gc_map_allocator(JSSlot) gc_slot_allocator;
@ -104,9 +105,12 @@ namespace JSClasses {
{ {
if (superClass) { if (superClass) {
// inherit superclass methods // inherit superclass methods
JSMethods::iterator end = superClass->mMethods.end(); mMethods = JSMethods(superClass->mMethods);
for (JSMethods::iterator i = superClass->mMethods.begin(); i != end; i++) // and virtual fields
mMethods.push_back(*i); 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; 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]; JSSlot& slot = mSlots[name];
ASSERT(slot.mType == 0);
slot.mType = type; slot.mType = type;
slot.mIndex = mSlotCount++; // starts at 0. slot.mIndex = mSlotCount++; // starts at 0.
slot.mSetter = setter; slot.mSetter = setter;
slot.mGetter = getter; slot.mGetter = getter;
slot.mFlags = flags;
if (setter || getter) if (setter || getter)
slot.mActual = false; slot.mActual = false;
return slot; return slot;
@ -137,11 +141,13 @@ namespace JSClasses {
{ {
JSSlots::iterator slti = mSlots.find(name); JSSlots::iterator slti = mSlots.find(name);
if (slti == mSlots.end()) if (slti == mSlots.end())
defineSlot(name, type, getter, 0); defineSlot(name, type, JSSlot::kNoFlag, getter, 0);
else { else {
ASSERT(!slti->second.mActual); if (slti->second.mActual)
ASSERT(slti->second.isVirtual());
ASSERT(slti->second.mGetter == 0); ASSERT(slti->second.mGetter == 0);
slti->second.mGetter = getter; slti->second.mGetter = getter;
slti->second.mActual = false;
} }
mHasGetters = true; mHasGetters = true;
} }
@ -150,11 +156,14 @@ namespace JSClasses {
{ {
JSSlots::iterator slti = mSlots.find(name); JSSlots::iterator slti = mSlots.find(name);
if (slti == mSlots.end()) if (slti == mSlots.end())
defineSlot(name, type, 0, setter); defineSlot(name, type, JSSlot::kNoFlag, 0, setter);
else { else {
ASSERT(!slti->second.mActual); JSSlot &s = slti->second;
ASSERT(slti->second.mSetter == 0); if (s.mActual)
slti->second.mSetter = setter; ASSERT(s.isVirtual());
ASSERT(s.mSetter == 0);
s.mSetter = setter;
s.mActual = false;
} }
mHasSetters = true; mHasSetters = true;
} }

Просмотреть файл

@ -171,6 +171,15 @@ static JSValue load(Context *cx, const JSValues &argv)
return result; 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? #if 0 // need a XP version of this, rip off from Monkey?
#include <sys/timeb.h> #include <sys/timeb.h>
static JSValue time(Context *cx, const JSValues &argv) static JSValue time(Context *cx, const JSValues &argv)
@ -189,7 +198,7 @@ class Tracer : public Context::Listener {
typedef InstructionStream::difference_type InstructionOffset; typedef InstructionStream::difference_type InstructionOffset;
void listen(Context* context, Context::Event event) void listen(Context* context, Context::Event event)
{ {
if (event & Context::EV_STEP) { if (goGeorge && (event & Context::EV_STEP)) {
ICodeModule *iCode = context->getICode(); ICodeModule *iCode = context->getICode();
JSValues &registers = context->getRegisters(); JSValues &registers = context->getRegisters();
InstructionIterator pc = context->getPC(); 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 //#define TEST_XML_LOADER
static void readEvalPrint(FILE *in, World &world) 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["print"], print);
global.defineNativeFunction(world.identifiers["dump"], dump); global.defineNativeFunction(world.identifiers["dump"], dump);
global.defineNativeFunction(world.identifiers["load"], load); global.defineNativeFunction(world.identifiers["load"], load);
global.defineNativeFunction(world.identifiers["george"], george);
// global.defineNativeFunction(world.identifiers["time"], time); // global.defineNativeFunction(world.identifiers["time"], time);
String buffer; String buffer;