зеркало из https://github.com/mozilla/pjs.git
Completed switch to prototype base for builtins. Fixed string.length
This commit is contained in:
Родитель
c613b5df3c
Коммит
2d6d09d271
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче