Fixed for..in to descend prototype chain. Fixed binding for non-methods.

This commit is contained in:
rogerl%netscape.com 2001-10-02 01:15:12 +00:00
Родитель d3beb86682
Коммит 182c6da18e
3 изменённых файлов: 66 добавлений и 29 удалений

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

@ -868,7 +868,7 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
const String &name = *mCurModule->getString(index);
JSObject *parent = mScopeChain->getNameValue(this, name, CURRENT_ATTR);
JSValue result = topValue();
if (result.isFunction() && result.function->isMethod()) {
if (result.isFunction()) {
popValue();
if (result.function->isConstructor())
// A constructor has to be called with a NULL 'this' in order to prompt it
@ -879,6 +879,19 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
}
}
break;
case SetNameOp:
{
uint32 index = *((uint32 *)pc);
pc += sizeof(uint32);
const String &name = *mCurModule->getString(index);
JSValue v = topValue();
if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) {
popValue();
pushValue(JSValue(v.function->getFunction()));
}
mScopeChain->setNameValue(this, name, CURRENT_ATTR);
}
break;
case GetTypeOfNameOp:
{
uint32 index = *((uint32 *)pc);
@ -891,14 +904,6 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
pushValue(kUndefinedValue);
}
break;
case SetNameOp:
{
uint32 index = *((uint32 *)pc);
pc += sizeof(uint32);
const String &name = *mCurModule->getString(index);
mScopeChain->setNameValue(this, name, CURRENT_ATTR);
}
break;
case GetElementOp:
{
uint32 dimCount = *((uint16 *)pc);
@ -969,6 +974,9 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
if (target) {
JSValue v = popValue(); // need to have this sitting right above the base value
if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) {
v = JSValue(v.function->getFunction());
}
insertValue(v, mStackTop - dimCount);
JSValue result;
@ -993,6 +1001,9 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
if (dimCount != 1)
reportError(Exception::typeError, "too many indices");
JSValue v = popValue();
if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) {
v = JSValue(v.function->getFunction());
}
JSValue index = popValue();
popValue(); // discard base
const String *name = index.toString(this).string;
@ -1065,7 +1076,7 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
// if the result is a method of some kind, bind
// the base object to it
JSValue result = topValue();
if (result.isFunction() && result.function->isMethod()) {
if (result.isFunction()) {
popValue();
if (result.function->isConstructor())
// A constructor has to be called with a NULL 'this' in order to prompt it
@ -1104,6 +1115,9 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
case SetPropertyOp:
{
JSValue v = popValue();
if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) {
v = JSValue(v.function->getFunction());
}
JSValue base = popValue();
JSObject *obj = NULL;
if (!base.isObject() && !base.isType())
@ -1307,7 +1321,11 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
{
uint32 index = *((uint32 *)pc);
pc += sizeof(uint32);
mLocals[index] = topValue();
JSValue v = topValue();
if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) {
v = JSValue(v.function->getFunction());
}
mLocals[index] = v;
}
break;
case GetClosureVarOp:
@ -1321,6 +1339,10 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
break;
case SetClosureVarOp:
{
JSValue v = topValue();
if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) {
v = JSValue(v.function->getFunction());
}
uint32 depth = *((uint32 *)pc);
pc += sizeof(uint32);
uint32 index = *((uint32 *)pc);
@ -1346,9 +1368,13 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
break;
case SetArgOp:
{
JSValue v = topValue();
if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) {
v = JSValue(v.function->getFunction());
}
uint32 index = *((uint32 *)pc);
pc += sizeof(uint32);
mArgumentBase[index] = topValue();
mArgumentBase[index] = v;
}
break;
case GetMethodOp:
@ -1381,6 +1407,9 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
case SetFieldOp:
{
JSValue v = popValue();
if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) {
v = JSValue(v.function->getFunction());
}
JSValue base = popValue();
ASSERT(dynamic_cast<JSInstance *>(base.object));
uint32 index = *((uint32 *)pc);
@ -1875,7 +1904,7 @@ static JSValue compareEqual(Context *cx, JSValue r1, JSValue r2)
else {
if (r1.isUndefined())
return kTrueValue;
if (r1.isNull() || r2.isNull()) // because null->getType() == Object_Type
if (r1.isNull())
return kTrueValue;
if (r1.isObject() && r2.isObject()) // because new Boolean()->getType() == Boolean_Type
return JSValue(r1.object == r2.object);
@ -2401,7 +2430,7 @@ JSType *JSValue::getType() const {
case string_tag: return (JSType *)String_Type;
case object_tag: return object->getType();
case undefined_tag: return Void_Type;
case null_tag: return Object_Type;
case null_tag: return Null_Type;
case function_tag: return Function_Type;
case type_tag: return Type_Type;
default:

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

@ -75,6 +75,7 @@ JSStringType *String_Type;
JSType *Boolean_Type;
JSType *Type_Type;
JSType *Void_Type;
JSType *Null_Type;
JSType *Unit_Type;
JSType *Attribute_Type;
JSType *NamedArgument_Type;
@ -1733,8 +1734,12 @@ static JSValue Object_forin(Context *cx, const JSValue& thisValue, JSValue * /*a
IteratorDongle *itDude = new IteratorDongle();
itDude->obj = obj;
itDude->it = obj->mProperties.begin();
if (itDude->it == itDude->obj->mProperties.end())
return kNullValue;
while (itDude->it == itDude->obj->mProperties.end()) {
itDude->obj = itDude->obj->mPrototype;
if (itDude->obj == NULL)
return kNullValue;
itDude->it = itDude->obj->mProperties.begin();
}
JSValue v(&PROPERTY_NAME(itDude->it));
iteratorObject->setProperty(cx, cx->mWorld.identifiers["value"], 0, v);
@ -1751,14 +1756,15 @@ static JSValue Object_next(Context *cx, const JSValue& /*thisValue*/, JSValue *a
IteratorDongle *itDude = (IteratorDongle *)(iteratorObject->mPrivate);
itDude->it++;
if (itDude->it == itDude->obj->mProperties.end())
return kNullValue;
else {
JSValue v(&PROPERTY_NAME(itDude->it));
iteratorObject->setProperty(cx, cx->mWorld.identifiers["value"], 0, v);
return iteratorValue;
}
while (itDude->it == itDude->obj->mProperties.end()) {
itDude->obj = itDude->obj->mPrototype;
if (itDude->obj == NULL)
return kNullValue;
itDude->it = itDude->obj->mProperties.begin();
}
JSValue v(&PROPERTY_NAME(itDude->it));
iteratorObject->setProperty(cx, cx->mWorld.identifiers["value"], 0, v);
return iteratorValue;
}
static JSValue Object_done(Context *, const JSValue& /*thisValue*/, JSValue * /*argv*/, uint32 /*argc*/)
@ -1880,8 +1886,7 @@ static JSValue Number_Constructor(Context *cx, const JSValue& thisValue, JSValue
static JSValue Number_toString(Context *cx, const JSValue& thisValue, JSValue * /*argv*/, uint32 /*argc*/)
{
ASSERT(thisValue.isObject());
if (thisValue.getType() != Number_Type)
if (!thisValue.isObject() || (thisValue.getType() != Number_Type))
cx->reportError(Exception::typeError, "Number.toString called on something other than a Number object");
JSObject *thisObj = thisValue.object;
return JSValue(numberToString(*((float64 *)(thisObj->mPrivate))));
@ -1889,8 +1894,7 @@ static JSValue Number_toString(Context *cx, const JSValue& thisValue, JSValue *
static JSValue Number_valueOf(Context *cx, const JSValue& thisValue, JSValue * /*argv*/, uint32 /*argc*/)
{
ASSERT(thisValue.isObject());
if (thisValue.getType() != Number_Type)
if (!thisValue.isObject() || (thisValue.getType() != Number_Type))
cx->reportError(Exception::typeError, "Number.valueOf called on something other than a Number object");
JSObject *thisObj = thisValue.object;
return JSValue(*((float64 *)(thisObj->mPrivate)));
@ -2193,11 +2197,12 @@ void Context::initBuiltins()
{ "String", String_Constructor, &kNullValue },
{ "Array", Array_Constructor, &kNullValue },
{ "Boolean", Boolean_Constructor, &kFalseValue },
{ "Void", NULL, &kNullValue },
{ "Void", NULL, &kUndefinedValue },
{ "Unit", NULL, &kNullValue },
{ "Attribute", NULL, &kNullValue },
{ "NamedArgument", NULL, &kNullValue },
{ "Date", Date_Constructor, &kPositiveZero },
{ "Null", NULL, &kNullValue },
};
Object_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[0].name)], NULL);
@ -2233,6 +2238,7 @@ void Context::initBuiltins()
Attribute_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[10].name)], Object_Type);
NamedArgument_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[11].name)], Object_Type);
Date_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[12].name)], Object_Type);
Null_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[13].name)], Object_Type);
String_Type->defineVariable(this, FromCharCode_StringAtom, NULL, String_Type, JSValue(new JSFunction(this, String_fromCharCode, String_Type)));
@ -2290,6 +2296,7 @@ void Context::initBuiltins()
initClass(Attribute_Type, &builtInClasses[10], NULL);
initClass(NamedArgument_Type, &builtInClasses[11], NULL);
initClass(Date_Type, &builtInClasses[12], getDateProtos() );
initClass(Null_Type, &builtInClasses[13], NULL);
Type_Type->defineUnaryOperator(Index, new JSFunction(this, arrayMaker, Type_Type));

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

@ -111,6 +111,7 @@ static const double two31 = 2147483648.0;
// has this type).
extern JSType *Boolean_Type;
extern JSType *Void_Type;
extern JSType *Null_Type;
extern JSArrayType *Array_Type;
extern JSType *Unit_Type;
extern JSType *Function_Type;