mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 04:45:45 +00:00
Restore enumeable, permanent, readonly single-char elements to string objects; fix propertyIsEnumerable to work with shared permanent proto-properties (167910, r=rogerl).
This commit is contained in:
parent
65f9649028
commit
d02561c5d2
@ -1123,7 +1123,6 @@ obj_hasOwnProperty(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
JSObject *obj2;
|
||||
JSProperty *prop;
|
||||
JSScopeProperty *sprop;
|
||||
JSBool sharedPermanent;
|
||||
|
||||
if (!JS_ValueToId(cx, argv[0], &id))
|
||||
return JS_FALSE;
|
||||
@ -1135,9 +1134,7 @@ obj_hasOwnProperty(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
*rval = JSVAL_TRUE;
|
||||
} else if (OBJ_IS_NATIVE(obj2)) {
|
||||
sprop = (JSScopeProperty *)prop;
|
||||
sharedPermanent =
|
||||
(~sprop->attrs & (JSPROP_SHARED | JSPROP_PERMANENT)) == 0;
|
||||
*rval = BOOLEAN_TO_JSVAL(sharedPermanent);
|
||||
*rval = BOOLEAN_TO_JSVAL(SPROP_IS_SHARED_PERMANENT(sprop));
|
||||
} else {
|
||||
*rval = JSVAL_FALSE;
|
||||
}
|
||||
@ -1176,14 +1173,27 @@ obj_propertyIsEnumerable(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
|
||||
return JS_FALSE;
|
||||
|
||||
/* XXX ECMA spec error compatible: return false unless hasOwnProperty. */
|
||||
if (prop && obj2 != obj) {
|
||||
/*
|
||||
* XXX ECMA spec error compatible: return false unless hasOwnProperty.
|
||||
* The ECMA spec really should be fixed so propertyIsEnumerable and the
|
||||
* for..in loop agree on whether prototype properties are enumerable,
|
||||
* obviously by fixing this method (not by breaking the for..in loop!).
|
||||
*
|
||||
* We check here for shared permanent prototype properties, which should
|
||||
* be treated as if they are local to obj. They are an implementation
|
||||
* technique used to satisfy ECMA requirements; users should not be able
|
||||
* to distinguish a shared permanent proto-property from a local one.
|
||||
*/
|
||||
if (prop &&
|
||||
obj2 != obj &&
|
||||
!(OBJ_IS_NATIVE(obj2) &&
|
||||
SPROP_IS_SHARED_PERMANENT((JSScopeProperty *)prop))) {
|
||||
OBJ_DROP_PROPERTY(cx, obj2, prop);
|
||||
*rval = JSVAL_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
ok = OBJ_GET_ATTRIBUTES(cx, obj, id, prop, &attrs);
|
||||
ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs);
|
||||
if (prop)
|
||||
OBJ_DROP_PROPERTY(cx, obj2, prop);
|
||||
if (ok)
|
||||
@ -2804,7 +2814,7 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
|
||||
if (prop) {
|
||||
if (OBJ_IS_NATIVE(proto)) {
|
||||
sprop = (JSScopeProperty *)prop;
|
||||
if ((~sprop->attrs & (JSPROP_SHARED | JSPROP_PERMANENT)) == 0)
|
||||
if (SPROP_IS_SHARED_PERMANENT(sprop))
|
||||
*rval = JSVAL_FALSE;
|
||||
}
|
||||
OBJ_DROP_PROPERTY(cx, proto, prop);
|
||||
|
@ -315,6 +315,10 @@ struct JSScopeProperty {
|
||||
JSMSG_GETTER_ONLY, NULL), JS_FALSE) \
|
||||
: SPROP_CALL_SETTER(cx, sprop, (sprop)->setter, obj, obj2, vp))
|
||||
|
||||
/* Macro for common expression to test for shared permanent attributes. */
|
||||
#define SPROP_IS_SHARED_PERMANENT(sprop) \
|
||||
((~(sprop)->attrs & (JSPROP_SHARED | JSPROP_PERMANENT)) == 0)
|
||||
|
||||
extern JSScope *
|
||||
js_GetMutableScope(JSContext *cx, JSObject *obj);
|
||||
|
||||
|
@ -502,7 +502,7 @@ static JSPropertySpec string_props[] = {
|
||||
static JSBool
|
||||
str_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
JSString *str, *str1;
|
||||
JSString *str;
|
||||
jsint slot;
|
||||
|
||||
if (!JSVAL_IS_INT(id))
|
||||
@ -511,22 +511,57 @@ str_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
slot = JSVAL_TO_INT(id);
|
||||
if (slot == STRING_LENGTH) {
|
||||
if (slot == STRING_LENGTH)
|
||||
*vp = INT_TO_JSVAL((jsint) JSSTRING_LENGTH(str));
|
||||
} else {
|
||||
/*
|
||||
* ECMA extension: if the property has not been set already (possibly
|
||||
* to a user-defined value), return as its value the character at the
|
||||
* given index. Don't use resolve, which penalizes all string method
|
||||
* calls and other property accesses. Let the property attributes be
|
||||
* the default, so the user can override, enumerate, etc. and get the
|
||||
* expected results.
|
||||
*/
|
||||
if (JSVAL_IS_VOID(*vp) && (size_t)slot < JSSTRING_LENGTH(str)) {
|
||||
str1 = js_NewDependentString(cx, str, (size_t)slot, 1, 0);
|
||||
if (!str1)
|
||||
return JS_FALSE;
|
||||
*vp = STRING_TO_JSVAL(str1);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#define STRING_ELEMENT_ATTRS (JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT)
|
||||
|
||||
static JSBool
|
||||
str_enumerate(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSString *str, *str1;
|
||||
size_t i, length;
|
||||
|
||||
str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
length = JSSTRING_LENGTH(str);
|
||||
for (i = 0; i < length; i++) {
|
||||
str1 = js_NewDependentString(cx, str, i, 1, 0);
|
||||
if (!str1)
|
||||
return JS_FALSE;
|
||||
if (!OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSVAL(i),
|
||||
STRING_TO_JSVAL(str1), NULL, NULL,
|
||||
STRING_ELEMENT_ATTRS, NULL)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
str_resolve(JSContext *cx, JSObject *obj, jsval id)
|
||||
{
|
||||
JSString *str, *str1;
|
||||
jsint slot;
|
||||
|
||||
if (!JSVAL_IS_INT(id))
|
||||
return JS_TRUE;
|
||||
|
||||
str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
slot = JSVAL_TO_INT(id);
|
||||
if ((size_t)slot < JSSTRING_LENGTH(str)) {
|
||||
str1 = js_NewDependentString(cx, str, (size_t)slot, 1, 0);
|
||||
if (!str1)
|
||||
return JS_FALSE;
|
||||
if (!OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSVAL(slot),
|
||||
STRING_TO_JSVAL(str1), NULL, NULL,
|
||||
STRING_ELEMENT_ATTRS, NULL)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
return JS_TRUE;
|
||||
@ -536,7 +571,7 @@ static JSClass string_class = {
|
||||
js_String_str,
|
||||
JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub, str_getProperty, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
|
||||
str_enumerate, str_resolve, JS_ConvertStub, JS_FinalizeStub,
|
||||
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user