зеркало из https://github.com/mozilla/pjs.git
Fixed adding setter to virtual inherited field.
This commit is contained in:
Родитель
5fb5604727
Коммит
7b8898dcf1
|
@ -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 ®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;
|
||||
|
|
|
@ -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 ®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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче