зеркало из https://github.com/mozilla/gecko-dev.git
Fixed for..in to descend prototype chain. Fixed binding for non-methods.
This commit is contained in:
Родитель
d3beb86682
Коммит
182c6da18e
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче