Inherited non-configurable accessor properties mis-reported as own properties (637994, r=jwalden).

This commit is contained in:
Brendan Eich 2011-06-14 23:48:59 -07:00
parent a2fa4d23af
commit b2a9eace38
3 changed files with 49 additions and 34 deletions

View File

@ -1484,7 +1484,6 @@ js_HasOwnProperty(JSContext *cx, LookupPropOp lookup, JSObject *obj, jsid id,
if (*objp == obj)
return true;
Class *clasp = (*objp)->getClass();
JSObject *outer = NULL;
if (JSObjectOp op = (*objp)->getClass()->ext.outerObject) {
outer = op(cx, *objp);
@ -1492,30 +1491,8 @@ js_HasOwnProperty(JSContext *cx, LookupPropOp lookup, JSObject *obj, jsid id,
return false;
}
if (outer != *objp) {
if ((*objp)->isNative() && obj->getClass() == clasp) {
/*
* The combination of JSPROP_SHARED and JSPROP_PERMANENT in a
* delegated property makes that property appear to be direct in
* all delegating instances of the same native class. This hack
* avoids bloating every function instance with its own 'length'
* (AKA 'arity') property. But it must not extend across class
* boundaries, to avoid making hasOwnProperty lie (bug 320854).
*
* It's not really a hack, of course: a permanent property can't
* be deleted, and JSPROP_SHARED means "don't allocate a slot in
* any instance, prototype or delegating". Without a slot, and
* without the ability to remove and recreate (with differences)
* the property, there is no way to tell whether it is directly
* owned, or indirectly delegated.
*/
Shape *shape = reinterpret_cast<Shape *>(*propp);
if (shape->isSharedPermanent())
return true;
}
if (outer != *objp)
*propp = NULL;
}
return true;
}

View File

@ -284,10 +284,15 @@ NewXMLNamespace(JSContext *cx, JSLinearString *prefix, JSLinearString *uri, JSBo
obj = NewBuiltinClassInstanceXML(cx, &js_NamespaceClass);
if (!obj)
return JS_FALSE;
return NULL;
JS_ASSERT(JSVAL_IS_VOID(obj->getNamePrefixVal()));
JS_ASSERT(JSVAL_IS_VOID(obj->getNameURIVal()));
JS_ASSERT(JSVAL_IS_VOID(obj->getNamespaceDeclared()));
/* Per ECMA-357, 13.2.5, these properties must be "own". */
if (!JS_DefineProperties(cx, obj, namespace_props))
return NULL;
if (prefix)
obj->setNamePrefix(prefix);
if (uri)
@ -477,20 +482,26 @@ static JSFunctionSpec qname_methods[] = {
};
static void
InitXMLQName(JSObject *obj, JSLinearString *uri, JSLinearString *prefix,
static bool
InitXMLQName(JSContext *cx, JSObject *obj, JSLinearString *uri, JSLinearString *prefix,
JSLinearString *localName)
{
JS_ASSERT(obj->isQName());
JS_ASSERT(JSVAL_IS_VOID(obj->getNamePrefixVal()));
JS_ASSERT(JSVAL_IS_VOID(obj->getNameURIVal()));
JS_ASSERT(JSVAL_IS_VOID(obj->getQNameLocalNameVal()));
/* Per ECMA-357, 13.3.5, these properties must be "own". */
if (!JS_DefineProperties(cx, obj, qname_props))
return false;
if (uri)
obj->setNameURI(uri);
if (prefix)
obj->setNamePrefix(prefix);
if (localName)
obj->setQNameLocalName(localName);
return true;
}
static JSObject *
@ -500,7 +511,8 @@ NewXMLQName(JSContext *cx, JSLinearString *uri, JSLinearString *prefix,
JSObject *obj = NewBuiltinClassInstanceXML(cx, &js_QNameClass);
if (!obj)
return NULL;
InitXMLQName(obj, uri, prefix, localName);
if (!InitXMLQName(cx, obj, uri, prefix, localName))
return NULL;
METER(xml_stats.qname);
return obj;
}
@ -517,7 +529,8 @@ NewXMLAttributeName(JSContext *cx, JSLinearString *uri, JSLinearString *prefix,
if (!obj)
return NULL;
JS_ASSERT(obj->isQName());
InitXMLQName(obj, uri, prefix, localName);
if (!InitXMLQName(cx, obj, uri, prefix, localName))
return NULL;
METER(xml_stats.qname);
return obj;
}
@ -632,6 +645,11 @@ NamespaceHelper(JSContext *cx, JSObject *obj, intN argc, jsval *argv,
if (!obj)
return JS_FALSE;
}
/* Per ECMA-357, 13.2.5, these properties must be "own". */
if (!JS_DefineProperties(cx, obj, namespace_props))
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
METER(xml_stats.xmlnamespace);
@ -828,8 +846,7 @@ QNameHelper(JSContext *cx, JSObject *obj, intN argc, jsval *argv, jsval *rval)
}
out:
InitXMLQName(obj, uri, prefix, name);
return JS_TRUE;
return InitXMLQName(cx, obj, uri, prefix, name);
}
static JSBool
@ -7112,14 +7129,14 @@ JSObject *
js_InitNamespaceClass(JSContext *cx, JSObject *obj)
{
return js_InitClass(cx, obj, NULL, &js_NamespaceClass, Namespace, 2,
namespace_props, namespace_methods, NULL, NULL);
NULL, namespace_methods, NULL, NULL);
}
JSObject *
js_InitQNameClass(JSContext *cx, JSObject *obj)
{
return js_InitClass(cx, obj, NULL, &js_QNameClass, QName, 2,
qname_props, qname_methods, NULL, NULL);
NULL, qname_methods, NULL, NULL);
}
JSObject *
@ -7373,7 +7390,8 @@ js_GetAnyName(JSContext *cx, jsid *idp)
JS_ASSERT(!obj->getProto());
JSRuntime *rt = cx->runtime;
InitXMLQName(obj, rt->emptyString, rt->emptyString, rt->atomState.starAtom);
if (!InitXMLQName(cx, obj, rt->emptyString, rt->emptyString, rt->atomState.starAtom))
return false;
METER(xml_stats.qname);
v.setObject(*obj);

View File

@ -141,6 +141,26 @@ expectDescriptor(pd, expected);
/******************************************************************************/
var o2;
o = Object.create(Object.prototype, { x: {get: function () { return 12; } } });
pd = Object.getOwnPropertyDescriptor(o, "x");
expected =
{
set: undefined,
enumerable: false,
configurable: false
};
adjustDescriptorField(o, pd, expected, "get");
expectDescriptor(pd, expected);
o2 = Object.create(o);
assertEq(Object.getOwnPropertyDescriptor(o2, "x"), undefined);
/******************************************************************************/
o = {};
o.b = 12;