Bug 911864 - Expose an API to copy a single property across compartments. r=jorendorff

This commit is contained in:
Bobby Holley 2013-11-01 15:31:56 +01:00
Родитель 4828e1811f
Коммит 28781ba0db
2 изменённых файлов: 59 добавлений и 16 удалений

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

@ -173,9 +173,23 @@ extern JS_FRIEND_API(void)
js_DumpChars(const jschar *s, size_t n); js_DumpChars(const jschar *s, size_t n);
#endif #endif
/*
* Copies all own properties from |obj| to |target|. |obj| must be a "native"
* object (that is to say, normal-ish - not an Array or a Proxy).
*
* On entry, |cx| must be in the compartment of |target|.
*/
extern JS_FRIEND_API(bool) extern JS_FRIEND_API(bool)
JS_CopyPropertiesFrom(JSContext *cx, JSObject *target, JSObject *obj); JS_CopyPropertiesFrom(JSContext *cx, JSObject *target, JSObject *obj);
/*
* Single-property version of the above. This function asserts that an |own|
* property of the given name exists on |obj|.
*/
extern JS_FRIEND_API(bool)
JS_CopyPropertyFrom(JSContext *cx, JS::HandleId id, JS::HandleObject target,
JS::HandleObject obj);
extern JS_FRIEND_API(bool) extern JS_FRIEND_API(bool)
JS_WrapPropertyDescriptor(JSContext *cx, JS::MutableHandle<JSPropertyDescriptor> desc); JS_WrapPropertyDescriptor(JSContext *cx, JS::MutableHandle<JSPropertyDescriptor> desc);

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

@ -1756,11 +1756,54 @@ JSObject::deleteByValue(JSContext *cx, HandleObject obj, const Value &property,
return deleteProperty(cx, obj, propname, succeeded); return deleteProperty(cx, obj, propname, succeeded);
} }
static bool
CopyProperty(JSContext *cx, HandleObject target, HandleObject obj,
HandleShape shape)
{
// |shape| and |obj| are generally not same-compartment with |target| and
// |cx| here.
assertSameCompartment(cx, target);
unsigned attrs = shape->attributes();
PropertyOp getter = shape->getter();
StrictPropertyOp setter = shape->setter();
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
if ((attrs & JSPROP_GETTER) && !cx->compartment()->wrap(cx, &getter))
return false;
if ((attrs & JSPROP_SETTER) && !cx->compartment()->wrap(cx, &setter))
return false;
RootedValue v(cx, shape->hasSlot() ? obj->getSlot(shape->slot())
: UndefinedValue());
if (!cx->compartment()->wrap(cx, &v))
return false;
RootedId id(cx, shape->propid());
return JSObject::defineGeneric(cx, target, id, v, getter,
setter, attrs);
}
JS_FRIEND_API(bool)
JS_CopyPropertyFrom(JSContext *cx, HandleId id, HandleObject target,
HandleObject obj)
{
assertSameCompartment(cx, target);
MOZ_ASSERT(obj->isNative());
RootedObject obj2(cx);
RootedShape shape(cx);
{
AutoCompartment ac(cx, obj);
if (!JSObject::lookupGeneric(cx, obj, id, &obj2, &shape))
return false;
}
MOZ_ASSERT(shape && obj == obj2);
return CopyProperty(cx, target, obj, shape);
}
JS_FRIEND_API(bool) JS_FRIEND_API(bool)
JS_CopyPropertiesFrom(JSContext *cx, JSObject *targetArg, JSObject *objArg) JS_CopyPropertiesFrom(JSContext *cx, JSObject *targetArg, JSObject *objArg)
{ {
RootedObject target(cx, targetArg); RootedObject target(cx, targetArg);
RootedObject obj(cx, objArg); RootedObject obj(cx, objArg);
assertSameCompartment(cx, target);
// If we're not native, then we cannot copy properties. // If we're not native, then we cannot copy properties.
JS_ASSERT(target->isNative() == obj->isNative()); JS_ASSERT(target->isNative() == obj->isNative());
@ -1773,25 +1816,11 @@ JS_CopyPropertiesFrom(JSContext *cx, JSObject *targetArg, JSObject *objArg)
return false; return false;
} }
RootedShape shape(cx);
RootedValue v(cx);
RootedId id(cx);
size_t n = shapes.length(); size_t n = shapes.length();
RootedShape shape(cx);
while (n > 0) { while (n > 0) {
shape = shapes[--n]; shape = shapes[--n];
unsigned attrs = shape->attributes(); if (!CopyProperty(cx, target, obj, shape))
PropertyOp getter = shape->getter();
StrictPropertyOp setter = shape->setter();
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
if ((attrs & JSPROP_GETTER) && !cx->compartment()->wrap(cx, &getter))
return false;
if ((attrs & JSPROP_SETTER) && !cx->compartment()->wrap(cx, &setter))
return false;
v = shape->hasSlot() ? obj->getSlot(shape->slot()) : UndefinedValue();
if (!cx->compartment()->wrap(cx, &v))
return false;
id = shape->propid();
if (!JSObject::defineGeneric(cx, target, id, v, getter, setter, attrs))
return false; return false;
} }
return true; return true;