Completed switch to prototype base for builtins. Fixed string.length

This commit is contained in:
rogerl%netscape.com 2003-02-05 00:57:09 +00:00
Родитель c613b5df3c
Коммит 2d6d09d271
6 изменённых файлов: 72 добавлений и 21 удалений

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

@ -295,7 +295,9 @@ static int32 WeekDay(float64 t)
static float64 *Date_getProlog(JS2Metadata *meta, const js2val thisValue)
{
if (meta->objectType(thisValue) != meta->dateClass)
if (!JS2VAL_IS_OBJECT(thisValue)
|| (JS2VAL_TO_OBJECT(thisValue)->kind != PrototypeInstanceKind)
|| ((checked_cast<PrototypeInstance *>(JS2VAL_TO_OBJECT(thisValue)))->type != meta->dateClass))
meta->reportError(Exception::typeError, "You really need a date", meta->engine->errorPos());
DateInstance *dateInst = checked_cast<DateInstance *>(JS2VAL_TO_OBJECT(thisValue));
return &dateInst->ms;
@ -852,7 +854,7 @@ static js2val Date_format(JS2Metadata *meta, float64 date, formatspec format)
#define MAXARGS 7
js2val Date_Constructor(JS2Metadata *meta, const js2val /* thisValue */, js2val *argv, uint32 argc)
{
js2val thatValue = OBJECT_TO_JS2VAL(new DateInstance(meta->dateClass));
js2val thatValue = OBJECT_TO_JS2VAL(new DateInstance(meta->dateClass->prototype, meta->dateClass));
DateInstance *thisInst = checked_cast<DateInstance *>(JS2VAL_TO_OBJECT(thatValue));
/* Date called as constructor */
@ -1467,10 +1469,22 @@ void initDateObject(JS2Metadata *meta)
NamespaceList publicNamespaceList;
publicNamespaceList.push_back(meta->publicNamespace);
meta->dateClass->prototype = new DateInstance(meta->objectClass->prototype, meta->booleanClass);
// Adding "prototype" & "length" as static members of the class - not dynamic properties; XXX
meta->env->addFrame(meta->dateClass);
Variable *v = new Variable(meta->dateClass, OBJECT_TO_JS2VAL(meta->dateClass->prototype), true);
meta->defineLocalMember(meta->env, meta->engine->prototype_StringAtom, &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
v = new Variable(meta->numberClass, INT_TO_JS2VAL(1), true);
meta->defineLocalMember(meta->env, meta->engine->length_StringAtom, &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
meta->env->removeTopFrame();
PrototypeFunction *pf = &prototypeFunctions[0];
while (pf->name) {
SimpleInstance *fInst = new SimpleInstance(meta->functionClass);
fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code);
SimpleInstance *callInst = new SimpleInstance(meta->functionClass);
callInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code);
/*
XXX not prototype object function properties, like ECMA3
meta->writeDynamicProperty(meta->dateClass->prototype, new Multiname(meta->world.identifiers[pf->name], meta->publicNamespace), true, OBJECT_TO_JS2VAL(fInst), RunPhase);
@ -1480,9 +1494,15 @@ XXX not static members, since those can't be accessed from the instance
Variable *v = new Variable(meta->functionClass, OBJECT_TO_JS2VAL(fInst), true);
meta->defineLocalMember(&meta->env, &meta->world.identifiers[pf->name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
*/
InstanceMember *m = new InstanceMethod(fInst);
InstanceMember *m = new InstanceMethod(callInst);
meta->defineInstanceMember(meta->dateClass, &meta->cxt, &meta->world.identifiers[pf->name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, m, 0);
FunctionInstance *fInst = new FunctionInstance(meta->functionClass->prototype, meta->functionClass);
fInst->fWrap = callInst->fWrap;
meta->writeDynamicProperty(meta->dateClass->prototype, new Multiname(&meta->world.identifiers[pf->name], meta->publicNamespace), true, OBJECT_TO_JS2VAL(fInst), RunPhase);
meta->writeDynamicProperty(fInst, new Multiname(meta->engine->length_StringAtom, meta->publicNamespace), true, INT_TO_JS2VAL(pf->length), RunPhase);
pf++;
}
}

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

@ -88,6 +88,7 @@ namespace MetaData {
retval = JS2VAL_VOID;
baseVal = JS2VAL_VOID;
indexVal = JS2VAL_VOID;
int i = 0;
while (true) {
try {
a = JS2VAL_VOID;
@ -106,7 +107,7 @@ namespace MetaData {
default:
NOT_REACHED("Bad opcode, no biscuit");
}
JS2Object::gc(meta); // XXX temporarily, for testing
if ((i++ % 200) == 0) JS2Object::gc(meta); // XXX temporarily, for testing
}
catch (Exception &jsx) {
if (mTryStack.size() > 0) {

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

@ -126,7 +126,7 @@ namespace MetaData {
pCount = 0;
while (pb) {
// XXX define a static binding for each parameter
Variable *v = new Variable();
Variable *v = new Variable(objectClass, JS2VAL_UNDEFINED, false);
compileFrame->positional[pCount++] = v;
pb->mn = defineLocalMember(env, pb->name, &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, pb->pos);
pb = pb->next;
@ -3394,6 +3394,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
bool JS2Metadata::readProperty(js2val containerVal, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval)
{
bool isSimpleInstance = false;
JS2Object *container;
if (JS2VAL_IS_PRIMITIVE(containerVal)) {
readClassProperty:
JS2Class *c = objectType(containerVal);
@ -3403,10 +3404,13 @@ readClassProperty:
else {
// XXX Spec. would have us passing a primitive here since ES4 is 'not addressing' the issue
// of so-called wrapper objects.
return readInstanceMember(toObject(containerVal), c, (ib) ? &ib->qname : NULL, phase, rval);
if (!JS2VAL_IS_OBJECT(containerVal))
containerVal = toObject(containerVal);
else
return readInstanceMember(containerVal, c, (ib) ? &ib->qname : NULL, phase, rval);
}
}
JS2Object *container = JS2VAL_TO_OBJECT(containerVal);
container = JS2VAL_TO_OBJECT(containerVal);
switch (container->kind) {
case AttributeObjectKind:
case MultinameKind:

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

@ -588,30 +588,30 @@ public:
// Date instances are simple instances created by the Date class, they have an extra field
// that contains the millisecond count
class DateInstance : public SimpleInstance {
class DateInstance : public PrototypeInstance {
public:
DateInstance(JS2Class *type) : SimpleInstance(type) { }
DateInstance(JS2Object *parent, JS2Class *type) : PrototypeInstance(parent, type) { }
float64 ms;
};
// String instances are simple instances created by the String class, they have an extra field
// that contains the string data
class StringInstance : public SimpleInstance {
class StringInstance : public PrototypeInstance {
public:
StringInstance(JS2Class *type) : SimpleInstance(type), mValue(NULL) { }
StringInstance(JS2Object *parent, JS2Class *type) : PrototypeInstance(parent, type), mValue(NULL) { }
String *mValue; // has been allocated by engine in the GC'able Pond
virtual void markChildren() { if (mValue) JS2Object::mark(mValue); }
virtual void markChildren() { PrototypeInstance::markChildren(); if (mValue) JS2Object::mark(mValue); }
virtual ~StringInstance() { }
};
// Number instances are simple instances created by the Number class, they have an extra field
// that contains the float64 data
class NumberInstance : public SimpleInstance {
class NumberInstance : public PrototypeInstance {
public:
NumberInstance(JS2Class *type) : SimpleInstance(type), mValue(0.0) { }
NumberInstance(JS2Object *parent, JS2Class *type) : PrototypeInstance(parent, type), mValue(0.0) { }
float64 mValue;
virtual ~NumberInstance() { }

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

@ -57,7 +57,7 @@ namespace MetaData {
js2val Number_Constructor(JS2Metadata *meta, const js2val thisValue, js2val argv[], uint32 argc)
{
js2val thatValue = OBJECT_TO_JS2VAL(new NumberInstance(meta->numberClass));
js2val thatValue = OBJECT_TO_JS2VAL(new NumberInstance(meta->numberClass->prototype, meta->numberClass));
NumberInstance *numInst = checked_cast<NumberInstance *>(JS2VAL_TO_OBJECT(thatValue));
if (argc > 0)
@ -67,6 +67,14 @@ namespace MetaData {
return thatValue;
}
static js2val Number_Call(JS2Metadata *meta, const js2val thisValue, js2val argv[], uint32 argc)
{
if (argc > 0)
return meta->engine->allocNumber(meta->toFloat64(argv[0]));
else
return JS2VAL_ZERO;
}
static js2val Number_toString(JS2Metadata *meta, const js2val thisValue, js2val * /*argv*/, uint32 /*argc*/)
{
if (meta->objectType(thisValue) != meta->numberClass)
@ -82,6 +90,7 @@ namespace MetaData {
void initNumberObject(JS2Metadata *meta)
{
meta->numberClass->construct = Number_Constructor;
meta->numberClass->call = Number_Call;
#define N_CONSTANTS_COUNT (5)

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

@ -59,13 +59,15 @@ js2val String_Constructor(JS2Metadata *meta, const js2val /*thisValue*/, js2val
{
// XXX GC might happen after the new StringInstance, but before the
// object gets rooted somewhere - this is a general problem...
js2val thatValue = OBJECT_TO_JS2VAL(new StringInstance(meta->stringClass));
js2val thatValue = OBJECT_TO_JS2VAL(new StringInstance(meta->stringClass->prototype, meta->stringClass));
StringInstance *strInst = checked_cast<StringInstance *>(JS2VAL_TO_OBJECT(thatValue));
if (argc > 0)
strInst->mValue = meta->engine->allocStringPtr(meta->toString(argv[0]));
else
strInst->mValue = meta->engine->allocStringPtr("");
Multiname mn(meta->engine->length_StringAtom, meta->publicNamespace);
meta->writeDynamicProperty(JS2VAL_TO_OBJECT(thatValue), &mn, true, meta->engine->allocNumber(strInst->mValue->length()), RunPhase);
return thatValue;
}
@ -782,16 +784,31 @@ void initStringObject(JS2Metadata *meta)
meta->stringClass->construct = String_Constructor;
meta->stringClass->prototype = new StringInstance(meta->objectClass->prototype, meta->booleanClass);
// Adding "prototype" & "length" as static members of the class - not dynamic properties; XXX
meta->env->addFrame(meta->stringClass);
Variable *v = new Variable(meta->stringClass, OBJECT_TO_JS2VAL(meta->stringClass->prototype), true);
meta->defineLocalMember(meta->env, meta->engine->prototype_StringAtom, &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
v = new Variable(meta->numberClass, INT_TO_JS2VAL(1), true);
meta->defineLocalMember(meta->env, meta->engine->length_StringAtom, &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
meta->env->removeTopFrame();
PrototypeFunction *pf = &prototypeFunctions[0];
while (pf->name) {
SimpleInstance *fInst = new SimpleInstance(meta->functionClass);
fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code);
SimpleInstance *callInst = new SimpleInstance(meta->functionClass);
callInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code);
/*
XXX not prototype object function properties, like ECMA3, but members of the String class
meta->writeDynamicProperty(meta->stringClass->prototype, new Multiname(meta->world.identifiers[pf->name], meta->publicNamespace), true, OBJECT_TO_JS2VAL(fInst), RunPhase);
*/
InstanceMember *m = new InstanceMethod(fInst);
InstanceMember *m = new InstanceMethod(callInst);
meta->defineInstanceMember(meta->stringClass, &meta->cxt, &meta->world.identifiers[pf->name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, m, 0);
FunctionInstance *fInst = new FunctionInstance(meta->functionClass->prototype, meta->functionClass);
fInst->fWrap = callInst->fWrap;
meta->writeDynamicProperty(meta->stringClass->prototype, new Multiname(&meta->world.identifiers[pf->name], meta->publicNamespace), true, OBJECT_TO_JS2VAL(fInst), RunPhase);
meta->writeDynamicProperty(fInst, new Multiname(meta->engine->length_StringAtom, meta->publicNamespace), true, INT_TO_JS2VAL(pf->length), RunPhase);
pf++;
}