From 09b5f3debe8fa0ab3177faf70922444f2db62ca8 Mon Sep 17 00:00:00 2001 From: "rogerl%netscape.com" Date: Tue, 2 Oct 2001 01:15:12 +0000 Subject: [PATCH] Fixed for..in to descend prototype chain. Fixed binding for non-methods. git-svn-id: svn://10.0.0.236/trunk@104377 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/js2/src/js2execution.cpp | 57 ++++++++++++++++++++++++-------- mozilla/js2/src/js2runtime.cpp | 37 ++++++++++++--------- mozilla/js2/src/js2runtime.h | 1 + 3 files changed, 66 insertions(+), 29 deletions(-) diff --git a/mozilla/js2/src/js2execution.cpp b/mozilla/js2/src/js2execution.cpp index b5fffee220c..6f81b23c316 100644 --- a/mozilla/js2/src/js2execution.cpp +++ b/mozilla/js2/src/js2execution.cpp @@ -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(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: diff --git a/mozilla/js2/src/js2runtime.cpp b/mozilla/js2/src/js2runtime.cpp index d6137305a02..de1dee078e1 100644 --- a/mozilla/js2/src/js2runtime.cpp +++ b/mozilla/js2/src/js2runtime.cpp @@ -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)); diff --git a/mozilla/js2/src/js2runtime.h b/mozilla/js2/src/js2runtime.h index db4d0951b89..2a87802abdc 100644 --- a/mozilla/js2/src/js2runtime.h +++ b/mozilla/js2/src/js2runtime.h @@ -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;