From 09c78e6f8f9de5364181caa71722d5b24ab77ae6 Mon Sep 17 00:00:00 2001 From: "rogerl%netscape.com" Date: Thu, 24 Oct 2002 23:12:24 +0000 Subject: [PATCH] Number class. git-svn-id: svn://10.0.0.236/trunk@132471 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/js2/src/js2engine.cpp | 4 ++- mozilla/js2/src/js2engine.h | 1 + mozilla/js2/src/js2math.cpp | 40 ++++++++++++------------- mozilla/js2/src/js2metadata.cpp | 53 ++++++++++++++++++++++++++++----- mozilla/js2/src/js2metadata.h | 9 ++++++ mozilla/js2/src/js2regexp.cpp | 4 +-- mozilla/js2/src/js2string.cpp | 18 +++++------ 7 files changed, 90 insertions(+), 39 deletions(-) diff --git a/mozilla/js2/src/js2engine.cpp b/mozilla/js2/src/js2engine.cpp index 9ba204c85a0..5913c9eafb7 100644 --- a/mozilla/js2/src/js2engine.cpp +++ b/mozilla/js2/src/js2engine.cpp @@ -355,7 +355,8 @@ namespace MetaData { Empty_StringAtom(&world.identifiers[""]), Dollar_StringAtom(&world.identifiers["$"]), INIT_STRINGATOM(prototype), - INIT_STRINGATOM(length) + INIT_STRINGATOM(length), + INIT_STRINGATOM(toString) { for (int i = 0; i < 256; i++) float64Table[i] = NULL; @@ -605,6 +606,7 @@ namespace MetaData { JS2Object::mark(Empty_StringAtom); JS2Object::mark(Dollar_StringAtom); JS2Object::mark(length_StringAtom); + JS2Object::mark(toString_StringAtom); } void JS2Engine::pushHandler(uint8 *pc) diff --git a/mozilla/js2/src/js2engine.h b/mozilla/js2/src/js2engine.h index 35baa551f90..43a15c658fb 100644 --- a/mozilla/js2/src/js2engine.h +++ b/mozilla/js2/src/js2engine.h @@ -224,6 +224,7 @@ public: const String *Dollar_StringAtom; const String *prototype_StringAtom; const String *length_StringAtom; + const String *toString_StringAtom; // The activation stack, when it's empty and a return is executed, the // interpreter quits diff --git a/mozilla/js2/src/js2math.cpp b/mozilla/js2/src/js2math.cpp index 1ac3b6656ee..45334238618 100644 --- a/mozilla/js2/src/js2math.cpp +++ b/mozilla/js2/src/js2math.cpp @@ -93,73 +93,73 @@ static js2val Math_abs(JS2Metadata *meta, const js2val /*thisValue*/, js2val *ar if (argc == 0) return meta->engine->nanValue; else - return meta->engine->allocNumber(fd::fabs(meta->engine->meta->toFloat64(argv[0]))); + return meta->engine->allocNumber(fd::fabs(meta->toFloat64(argv[0]))); } static js2val Math_acos(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc) { if (argc == 0) return meta->engine->nanValue; - return meta->engine->allocNumber(fd::acos(meta->engine->meta->toFloat64(argv[0]))); + return meta->engine->allocNumber(fd::acos(meta->toFloat64(argv[0]))); } static js2val Math_asin(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc) { if (argc == 0) return meta->engine->nanValue; - return meta->engine->allocNumber(fd::asin(meta->engine->meta->toFloat64(argv[0]))); + return meta->engine->allocNumber(fd::asin(meta->toFloat64(argv[0]))); } static js2val Math_atan(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc) { if (argc == 0) return meta->engine->nanValue; - return meta->engine->allocNumber(fd::atan(meta->engine->meta->toFloat64(argv[0]))); + return meta->engine->allocNumber(fd::atan(meta->toFloat64(argv[0]))); } static js2val Math_atan2(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc) { if (argc <= 1) return meta->engine->nanValue; - float64 y = meta->engine->meta->toFloat64(argv[0]); - float64 x = meta->engine->meta->toFloat64(argv[1]); + float64 y = meta->toFloat64(argv[0]); + float64 x = meta->toFloat64(argv[1]); return meta->engine->allocNumber(fd::atan2(y, x)); } static js2val Math_ceil(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc) { if (argc == 0) return meta->engine->nanValue; - return meta->engine->allocNumber(fd::ceil(meta->engine->meta->toFloat64(argv[0]))); + return meta->engine->allocNumber(fd::ceil(meta->toFloat64(argv[0]))); } static js2val Math_cos(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc) { if (argc == 0) return meta->engine->nanValue; - return meta->engine->allocNumber(fd::cos(meta->engine->meta->toFloat64(argv[0]))); + return meta->engine->allocNumber(fd::cos(meta->toFloat64(argv[0]))); } static js2val Math_exp(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc) { if (argc == 0) return meta->engine->nanValue; - return meta->engine->allocNumber(fd::exp(meta->engine->meta->toFloat64(argv[0]))); + return meta->engine->allocNumber(fd::exp(meta->toFloat64(argv[0]))); } static js2val Math_floor(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc) { if (argc == 0) return meta->engine->nanValue; else - return meta->engine->allocNumber(fd::floor(meta->engine->meta->toFloat64(argv[0]))); + return meta->engine->allocNumber(fd::floor(meta->toFloat64(argv[0]))); } static js2val Math_log(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc) { if (argc == 0) return meta->engine->nanValue; - return meta->engine->allocNumber(fd::log(meta->engine->meta->toFloat64(argv[0]))); + return meta->engine->allocNumber(fd::log(meta->toFloat64(argv[0]))); } static js2val Math_max(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc) { if (argc == 0) return meta->engine->negInfValue; - float64 result = meta->engine->meta->toFloat64(argv[0]); + float64 result = meta->toFloat64(argv[0]); if (JSDOUBLE_IS_NaN(result)) return meta->engine->nanValue; for (uint32 i = 1; i < argc; ++i) { - float64 arg = meta->engine->meta->toFloat64(argv[i]); + float64 arg = meta->toFloat64(argv[i]); if (JSDOUBLE_IS_NaN(arg)) return meta->engine->nanValue; if (arg > result) result = arg; @@ -170,10 +170,10 @@ static js2val Math_min(JS2Metadata *meta, const js2val /*thisValue*/, js2val *ar { if (argc == 0) return meta->engine->posInfValue; - float64 result = meta->engine->meta->toFloat64(argv[0]); + float64 result = meta->toFloat64(argv[0]); if (JSDOUBLE_IS_NaN(result)) return meta->engine->nanValue; for (uint32 i = 1; i < argc; ++i) { - float64 arg = meta->engine->meta->toFloat64(argv[i]); + float64 arg = meta->toFloat64(argv[i]); if (JSDOUBLE_IS_NaN(arg)) return meta->engine->nanValue; if ((arg < result) || (JSDOUBLE_IS_POSZERO(result) && JSDOUBLE_IS_NEGZERO(arg))) result = arg; @@ -184,7 +184,7 @@ static js2val Math_pow(JS2Metadata *meta, const js2val /*thisValue*/, js2val *ar { if (argc < 1) return meta->engine->nanValue; - return meta->engine->allocNumber(fd::pow(meta->engine->meta->toFloat64(argv[0]), meta->engine->meta->toFloat64(argv[1]))); + return meta->engine->allocNumber(fd::pow(meta->toFloat64(argv[0]), meta->toFloat64(argv[1]))); } /* @@ -266,26 +266,26 @@ static js2val Math_round(JS2Metadata *meta, const js2val /*thisValue*/, js2val * { if (argc == 0) return meta->engine->nanValue; - float64 x = meta->engine->meta->toFloat64(argv[0]); + float64 x = meta->toFloat64(argv[0]); return meta->engine->allocNumber( fd::copysign( fd::floor(x + 0.5), x ) ); } static js2val Math_sin(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc) { if (argc == 0) return meta->engine->nanValue; - return meta->engine->allocNumber(fd::sin(meta->engine->meta->toFloat64(argv[0]))); + return meta->engine->allocNumber(fd::sin(meta->toFloat64(argv[0]))); } static js2val Math_sqrt(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc) { if (argc == 0) return meta->engine->nanValue; - return meta->engine->allocNumber(fd::sqrt(meta->engine->meta->toFloat64(argv[0]))); + return meta->engine->allocNumber(fd::sqrt(meta->toFloat64(argv[0]))); } static js2val Math_tan(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc) { if (argc == 0) return meta->engine->nanValue; - return meta->engine->allocNumber(fd::tan(meta->engine->meta->toFloat64(argv[0]))); + return meta->engine->allocNumber(fd::tan(meta->toFloat64(argv[0]))); } diff --git a/mozilla/js2/src/js2metadata.cpp b/mozilla/js2/src/js2metadata.cpp index fec633244b5..b128b2e5bfa 100644 --- a/mozilla/js2/src/js2metadata.cpp +++ b/mozilla/js2/src/js2metadata.cpp @@ -2594,17 +2594,38 @@ doUnary: return result; } - js2val Object_toString(JS2Metadata *meta, const js2val thisValue, js2val argv[], uint32 argc) + static js2val Object_toString(JS2Metadata *meta, const js2val thisValue, js2val argv[], uint32 argc) { return STRING_TO_JS2VAL(meta->engine->object_StringAtom); } - js2val GlobalObject_isNaN(JS2Metadata *meta, const js2val thisValue, js2val argv[], uint32 argc) + static js2val GlobalObject_isNaN(JS2Metadata *meta, const js2val thisValue, js2val argv[], uint32 argc) { float64 d = meta->toFloat64(argv[0]); return BOOLEAN_TO_JS2VAL(JSDOUBLE_IS_NaN(d)); } + static js2val Number_Constructor(JS2Metadata *meta, const js2val thisValue, js2val argv[], uint32 argc) + { + js2val thatValue = OBJECT_TO_JS2VAL(new NumberInstance(meta->numberClass)); + NumberInstance *numInst = checked_cast(JS2VAL_TO_OBJECT(thatValue)); + + if (argc > 0) + numInst->mValue = meta->toFloat64(argv[0]); + else + numInst->mValue = 0.0; + return thatValue; + } + + static js2val Number_toString(JS2Metadata *meta, const js2val thisValue, js2val * /*argv*/, uint32 /*argc*/) + { + if (meta->objectType(thisValue) != meta->numberClass) + meta->reportError(Exception::typeError, "Number.toString called on something other than a number thing", meta->engine->errorPos()); + NumberInstance *numInst = checked_cast(JS2VAL_TO_OBJECT(thisValue)); + return meta->engine->allocString(numberToString(&numInst->mValue)); + } + + void JS2Metadata::addGlobalObjectFunction(char *name, NativeCode *code) { FixedInstance *fInst = new FixedInstance(functionClass); @@ -2645,6 +2666,8 @@ doUnary: // A 'forbidden' member, used to mark hidden bindings forbiddenMember = new StaticMember(Member::Forbidden); + +/*** ECMA 3 Global Object ***/ // Non-function properties of the global object : 'undefined', 'NaN' and 'Infinity' // XXX Or are these fixed properties? writeDynamicProperty(glob, new Multiname(engine->undefined_StringAtom, publicNamespace), true, JS2VAL_UNDEFINED, RunPhase); @@ -2654,24 +2677,28 @@ doUnary: addGlobalObjectFunction("isNaN", GlobalObject_isNaN); +/*** ECMA 3 Object Class ***/ // Function properties of the Object prototype object objectClass->prototype = new PrototypeInstance(NULL, objectClass); // XXX Or make this a static class member? FixedInstance *fInst = new FixedInstance(functionClass); fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_VOID, true), Object_toString); - writeDynamicProperty(objectClass->prototype, new Multiname(&world.identifiers["toString"], publicNamespace), true, OBJECT_TO_JS2VAL(fInst), RunPhase); + writeDynamicProperty(objectClass->prototype, new Multiname(engine->toString_StringAtom, publicNamespace), true, OBJECT_TO_JS2VAL(fInst), RunPhase); + // needed for class instance variables... NamespaceList publicNamespaceList; publicNamespaceList.push_back(publicNamespace); Variable *v; InstanceMember *m; +/*** ECMA 3 Date Class ***/ MAKEBUILTINCLASS(dateClass, objectClass, true, true, true, &world.identifiers["Date"]); v = new Variable(classClass, OBJECT_TO_JS2VAL(dateClass), true); defineStaticMember(&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"]); v = new Variable(classClass, OBJECT_TO_JS2VAL(regexpClass), true); defineStaticMember(&env, &world.identifiers["RegExp"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); @@ -2687,20 +2714,31 @@ doUnary: m = new InstanceVariable(objectClass, false, false, regexpClass->slotCount++); defineInstanceMember(regexpClass, &cxt, &world.identifiers["multiline"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, m, 0); +/*** ECMA 3 String Class ***/ v = new Variable(classClass, OBJECT_TO_JS2VAL(stringClass), true); defineStaticMember(&env, &world.identifiers["String"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); -// stringClass->prototype = new PrototypeInstance(NULL, stringClass); initStringObject(this); +/*** ECMA 3 Number Class ***/ + v = new Variable(classClass, OBJECT_TO_JS2VAL(numberClass), true); + defineStaticMember(&env, &world.identifiers["Number"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + numberClass->construct = Number_Constructor; + fInst = new FixedInstance(functionClass); + fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_VOID, true), Number_toString); + m = new InstanceMethod(fInst); + defineInstanceMember(numberClass, &cxt, &world.identifiers["toString"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, m, 0); + + +/*** ECMA 3 Math Class ***/ MAKEBUILTINCLASS(mathClass, objectClass, true, true, true, &world.identifiers["Math"]); v = new Variable(classClass, OBJECT_TO_JS2VAL(mathClass), true); defineStaticMember(&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"]); v = new Variable(classClass, OBJECT_TO_JS2VAL(arrayClass), true); defineStaticMember(&env, &world.identifiers["Array"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); - // dateClass->prototype = new PrototypeInstance(NULL, dateClass); initArrayObject(this); @@ -2994,7 +3032,8 @@ readClassProperty: if ((ib == NULL) && isDynamicInstance) return readDynamicProperty(JS2VAL_TO_OBJECT(containerVal), multiname, lookupKind, phase, rval); else { - // XXX Spec. would have us passing a primitive here ??? + // 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); } } @@ -3561,7 +3600,7 @@ deleteClassProperty: // if not available or result is not primitive then try property 'valueOf' // if that's not available or returns a non primitive, throw a TypeError - Multiname mn(&world.identifiers["toString"], publicNamespace); + Multiname mn(engine->toString_StringAtom, publicNamespace); LookupKind lookup(false, NULL); js2val result; if (readProperty(x, &mn, &lookup, RunPhase, &result)) { diff --git a/mozilla/js2/src/js2metadata.h b/mozilla/js2/src/js2metadata.h index 1cb5639642c..8d503c27a49 100644 --- a/mozilla/js2/src/js2metadata.h +++ b/mozilla/js2/src/js2metadata.h @@ -560,6 +560,15 @@ public: virtual void markChildren() { if (mValue) JS2Object::mark(mValue); } }; +// Number instances are fixed (not dynamic? XXX) instances created by the Number class, they have an extra field +// that contains the float64 data +class NumberInstance : public FixedInstance { +public: + NumberInstance(JS2Class *type) : FixedInstance(type), mValue(NULL) { } + + float64 mValue; +}; + // Array instances are dynamic instances created by the Array class, they // maintain the value of the 'length' property when 'indexable' elements // are added. diff --git a/mozilla/js2/src/js2regexp.cpp b/mozilla/js2/src/js2regexp.cpp index 448dc2abb82..565731e1d43 100644 --- a/mozilla/js2/src/js2regexp.cpp +++ b/mozilla/js2/src/js2regexp.cpp @@ -135,12 +135,12 @@ namespace MetaData { if (argc > 0) { int32 index = 0; - const String *str = meta->engine->meta->toString(argv[0]); + const String *str = meta->toString(argv[0]); js2val globalMultiline = thisInst->getMultiline(meta); if (thisInst->getGlobal(meta)) { js2val lastIndex = thisInst->getLastIndex(meta); - index = meta->engine->meta->toInteger(lastIndex); + index = meta->toInteger(lastIndex); } REMatchState *match = REExecute(thisInst->mRegExp, str->begin(), index, toInt32(str->length()), meta->toBoolean(globalMultiline)); diff --git a/mozilla/js2/src/js2string.cpp b/mozilla/js2/src/js2string.cpp index c55a36e9cfc..f90f0c822c5 100644 --- a/mozilla/js2/src/js2string.cpp +++ b/mozilla/js2/src/js2string.cpp @@ -66,7 +66,7 @@ js2val String_Constructor(JS2Metadata *meta, const js2val /*thisValue*/, js2val StringInstance *strInst = checked_cast(JS2VAL_TO_OBJECT(thatValue)); if (argc > 0) - strInst->mValue = meta->engine->allocStringPtr(meta->engine->meta->toString(argv[0])); + strInst->mValue = meta->engine->allocStringPtr(meta->toString(argv[0])); else strInst->mValue = meta->engine->allocStringPtr(""); return thatValue; @@ -110,7 +110,7 @@ static js2val String_valueOf(JS2Metadata *meta, const js2val thisValue, js2val * */ static js2val String_search(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc) { - js2val S = STRING_TO_JS2VAL(meta->engine->meta->toString(thisValue)); + js2val S = STRING_TO_JS2VAL(meta->toString(thisValue)); js2val regexp = argv[0]; @@ -145,7 +145,7 @@ static js2val String_search(JS2Metadata *meta, const js2val thisValue, js2val *a static js2val String_match(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc) { - js2val S = STRING_TO_JS2VAL(meta->engine->meta->toString(thisValue)); + js2val S = STRING_TO_JS2VAL(meta->toString(thisValue)); js2val regexp = argv[0]; if ((argc == 0) || (meta->objectType(thisValue) != meta->regexpClass)) { @@ -255,14 +255,14 @@ static const String interpretDollar(JS2Metadata *meta, const String *replaceStr, static js2val String_replace(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc) { - const String *S = meta->engine->meta->toString(thisValue); + const String *S = meta->toString(thisValue); js2val searchValue; js2val replaceValue; if (argc > 0) searchValue = argv[0]; if (argc > 1) replaceValue = argv[1]; - const String *replaceStr = meta->engine->meta->toString(replaceValue); + const String *replaceStr = meta->toString(replaceValue); if (meta->objectType(searchValue) != meta->regexpClass) { RegExpInstance *reInst = checked_cast(JS2VAL_TO_OBJECT(searchValue)); @@ -308,7 +308,7 @@ static js2val String_replace(JS2Metadata *meta, const js2val thisValue, js2val * return meta->engine->allocString(newString); } else { - const String *searchStr = meta->engine->meta->toString(searchValue); + const String *searchStr = meta->toString(searchValue); REMatchState match; uint32 pos = S->find(*searchStr, 0); if (pos == String::npos) @@ -392,7 +392,7 @@ static void regexpSplitMatch(JS2Metadata *meta, const String *S, uint32 q, RESta static js2val String_split(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc) { - const String *S = meta->engine->meta->toString(thisValue); + const String *S = meta->toString(thisValue); js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta->arrayClass)); ArrayInstance *A = checked_cast(JS2VAL_TO_OBJECT(result)); @@ -414,7 +414,7 @@ static js2val String_split(JS2Metadata *meta, const js2val thisValue, js2val *ar if (meta->objectType(separatorV) == meta->regexpClass) RE = (checked_cast(JS2VAL_TO_OBJECT(separatorV)))->mRegExp; else - R = meta->engine->meta->toString(separatorV); + R = meta->toString(separatorV); if (lim == 0) return result; @@ -486,7 +486,7 @@ step11: static js2val String_charAt(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc) { - const String *str = meta->engine->meta->toString(thisValue); + const String *str = meta->toString(thisValue); uint32 pos = 0; if (argc > 0)