Bug 1134970 part 2. Add JS friend API to quickly copy properties from one object to another if the objects are similar enough. r=bhackett,waldo

This commit is contained in:
Boris Zbarsky 2015-02-24 16:04:22 -05:00
parent 2411ea5abb
commit 8e884d1246
2 changed files with 70 additions and 0 deletions

View File

@ -151,6 +151,24 @@ extern JS_FRIEND_API(JSObject *)
JS_CloneObject(JSContext *cx, JS::HandleObject obj, JS::HandleObject proto,
JS::HandleObject parent);
/*
* Copy the own properties of src to dst in a fast way. src and dst must both
* be native and must be in the compartment of cx. They must have the same
* class, the same parent, and the same prototype. Class reserved slots will
* NOT be copied.
*
* dst must not have any properties on it before this function is called.
*
* src must have been allocated via JS_NewObjectWithoutMetadata so that we can
* be sure it has no metadata that needs copying to dst. This also means that
* dst needs to have the compartment global as its parent. This function will
* preserve the existing metadata on dst, if any.
*/
extern JS_FRIEND_API(bool)
JS_InitializePropertiesFromCompatibleNativeObject(JSContext *cx,
JS::HandleObject dst,
JS::HandleObject src);
extern JS_FRIEND_API(JSString *)
JS_BasicObjectToString(JSContext *cx, JS::HandleObject obj);

View File

@ -1900,6 +1900,58 @@ js::DeepCloneObjectLiteral(JSContext *cx, HandleNativeObject obj, NewObjectKind
return clone;
}
static bool
InitializePropertiesFromCompatibleNativeObject(JSContext *cx,
HandleNativeObject dst,
HandleNativeObject src)
{
assertSameCompartment(cx, src, dst);
MOZ_ASSERT(src->getClass() == dst->getClass());
MOZ_ASSERT(src->getParent() == dst->getParent());
MOZ_ASSERT(dst->getParent() == cx->global());
MOZ_ASSERT(src->getProto() == dst->getProto());
MOZ_ASSERT(dst->lastProperty()->getObjectFlags() == 0);
MOZ_ASSERT(!src->getMetadata());
MOZ_ASSERT(!src->isSingleton());
// Save the dst metadata, if any, before we start messing with its shape.
RootedObject dstMetadata(cx, dst->getMetadata());
if (!dst->ensureElements(cx, src->getDenseInitializedLength()))
return false;
uint32_t initialized = src->getDenseInitializedLength();
for (uint32_t i = 0; i < initialized; ++i) {
dst->setDenseInitializedLength(i + 1);
dst->initDenseElement(i, src->getDenseElement(i));
}
MOZ_ASSERT(!src->hasPrivate());
RootedShape shape(cx, src->lastProperty());
size_t span = shape->slotSpan();
if (!dst->setLastProperty(cx, shape))
return false;
for (size_t i = JSCLASS_RESERVED_SLOTS(src->getClass()); i < span; i++)
dst->setSlot(i, src->getSlot(i));
if (dstMetadata) {
if (!js::SetObjectMetadata(cx, dst, dstMetadata))
return false;
}
return true;
}
JS_FRIEND_API(bool)
JS_InitializePropertiesFromCompatibleNativeObject(JSContext *cx,
HandleObject dst,
HandleObject src)
{
return InitializePropertiesFromCompatibleNativeObject(cx,
dst.as<NativeObject>(),
src.as<NativeObject>());
}
template<XDRMode mode>
bool
js::XDRObjectLiteral(XDRState<mode> *xdr, MutableHandleNativeObject obj)