This commit is contained in:
rogerl%netscape.com 2002-10-24 23:12:24 +00:00
Родитель 96d61b1511
Коммит 2f51deeff9
7 изменённых файлов: 90 добавлений и 39 удалений

Просмотреть файл

@ -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)

Просмотреть файл

@ -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

Просмотреть файл

@ -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])));
}

Просмотреть файл

@ -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<NumberInstance *>(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<NumberInstance *>(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)) {

Просмотреть файл

@ -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.

Просмотреть файл

@ -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));

Просмотреть файл

@ -66,7 +66,7 @@ js2val String_Constructor(JS2Metadata *meta, const js2val /*thisValue*/, js2val
StringInstance *strInst = checked_cast<StringInstance *>(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<RegExpInstance *>(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<ArrayInstance *>(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<RegExpInstance *>(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)