Commit 7b3794b2 authored by rogerl%netscape.com's avatar rogerl%netscape.com
Browse files

Changed array length handling.

parent 7f4dec79
Loading
Loading
Loading
Loading
+12 −18
Original line number Diff line number Diff line
@@ -59,32 +59,26 @@ namespace MetaData {
uint32 getLength(JS2Metadata *meta, JS2Object *obj)
{
    uint32 length = 0;
    if ((obj->kind == SimpleInstanceKind)
            && (checked_cast<SimpleInstance *>(obj)->type == meta->arrayClass)) {
        length = toUInt32(meta->toInteger(Array_lengthGet(meta, OBJECT_TO_JS2VAL(obj), NULL, 0)));
    }
    else {
        js2val result;
        JS2Class *c = meta->objectType(obj);
        js2val val = OBJECT_TO_JS2VAL(obj);
        if (c->ReadPublic(meta, &val, meta->engine->length_StringAtom, RunPhase, &result))
            length = toUInt32(meta->toInteger(result));
    }
    return length;
}

js2val setLength(JS2Metadata *meta, JS2Object *obj, uint32 newLength)
{
    js2val result = meta->engine->allocNumber(newLength);
    // XXX maybe should have setArrayLength as a specialization
    if ((obj->kind == SimpleInstanceKind)
            && (checked_cast<SimpleInstance *>(obj)->type == meta->arrayClass)) {
        uint32 length = getLength(meta, obj);
        if (newLength < length) {
            // need to delete all the elements above the new length
            bool deleteResult;
            JS2Class *c = meta->objectType(obj);
            for (uint32 i = newLength; i < length; i++) {
                c->DeletePublic(meta, OBJECT_TO_JS2VAL(obj), meta->engine->numberToString(i), &deleteResult);
            }
        }
        Multiname *mn = new Multiname(meta->engine->length_StringAtom, meta->publicNamespace);
        DEFINE_ROOTKEEPER(rk, mn);
        meta->arrayClass->Write(meta, OBJECT_TO_JS2VAL(obj), mn, meta->env, true, result, false);
        Array_lengthSet(meta, OBJECT_TO_JS2VAL(obj), &result, 1);
    }
    else {
        JS2Class *c = meta->objectType(obj);
+21 −14
Original line number Diff line number Diff line
@@ -729,7 +729,13 @@ namespace MetaData {
        ASSERT(JS2VAL_IS_OBJECT(base));
        JS2Object *obj = JS2VAL_TO_OBJECT(base);
        
        bool result = JS2Class::Write(meta, base, multiname, env, createIfMissing, newValue, false);
        bool result;
        if ((*multiname->name == *meta->engine->length_StringAtom) && (multiname->nsList->size() == 1) && (multiname->nsList->back() == meta->publicNamespace)) {
            Array_lengthSet(meta, base, &newValue, 1);
            result = true;
        }
        else {
            result = JS2Class::Write(meta, base, multiname, env, createIfMissing, newValue, false);
            if (result && (multiname->nsList->size() == 1) && (multiname->nsList->back() == meta->publicNamespace)) {
                const char16 *numEnd;        
                float64 f = stringToDouble(multiname->name->data(), multiname->name->data() + multiname->name->length(), numEnd);
@@ -745,6 +751,7 @@ namespace MetaData {
                }

            }
        }
        return result;
    }    

+51 −13
Original line number Diff line number Diff line
@@ -3845,6 +3845,33 @@ static const uint8 urlCharType[256] =
        return OBJECT_TO_JS2VAL(meta->functionClass->prototype);
    }
 
    js2val Array_lengthGet(JS2Metadata *meta, const js2val thisValue, js2val /* argv */ [], uint32 /* argc */)
    {
        ASSERT(JS2VAL_IS_OBJECT(thisValue));
        JS2Object *obj = JS2VAL_TO_OBJECT(thisValue);
        ArrayInstance *arrInst = checked_cast<ArrayInstance *>(obj);
        
        return meta->engine->allocNumber(arrInst->length);
    }

    js2val Array_lengthSet(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
    {
        ASSERT(JS2VAL_IS_OBJECT(thisValue));
        JS2Object *obj = JS2VAL_TO_OBJECT(thisValue);
        ArrayInstance *arrInst = checked_cast<ArrayInstance *>(obj);

        uint32 newLength = meta->convertValueToUInteger(argv[0]);
        if (newLength < arrInst->length) {
            // need to delete all the elements above the new length
            bool deleteResult;
            for (uint32 i = newLength; i < arrInst->length; i++) {
                meta->arrayClass->DeletePublic(meta, thisValue, meta->engine->numberToString(i), &deleteResult);
            }
        }
        arrInst->length = newLength;
        return JS2VAL_UNDEFINED;
    }

    static js2val Object_valueOf(JS2Metadata *meta, const js2val thisValue, js2val /* argv */ [], uint32 /* argc */)
    {
        return thisValue;
@@ -3949,28 +3976,28 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...


// Add __proto__ as a getter/setter instance member to Object & class
        Multiname mn(&world.identifiers["__proto__"], publicNamespace);
        Multiname proto_mn(&world.identifiers["__proto__"], publicNamespace);
        fInst = new FunctionInstance(this, functionClass->prototype, functionClass);
        fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_VOID, true), class_underbarProtoGet, env);
        fInst->fWrap->length = 0;
        InstanceGetter *g = new InstanceGetter(&mn, fInst, objectClass, true, true);
        defineInstanceMember(classClass, &cxt, mn.name, *mn.nsList, Attribute::NoOverride, false, g, 0);
        InstanceGetter *g = new InstanceGetter(&proto_mn, fInst, objectClass, true, true);
        defineInstanceMember(classClass, &cxt, proto_mn.name, *proto_mn.nsList, Attribute::NoOverride, false, g, 0);
        fInst = new FunctionInstance(this, functionClass->prototype, functionClass);
        fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_VOID, true), class_underbarProtoGet, env);
        fInst->fWrap->length = 0;
        InstanceSetter *s = new InstanceSetter(&mn, fInst, objectClass, true, true);
        defineInstanceMember(classClass, &cxt, mn.name, *mn.nsList, Attribute::NoOverride, false, s, 0);
        InstanceSetter *s = new InstanceSetter(&proto_mn, fInst, objectClass, true, true);
        defineInstanceMember(classClass, &cxt, proto_mn.name, *proto_mn.nsList, Attribute::NoOverride, false, s, 0);

        fInst = new FunctionInstance(this, functionClass->prototype, functionClass);
        fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_VOID, true), Object_underbarProtoGet, env);
        fInst->fWrap->length = 0;
        g = new InstanceGetter(&mn, fInst, objectClass, true, true);
        defineInstanceMember(objectClass, &cxt, mn.name, *mn.nsList, Attribute::NoOverride, false, g, 0);
        g = new InstanceGetter(&proto_mn, fInst, objectClass, true, true);
        defineInstanceMember(objectClass, &cxt, proto_mn.name, *proto_mn.nsList, Attribute::NoOverride, false, g, 0);
        fInst = new FunctionInstance(this, functionClass->prototype, functionClass);
        fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_VOID, true), Object_underbarProtoSet, env);
        fInst->fWrap->length = 0;
        s = new InstanceSetter(&mn, fInst, objectClass, true, true);
        defineInstanceMember(objectClass, &cxt, mn.name, *mn.nsList, Attribute::NoOverride, false, s, 0);
        s = new InstanceSetter(&proto_mn, fInst, objectClass, true, true);
        defineInstanceMember(objectClass, &cxt, proto_mn.name, *proto_mn.nsList, Attribute::NoOverride, false, s, 0);


// Adding 'toString' to the Object.prototype XXX Or make this a static class member?
@@ -4033,11 +4060,21 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
        initMathObject(this, mathObject);

/*** ECMA 3  Array Class ***/

        arrayClass = new JS2ArrayClass(objectClass, NULL, new Namespace(engine->private_StringAtom), true, true, engine->allocStringPtr(&world.identifiers["Array"])); arrayClass->complete = true; arrayClass->defaultValue = JS2VAL_NULL;        
        v = new Variable(classClass, OBJECT_TO_JS2VAL(arrayClass), true);
        defineLocalMember(env, &world.identifiers["Array"], NULL, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true);
        initArrayObject(this);
        Multiname length_mn(&world.identifiers["length"], publicNamespace);
        fInst = new FunctionInstance(this, functionClass->prototype, functionClass);
        fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_VOID, true), Array_lengthGet, env);
        fInst->fWrap->length = 0;
        g = new InstanceGetter(&length_mn, fInst, objectClass, true, true);
        defineInstanceMember(arrayClass, &cxt, length_mn.name, *length_mn.nsList, Attribute::NoOverride, false, g, 0);
        fInst = new FunctionInstance(this, functionClass->prototype, functionClass);
        fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_VOID, true), Array_lengthSet, env);
        fInst->fWrap->length = 0;
        s = new InstanceSetter(&length_mn, fInst, objectClass, true, true);
        defineInstanceMember(arrayClass, &cxt, length_mn.name, *length_mn.nsList, Attribute::NoOverride, false, s, 0);

/*** ECMA 3  Error Classes ***/
        MAKEBUILTINCLASS(errorClass, objectClass, true, true, engine->allocStringPtr(&world.identifiers["Error"]), JS2VAL_NULL);
@@ -4884,10 +4921,11 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
    ArrayInstance::ArrayInstance(JS2Metadata *meta, js2val parent, JS2Class *type) 
        : SimpleInstance(meta, parent, type) 
    {
        JS2Object *result = this;
        DEFINE_ROOTKEEPER(rk1, result);
        length = 0;
//        JS2Object *result = this;
//        DEFINE_ROOTKEEPER(rk1, result);

        meta->createDynamicProperty(this, meta->engine->length_StringAtom, INT_TO_JS2VAL(0), ReadWriteAccess, true, false);
//        meta->createDynamicProperty(this, meta->engine->length_StringAtom, INT_TO_JS2VAL(0), ReadWriteAccess, true, false);
    }

 /************************************************************************************
+6 −33
Original line number Diff line number Diff line
@@ -63,39 +63,6 @@ typedef js2val (Callor)(JS2Metadata *meta, const js2val thisValue, js2val *argv,
typedef js2val (Constructor)(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc);
typedef js2val (NativeCode)(JS2Metadata *meta, const js2val thisValue, js2val argv[], uint32 argc);

/*
typedef bool (Read)(JS2Metadata *meta, js2val *base, JS2Class *limit, Multiname *multiname, Environment *env, Phase phase, js2val *rval);
typedef bool (ReadPublic)(JS2Metadata *meta, js2val *base, JS2Class *limit, const String *name, Phase phase, js2val *rval);
typedef bool (Write)(JS2Metadata *meta, js2val base, JS2Class *limit, Multiname *multiname, Environment *env, bool createIfMissing, js2val newValue, bool initFlag);
typedef bool (WritePublic)(JS2Metadata *meta, js2val base, JS2Class *limit, const String *name, bool createIfMissing, js2val newValue);
typedef bool (DeleteProperty)(JS2Metadata *meta, js2val base, JS2Class *limit, Multiname *multiname, Environment *env, bool *result);
typedef bool (DeletePublic)(JS2Metadata *meta, js2val base, JS2Class *limit, const String *name, bool *result);
typedef bool (BracketRead)(JS2Metadata *meta, js2val *base, JS2Class *limit, js2val indexVal, Phase phase, js2val *rval);
typedef bool (BracketWrite)(JS2Metadata *meta, js2val base, JS2Class *limit, js2val indexVal, js2val newValue);
typedef bool (BracketDelete)(JS2Metadata *meta, js2val base, JS2Class *limit, js2val indexVal, bool *result);
typedef js2val (ImplicitCoerce)(JS2Metadata *meta, js2val newValue, JS2Class *toClass);
typedef js2val (Is)(JS2Metadata *meta, js2val newValue, JS2Class *isClass);

bool defaultReadProperty(JS2Metadata *meta, js2val *base, JS2Class *limit, Multiname *multiname, Environment *env, Phase phase, js2val *rval);
bool defaultReadPublicProperty(JS2Metadata *meta, js2val *base, JS2Class *limit, const String *name, Phase phase, js2val *rval);
bool defaultBracketRead(JS2Metadata *meta, js2val *base, JS2Class *limit, js2val indexVal, Phase phase, js2val *rval);
bool defaultWriteProperty(JS2Metadata *meta, js2val base, JS2Class *limit, Multiname *multiname, Environment *env, bool createIfMissing, js2val newValue, bool initFlag);
bool defaultWritePublicProperty(JS2Metadata *meta, js2val base, JS2Class *limit, const String *name, bool createIfMissing, js2val newValue);
bool defaultBracketWrite(JS2Metadata *meta, js2val base, JS2Class *limit, js2val indexVal, js2val newValue);
bool defaultDeleteProperty(JS2Metadata *meta, js2val base, JS2Class *limit, Multiname *multiname, Environment *env, bool *result);
bool defaultDeletePublic(JS2Metadata *meta, js2val base, JS2Class *limit, const String *name, bool *result);
bool defaultBracketDelete(JS2Metadata *meta, js2val base, JS2Class *limit, js2val indexVal, bool *result);

bool arrayClass_WriteProperty(JS2Metadata *meta, js2val base, JS2Class *limit, Multiname *multiname, Environment *env, bool createIfMissing, js2val newValue, bool initFlag);
bool arrayClass_WritePublic(JS2Metadata *meta, js2val base, JS2Class *limit, const String *name, bool createIfMissing, js2val newValue);

js2val defaultImplicitCoerce(JS2Metadata *meta, js2val newValue, JS2Class *isClass);
js2val defaultIs(JS2Metadata *meta, js2val newValue, JS2Class *isClass);
js2val integerImplicitCoerce(JS2Metadata *meta, js2val newValue, JS2Class *isClass);
js2val integerIs(JS2Metadata *meta, js2val newValue, JS2Class *isClass);

bool stringClass_BracketRead(JS2Metadata *meta, js2val *base, JS2Class *limit, js2val indexVal, Phase phase, js2val *rval);
*/
extern void initDateObject(JS2Metadata *meta);
extern void initStringObject(JS2Metadata *meta);
extern void initMathObject(JS2Metadata *meta, SimpleInstance *mathObject);
@@ -119,6 +86,10 @@ extern js2val RegExp_exec(JS2Metadata *meta, const js2val thisValue, js2val *arg
extern js2val Boolean_Constructor(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc);
extern js2val Number_Constructor(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc);


js2val Array_lengthGet(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc);
js2val Array_lengthSet(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc);

typedef struct {
    char *name;
    uint16 length;
@@ -1032,6 +1003,8 @@ class ArrayInstance : public SimpleInstance {
public:
    ArrayInstance(JS2Metadata *meta, js2val parent, JS2Class *type);
    virtual ~ArrayInstance()             { }

    uint32 length;
};

// RegExp instances are simple instances created by the RegExp class, they have an extra field