From e86532ffbcacbfeb885cf58ce2cc62f050b1873e Mon Sep 17 00:00:00 2001 From: "rogerl%netscape.com" Date: Tue, 20 May 2003 22:51:51 +0000 Subject: [PATCH] Changed array length handling. git-svn-id: svn://10.0.0.236/trunk@142670 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/js2/src/js2array.cpp | 30 +++++++--------- mozilla/js2/src/js2eval.cpp | 31 +++++++++------- mozilla/js2/src/js2metadata.cpp | 64 ++++++++++++++++++++++++++------- mozilla/js2/src/js2metadata.h | 39 ++++---------------- 4 files changed, 88 insertions(+), 76 deletions(-) diff --git a/mozilla/js2/src/js2array.cpp b/mozilla/js2/src/js2array.cpp index 0b7d7e196d4..c49c99d56e3 100644 --- a/mozilla/js2/src/js2array.cpp +++ b/mozilla/js2/src/js2array.cpp @@ -59,32 +59,26 @@ namespace MetaData { uint32 getLength(JS2Metadata *meta, JS2Object *obj) { uint32 length = 0; - 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)); + if ((obj->kind == SimpleInstanceKind) + && (checked_cast(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(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); diff --git a/mozilla/js2/src/js2eval.cpp b/mozilla/js2/src/js2eval.cpp index 8fbc964c375..43376cbc6d1 100644 --- a/mozilla/js2/src/js2eval.cpp +++ b/mozilla/js2/src/js2eval.cpp @@ -728,22 +728,29 @@ namespace MetaData { { ASSERT(JS2VAL_IS_OBJECT(base)); JS2Object *obj = JS2VAL_TO_OBJECT(base); + + 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); + uint32 index = JS2Engine::float64toUInt32(f); - bool 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); - uint32 index = JS2Engine::float64toUInt32(f); + char buf[dtosStandardBufferSize]; + const char *chrp = doubleToStr(buf, dtosStandardBufferSize, index, dtosStandard, 0); - char buf[dtosStandardBufferSize]; - const char *chrp = doubleToStr(buf, dtosStandardBufferSize, index, dtosStandard, 0); + if (widenCString(chrp) == *multiname->name) { + uint32 length = getLength(meta, obj); + if (index >= length) + setLength(meta, obj, index + 1); + } - if (widenCString(chrp) == *multiname->name) { - uint32 length = getLength(meta, obj); - if (index >= length) - setLength(meta, obj, index + 1); } - } return result; } diff --git a/mozilla/js2/src/js2metadata.cpp b/mozilla/js2/src/js2metadata.cpp index 9ee8c5fa1b9..bd566200dfc 100644 --- a/mozilla/js2/src/js2metadata.cpp +++ b/mozilla/js2/src/js2metadata.cpp @@ -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(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(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); } /************************************************************************************ diff --git a/mozilla/js2/src/js2metadata.h b/mozilla/js2/src/js2metadata.h index 2b79b8f351a..8fde36a9461 100644 --- a/mozilla/js2/src/js2metadata.h +++ b/mozilla/js2/src/js2metadata.h @@ -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