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;
}
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);

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

@ -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

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

@ -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 <sys/timeb.h>
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 &registers = 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;

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

@ -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;
}

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

@ -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);

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

@ -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

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

@ -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;
}

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

@ -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 <sys/timeb.h>
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 &registers = 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;