From 63ae1fcbf1028ea7f3e5f497734afe6314ce6b4d Mon Sep 17 00:00:00 2001 From: "rogerl%netscape.com" Date: Thu, 20 Feb 2003 16:17:49 +0000 Subject: [PATCH] Fixed Array.length & proto functions. git-svn-id: svn://10.0.0.236/trunk@138036 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/js2/src/js2array.cpp | 47 +++++++++++++++++++++------- mozilla/js2/src/js2engine.cpp | 2 +- mozilla/js2/src/js2engine.h | 2 +- mozilla/js2/src/js2metadata.cpp | 36 ++++++++++++--------- mozilla/js2/src/js2metadata.h | 12 +++++-- mozilla/js2/src/js2op_arithmetic.cpp | 6 ++-- mozilla/js2/src/js2op_literal.cpp | 2 +- mozilla/js2/src/js2regexp.cpp | 2 +- mozilla/js2/src/js2string.cpp | 4 +-- mozilla/js2/src/js2value.h | 2 ++ 10 files changed, 77 insertions(+), 38 deletions(-) diff --git a/mozilla/js2/src/js2array.cpp b/mozilla/js2/src/js2array.cpp index c3934078038..bce390fdfde 100644 --- a/mozilla/js2/src/js2array.cpp +++ b/mozilla/js2/src/js2array.cpp @@ -68,15 +68,31 @@ uint32 getLength(JS2Metadata *meta, JS2Object *obj) js2val setLength(JS2Metadata *meta, JS2Object *obj, uint32 length) { - Multiname mn(meta->engine->length_StringAtom, meta->publicNamespace); js2val result = meta->engine->allocNumber(length); - meta->writeDynamicProperty(obj, &mn, true, result, RunPhase); + + if (obj->kind == PrototypeInstanceKind) { + // Can't call 'writeDynamicProperty' as that'll just cycle back here for + // ArrayInstances. + DynamicPropertyMap *dMap = &checked_cast(obj)->dynamicProperties; + for (DynamicPropertyIterator i = dMap->begin(), end = dMap->end(); (i != end); i++) { + if (i->first == *meta->engine->length_StringAtom) { + i->second = result; + return result; + } + } + const DynamicPropertyMap::value_type e(*meta->engine->length_StringAtom, result); + checked_cast(obj)->dynamicProperties.insert(e); + } + else { + Multiname mn(meta->engine->length_StringAtom, meta->publicNamespace); + meta->writeDynamicProperty(obj, &mn, true, result, RunPhase); + } return result; } js2val Array_Constructor(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc) { - js2val thatValue = OBJECT_TO_JS2VAL(new ArrayInstance(meta->arrayClass->prototype, meta->arrayClass)); + js2val thatValue = OBJECT_TO_JS2VAL(new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass)); ArrayInstance *arrInst = checked_cast(JS2VAL_TO_OBJECT(thatValue)); if (argc > 0) { if (argc == 1) { @@ -208,7 +224,7 @@ js2val Array_concat(JS2Metadata *meta, const js2val thisValue, js2val *argv, uin { js2val E = thisValue; - js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta->arrayClass->prototype, meta->arrayClass)); + js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass)); ArrayInstance *A = checked_cast(JS2VAL_TO_OBJECT(result)); uint32 n = 0; uint32 i = 0; @@ -358,7 +374,7 @@ static js2val Array_slice(JS2Metadata *meta, const js2val thisValue, js2val *arg ASSERT(JS2VAL_IS_OBJECT(thisValue)); JS2Object *thisObj = JS2VAL_TO_OBJECT(thisValue); - js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta->arrayClass->prototype, meta->arrayClass)); + js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass)); ArrayInstance *A = checked_cast(JS2VAL_TO_OBJECT(result)); uint32 length = getLength(meta, thisObj); @@ -584,7 +600,7 @@ static js2val Array_splice(JS2Metadata *meta, const js2val thisValue, js2val *ar JS2Object *thisObj = JS2VAL_TO_OBJECT(thisValue); uint32 length = getLength(meta, thisObj); - js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta->arrayClass->prototype, meta->arrayClass)); + js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass)); ArrayInstance *A = checked_cast(JS2VAL_TO_OBJECT(result)); int32 arg0 = meta->toInteger(argv[0]); @@ -807,7 +823,8 @@ void initArrayObject(JS2Metadata *meta) publicNamespaceList.push_back(meta->publicNamespace); meta->arrayClass->construct = Array_Constructor; - meta->arrayClass->prototype = new ArrayInstance(meta->objectClass->prototype, meta->arrayClass); + meta->arrayClass->call = Array_Constructor; + meta->arrayClass->prototype = new ArrayInstance(meta, meta->objectClass->prototype, meta->arrayClass); // Adding "prototype" & "length" as static members of the class - not dynamic properties; XXX meta->env->addFrame(meta->arrayClass); @@ -819,11 +836,19 @@ void initArrayObject(JS2Metadata *meta) PrototypeFunction *pf = &arrayProtos[0]; while (pf->name) { - SimpleInstance *fInst = new SimpleInstance(meta->functionClass); - fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code); - - InstanceMember *m = new InstanceMethod(fInst); + + SimpleInstance *callInst = new SimpleInstance(meta->functionClass); + callInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code); + InstanceMember *m = new InstanceMethod(callInst); meta->defineInstanceMember(meta->arrayClass, &meta->cxt, &meta->world.identifiers[pf->name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, m, 0); +/* + Dynamic property of the prototype: +*/ + FunctionInstance *fInst = new FunctionInstance(meta->functionClass->prototype, meta->functionClass); + fInst->fWrap = callInst->fWrap; + meta->writeDynamicProperty(meta->arrayClass->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++; } } diff --git a/mozilla/js2/src/js2engine.cpp b/mozilla/js2/src/js2engine.cpp index 72eaaf630b9..b361195fd12 100644 --- a/mozilla/js2/src/js2engine.cpp +++ b/mozilla/js2/src/js2engine.cpp @@ -223,7 +223,7 @@ namespace MetaData { // otherwise get a double value js2val JS2Engine::allocNumber(float64 x) { - uint32 i; + int32 i; js2val retval; if (JSDOUBLE_IS_INT(x, i) && INT_FITS_IN_JS2VAL(i)) retval = INT_TO_JS2VAL(i); diff --git a/mozilla/js2/src/js2engine.h b/mozilla/js2/src/js2engine.h index 7ae3569add0..366972bc1a0 100644 --- a/mozilla/js2/src/js2engine.h +++ b/mozilla/js2/src/js2engine.h @@ -268,7 +268,7 @@ public: // The execution stack for expression evaluation, should be empty // between statements. -#define INITIAL_EXEC_STACK (40) +#define INITIAL_EXEC_STACK (80) js2val *execStackLimit; js2val *execStack; diff --git a/mozilla/js2/src/js2metadata.cpp b/mozilla/js2/src/js2metadata.cpp index fea39c3a8fd..6ada3e19fc0 100644 --- a/mozilla/js2/src/js2metadata.cpp +++ b/mozilla/js2/src/js2metadata.cpp @@ -3066,14 +3066,14 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... writeDynamicProperty(fInst, new Multiname(engine->length_StringAtom, publicNamespace), true, INT_TO_JS2VAL(0), RunPhase); /*** ECMA 3 Date Class ***/ - MAKEBUILTINCLASS(dateClass, objectClass, true, true, true, &world.identifiers["Date"], JS2VAL_NULL); + MAKEBUILTINCLASS(dateClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["Date"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(dateClass), true); defineLocalMember(env, &world.identifiers["Date"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); // dateClass->prototype = new PrototypeInstance(NULL, dateClass); initDateObject(this); /*** ECMA 3 RegExp Class ***/ - MAKEBUILTINCLASS(regexpClass, objectClass, true, true, true, &world.identifiers["RegExp"], JS2VAL_NULL); + MAKEBUILTINCLASS(regexpClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["RegExp"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(regexpClass), true); defineLocalMember(env, &world.identifiers["RegExp"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); initRegExpObject(this); @@ -3094,37 +3094,37 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... initBooleanObject(this); /*** ECMA 3 Math Class ***/ - MAKEBUILTINCLASS(mathClass, objectClass, true, true, true, &world.identifiers["Math"], JS2VAL_NULL); + MAKEBUILTINCLASS(mathClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["Math"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(mathClass), true); defineLocalMember(env, &world.identifiers["Math"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); initMathObject(this); /*** ECMA 3 Array Class ***/ - MAKEBUILTINCLASS(arrayClass, objectClass, true, true, true, &world.identifiers["Array"], JS2VAL_NULL); + MAKEBUILTINCLASS(arrayClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["Array"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(arrayClass), true); defineLocalMember(env, &world.identifiers["Array"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); initArrayObject(this); /*** ECMA 3 Error Classes ***/ - MAKEBUILTINCLASS(errorClass, objectClass, true, true, true, &world.identifiers["Error"], JS2VAL_NULL); + MAKEBUILTINCLASS(errorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["Error"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(errorClass), true); defineLocalMember(env, &world.identifiers["Error"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); - MAKEBUILTINCLASS(evalErrorClass, objectClass, true, true, true, &world.identifiers["EvalError"], JS2VAL_NULL); + MAKEBUILTINCLASS(evalErrorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["EvalError"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(evalErrorClass), true); defineLocalMember(env, &world.identifiers["EvalError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); - MAKEBUILTINCLASS(rangeErrorClass, objectClass, true, true, true, &world.identifiers["RangeError"], JS2VAL_NULL); + MAKEBUILTINCLASS(rangeErrorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["RangeError"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(rangeErrorClass), true); defineLocalMember(env, &world.identifiers["RangeError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); - MAKEBUILTINCLASS(referenceErrorClass, objectClass, true, true, true, &world.identifiers["ReferenceError"], JS2VAL_NULL); + MAKEBUILTINCLASS(referenceErrorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["ReferenceError"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(referenceErrorClass), true); defineLocalMember(env, &world.identifiers["ReferenceError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); - MAKEBUILTINCLASS(syntaxErrorClass, objectClass, true, true, true, &world.identifiers["SyntaxError"], JS2VAL_NULL); + MAKEBUILTINCLASS(syntaxErrorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["SyntaxError"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(syntaxErrorClass), true); defineLocalMember(env, &world.identifiers["SyntaxError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); - MAKEBUILTINCLASS(typeErrorClass, objectClass, true, true, true, &world.identifiers["TypeError"], JS2VAL_NULL); + MAKEBUILTINCLASS(typeErrorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["TypeError"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(typeErrorClass), true); defineLocalMember(env, &world.identifiers["TypeError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); - MAKEBUILTINCLASS(uriErrorClass, objectClass, true, true, true, &world.identifiers["UriError"], JS2VAL_NULL); + MAKEBUILTINCLASS(uriErrorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["UriError"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(uriErrorClass), true); defineLocalMember(env, &world.identifiers["UriError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); initErrorObject(this); @@ -3303,6 +3303,12 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... dynamicProperties->insert(e); } + void PrototypeInstance::writeProperty(JS2Metadata * /* meta */, const String *name, js2val newValue) + { + const DynamicPropertyMap::value_type e(*name, newValue); + dynamicProperties.insert(e); + } + void ArrayInstance::writeProperty(JS2Metadata *meta, const String *name, js2val newValue) { // An index has to pass the test that : @@ -3372,8 +3378,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... } else { PrototypeInstance *pInst = checked_cast(container); - const DynamicPropertyMap::value_type e(*name, newValue); - pInst->dynamicProperties.insert(e); + pInst->writeProperty(this, name, newValue); return true; } } @@ -3982,6 +3987,7 @@ deleteClassProperty: GCMARKOBJECT(dateClass); GCMARKOBJECT(regexpClass); GCMARKOBJECT(mathClass); + GCMARKOBJECT(arrayClass); GCMARKOBJECT(errorClass); GCMARKOBJECT(evalErrorClass); GCMARKOBJECT(rangeErrorClass); @@ -4644,9 +4650,9 @@ deleteClassProperty: ParameterFrame *plural = checked_cast(pluralFrame); ASSERT((plural->positionalCount == 0) || (plural->positional != NULL)); - js2val argumentsVal = OBJECT_TO_JS2VAL(new ArrayInstance(meta->arrayClass->prototype, meta->arrayClass)); + js2val argumentsVal = OBJECT_TO_JS2VAL(new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass)); ArrayInstance *arrInst = checked_cast(JS2VAL_TO_OBJECT(argumentsVal)); - uint32 i; + uint32 i; for (i = 0; ((i < argCount) && (i < plural->positionalCount)); i++) { ASSERT(plural->positional[i]->cloneContent); ASSERT(plural->positional[i]->cloneContent->kind == Member::Variable); diff --git a/mozilla/js2/src/js2metadata.h b/mozilla/js2/src/js2metadata.h index 4f3f2eaf412..1fb5a5390d5 100644 --- a/mozilla/js2/src/js2metadata.h +++ b/mozilla/js2/src/js2metadata.h @@ -187,6 +187,8 @@ public: static void mark(const void *p) { ((PondScum *)p)[-1].mark(); } static void markJS2Value(js2val v); + virtual void writeProperty(JS2Metadata *meta, const String *name, js2val newValue) { ASSERT(false); } + }; class Attribute : public JS2Object { @@ -563,10 +565,11 @@ public: DynamicPropertyMap *dynamicProperties; // A set of this instance's dynamic properties, or NULL if this is a fixed instance FunctionWrapper *fWrap; - virtual void writeProperty(JS2Metadata *meta, const String *name, js2val newValue); - virtual void markChildren(); virtual ~SimpleInstance() { } + + virtual void writeProperty(JS2Metadata *meta, const String *name, js2val newValue); + }; @@ -584,6 +587,9 @@ public: DynamicPropertyMap dynamicProperties; // A set of this instance's dynamic properties virtual void markChildren(); virtual ~PrototypeInstance() { } + + virtual void writeProperty(JS2Metadata *meta, const String *name, js2val newValue); + }; // Date instances are simple instances created by the Date class, they have an extra field @@ -644,7 +650,7 @@ public: // are added. class ArrayInstance : public PrototypeInstance { public: - ArrayInstance(JS2Object *parent, JS2Class *type) : PrototypeInstance(parent, type) { } + ArrayInstance(JS2Metadata *meta, JS2Object *parent, JS2Class *type) : PrototypeInstance(parent, type) { setLength(meta, this, 0); } virtual void writeProperty(JS2Metadata *meta, const String *name, js2val newValue); virtual ~ArrayInstance() { } diff --git a/mozilla/js2/src/js2op_arithmetic.cpp b/mozilla/js2/src/js2op_arithmetic.cpp index f9ec958acc6..97b27bfeb84 100644 --- a/mozilla/js2/src/js2op_arithmetic.cpp +++ b/mozilla/js2/src/js2op_arithmetic.cpp @@ -398,14 +398,14 @@ pushNumber(z); } } - } + } } break; case eSubtract: { - b = pop(); - a = pop(); + b = pop(); + a = pop(); a = meta->toGeneralNumber(a); b = meta->toGeneralNumber(b); if (JS2VAL_IS_LONG(a)) { diff --git a/mozilla/js2/src/js2op_literal.cpp b/mozilla/js2/src/js2op_literal.cpp index 463178f363a..1e311a6e98b 100644 --- a/mozilla/js2/src/js2op_literal.cpp +++ b/mozilla/js2/src/js2op_literal.cpp @@ -135,7 +135,7 @@ { uint16 argCount = BytecodeContainer::getShort(pc); pc += sizeof(uint16); - ArrayInstance *aInst = new ArrayInstance(meta->arrayClass->prototype, meta->arrayClass); + ArrayInstance *aInst = new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass); baseVal = OBJECT_TO_JS2VAL(aInst); for (uint16 i = 0; i < argCount; i++) { b = pop(); diff --git a/mozilla/js2/src/js2regexp.cpp b/mozilla/js2/src/js2regexp.cpp index 8958f8f8a04..4d2bdf081e8 100644 --- a/mozilla/js2/src/js2regexp.cpp +++ b/mozilla/js2/src/js2regexp.cpp @@ -142,7 +142,7 @@ namespace MetaData { REMatchState *match = REExecute(thisInst->mRegExp, str->begin(), index, toInt32(str->length()), meta->toBoolean(globalMultiline)); if (match) { - PrototypeInstance *A = new ArrayInstance(meta->arrayClass->prototype, meta->arrayClass); + PrototypeInstance *A = new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass); result = OBJECT_TO_JS2VAL(A); js2val matchStr = meta->engine->allocString(str->substr((uint32)match->startIndex, (uint32)match->endIndex - match->startIndex)); Multiname mname(&meta->world.identifiers[*meta->toString((long)0)], meta->publicNamespace); diff --git a/mozilla/js2/src/js2string.cpp b/mozilla/js2/src/js2string.cpp index 1edb105e5c1..166b16a93fa 100644 --- a/mozilla/js2/src/js2string.cpp +++ b/mozilla/js2/src/js2string.cpp @@ -170,7 +170,7 @@ static js2val String_match(JS2Metadata *meta, const js2val thisValue, js2val *ar return RegExp_exec(meta, regexp, &S, 1); } else { - PrototypeInstance *A = new ArrayInstance(meta->arrayClass->prototype, meta->arrayClass); + PrototypeInstance *A = new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass); int32 index = 0; int32 lastIndex = 0; while (true) { @@ -405,7 +405,7 @@ static js2val String_split(JS2Metadata *meta, const js2val thisValue, js2val *ar { const String *S = meta->toString(thisValue); - js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta->arrayClass->prototype, meta->arrayClass)); + js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass)); ArrayInstance *A = checked_cast(JS2VAL_TO_OBJECT(result)); uint32 lim; diff --git a/mozilla/js2/src/js2value.h b/mozilla/js2/src/js2value.h index 9ddfc6133ac..e077e85d06a 100644 --- a/mozilla/js2/src/js2value.h +++ b/mozilla/js2/src/js2value.h @@ -78,6 +78,8 @@ #define INT_TO_JS2VAL(i) (((js2val)(i) << 1) | JS2VAL_INT) #define JS2VAL_TO_INT(v) ((int32)(v) >> 1) #define INT_FITS_IN_JS2VAL(i) ((uint32)((i)+JS2VAL_INT_MAX) <= 2*JS2VAL_INT_MAX) +#define INT_FITS_IN_JSVAL(i) ((jsuint)((i)+JSVAL_INT_MAX) <= 2*JSVAL_INT_MAX) + #define LONG_FITS_IN_JS2VAL(x) (JSLL_CMP((x), >, -JS2VAL_INT_MAX) && JSLL_CMP(JS2VAL_INT_MAX, >, (x))) #define ULONG_FITS_IN_JS2VAL(x) (JSLL_CMP(JS2VAL_INT_MAX, >, (x)))