Backed out changeset 205f8fa00772 (bug 1055755) for Android debug jsreftest permafail.

CLOSED TREE
This commit is contained in:
Ryan VanderMeulen 2015-01-06 19:07:06 -05:00
parent 50ef0a650b
commit 5119aa2dd9
12 changed files with 84 additions and 20 deletions

View File

@ -44,7 +44,8 @@ PreWrap(JSContext *cx, JS::HandleObject scope, JS::HandleObject obj,
}
static JSObject *
Wrap(JSContext *cx, JS::HandleObject obj, JS::HandleObject parent)
Wrap(JSContext *cx, JS::HandleObject existing, JS::HandleObject obj,
JS::HandleObject parent)
{
return js::Wrapper::New(cx, obj, parent, &js::CrossCompartmentWrapper::singleton);
}

View File

@ -801,10 +801,15 @@ typedef bool
/*
* Callback used to ask the embedding for the cross compartment wrapper handler
* that implements the desired prolicy for this kind of object in the
* destination compartment. |obj| is the object to be wrapped.
* destination compartment. |obj| is the object to be wrapped. If |existing| is
* non-nullptr, it will point to an existing wrapper object that should be
* re-used if possible. |existing| is guaranteed to be a cross-compartment
* wrapper with a lazily-defined prototype and the correct global. It is
* guaranteed not to wrap a function.
*/
typedef JSObject *
(* JSWrapObjectCallback)(JSContext *cx, JS::HandleObject obj, JS::HandleObject parent);
(* JSWrapObjectCallback)(JSContext *cx, JS::HandleObject existing, JS::HandleObject obj,
JS::HandleObject parent);
/*
* Callback used by the wrap hook to ask the embedding to prepare an object

View File

@ -343,10 +343,12 @@ JSCompartment::wrap(JSContext *cx, MutableHandleString strp)
}
bool
JSCompartment::wrap(JSContext *cx, MutableHandleObject obj)
JSCompartment::wrap(JSContext *cx, MutableHandleObject obj, HandleObject existingArg)
{
MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(this));
MOZ_ASSERT(cx->compartment() == this);
MOZ_ASSERT_IF(existingArg, existingArg->compartment() == cx->compartment());
MOZ_ASSERT_IF(existingArg, IsDeadProxyObject(existingArg));
if (!obj)
return true;
@ -419,7 +421,20 @@ JSCompartment::wrap(JSContext *cx, MutableHandleObject obj)
return true;
}
obj.set(cb->wrap(cx, obj, global));
RootedObject existing(cx, existingArg);
if (existing) {
// Is it possible to reuse |existing|?
if (!existing->getTaggedProto().isLazy() ||
// Note: Class asserted above, so all that's left to check is callability
existing->isCallable() ||
existing->getParent() != global ||
obj->isCallable())
{
existing = nullptr;
}
}
obj.set(cb->wrap(cx, existing, obj, global));
if (!obj)
return false;

View File

@ -355,10 +355,12 @@ struct JSCompartment
/* Mark cross-compartment wrappers. */
void markCrossCompartmentWrappers(JSTracer *trc);
inline bool wrap(JSContext *cx, JS::MutableHandleValue vp);
inline bool wrap(JSContext *cx, JS::MutableHandleValue vp,
JS::HandleObject existing = js::NullPtr());
bool wrap(JSContext *cx, js::MutableHandleString strp);
bool wrap(JSContext *cx, JS::MutableHandleObject obj);
bool wrap(JSContext *cx, JS::MutableHandleObject obj,
JS::HandleObject existingArg = js::NullPtr());
bool wrap(JSContext *cx, JS::MutableHandle<js::PropertyDescriptor> desc);
bool wrap(JSContext *cx, JS::MutableHandle<js::PropDesc> desc);

View File

@ -54,8 +54,10 @@ js::AutoCompartment::~AutoCompartment()
}
inline bool
JSCompartment::wrap(JSContext *cx, JS::MutableHandleValue vp)
JSCompartment::wrap(JSContext *cx, JS::MutableHandleValue vp, JS::HandleObject existing)
{
MOZ_ASSERT_IF(existing, vp.isObject());
/* Only GC things have to be wrapped or copied. */
if (!vp.isMarkable())
return true;
@ -112,7 +114,7 @@ JSCompartment::wrap(JSContext *cx, JS::MutableHandleValue vp)
}
JS::RootedObject obj(cx, &vp.toObject());
if (!wrap(cx, &obj))
if (!wrap(cx, &obj, existing))
return false;
vp.setObject(*obj);
MOZ_ASSERT_IF(cacheResult, obj == cacheResult);

View File

@ -72,7 +72,7 @@ class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
static JSObject *New(JSContext *cx, JSObject *obj, JSObject *parent, const Wrapper *handler,
const WrapperOptions &options = WrapperOptions());
static JSObject *Renew(JSContext *cx, JSObject *obj, const Wrapper *handler);
static JSObject *Renew(JSContext *cx, JSObject *existing, JSObject *obj, const Wrapper *handler);
static const Wrapper *wrapperHandler(JSObject *wrapper);
@ -217,7 +217,8 @@ typedef SecurityWrapper<Wrapper> SameCompartmentSecurityWrapper;
typedef SecurityWrapper<CrossCompartmentWrapper> CrossCompartmentSecurityWrapper;
extern JSObject *
TransparentObjectWrapper(JSContext *cx, HandleObject obj, HandleObject parent);
TransparentObjectWrapper(JSContext *cx, HandleObject existing, HandleObject obj,
HandleObject parent);
inline bool
IsWrapper(JSObject *obj)

View File

@ -526,17 +526,25 @@ js::RemapWrapper(JSContext *cx, JSObject *wobjArg, JSObject *newTargetArg)
// immediately cease to be a cross-compartment wrapper. Neuter it.
NukeCrossCompartmentWrapper(cx, wobj);
// First, we wrap it in the new compartment.
// First, we wrap it in the new compartment. We try to use the existing
// wrapper, |wobj|, since it's been nuked anyway. The wrap() function has
// the choice to reuse |wobj| or not.
RootedObject tobj(cx, newTarget);
AutoCompartment ac(cx, wobj);
if (!wcompartment->wrap(cx, &tobj))
if (!wcompartment->wrap(cx, &tobj, wobj))
MOZ_CRASH();
// Now, because we need to maintain object identity, we do a brain
// transplant on the old object so that it contains the contents of the
// new one.
if (!JSObject::swap(cx, wobj, tobj))
MOZ_CRASH();
// If wrap() reused |wobj|, it will have overwritten it and returned with
// |tobj == wobj|. Otherwise, |tobj| will point to a new wrapper and |wobj|
// will still be nuked. In the latter case, we replace |wobj| with the
// contents of the new wrapper in |tobj|.
if (tobj != wobj) {
// Now, because we need to maintain object identity, we do a brain
// transplant on the old object so that it contains the contents of the
// new one.
if (!JSObject::swap(cx, wobj, tobj))
MOZ_CRASH();
}
// Before swapping, this wrapper came out of wrap(), which enforces the
// invariant that the wrapper in the map points directly to the key.

View File

@ -833,6 +833,21 @@ js::NewProxyObject(JSContext *cx, const BaseProxyHandler *handler, HandleValue p
options);
}
void
ProxyObject::renew(JSContext *cx, const BaseProxyHandler *handler, Value priv)
{
MOZ_ASSERT_IF(IsCrossCompartmentWrapper(this), IsDeadProxyObject(this));
MOZ_ASSERT(getParent() == cx->global());
MOZ_ASSERT(getClass() == &ProxyObject::class_);
MOZ_ASSERT(!getClass()->ext.innerObject);
MOZ_ASSERT(hasLazyPrototype());
setHandler(handler);
setCrossCompartmentPrivate(priv);
setExtra(0, UndefinedValue());
setExtra(1, UndefinedValue());
}
JS_FRIEND_API(JSObject *)
js_InitProxyClass(JSContext *cx, HandleObject obj)
{

View File

@ -42,6 +42,13 @@ Wrapper::New(JSContext *cx, JSObject *obj, JSObject *parent, const Wrapper *hand
return NewProxyObject(cx, handler, priv, options.proto(), parent, options);
}
JSObject *
Wrapper::Renew(JSContext *cx, JSObject *existing, JSObject *obj, const Wrapper *handler)
{
existing->as<ProxyObject>().renew(cx, handler, ObjectValue(*obj));
return existing;
}
const Wrapper *
Wrapper::wrapperHandler(JSObject *wrapper)
{
@ -120,7 +127,8 @@ JSObject *Wrapper::defaultProto = TaggedProto::LazyProto;
/* Compartments. */
extern JSObject *
js::TransparentObjectWrapper(JSContext *cx, HandleObject obj, HandleObject parent)
js::TransparentObjectWrapper(JSContext *cx, HandleObject existing, HandleObject obj,
HandleObject parent)
{
// Allow wrapping outer window proxies.
MOZ_ASSERT(!obj->is<WrapperObject>() || obj->getClass()->ext.innerObject);

View File

@ -99,6 +99,8 @@ class ProxyObject : public JSObject
public:
static unsigned grayLinkExtraSlot(JSObject *obj);
void renew(JSContext *cx, const BaseProxyHandler *handler, Value priv);
static void trace(JSTracer *trc, JSObject *obj);
void nuke(const BaseProxyHandler *handler);

View File

@ -382,7 +382,8 @@ SelectAddonWrapper(JSContext *cx, HandleObject obj, const Wrapper *wrapper)
}
JSObject *
WrapperFactory::Rewrap(JSContext *cx, HandleObject obj, HandleObject parent)
WrapperFactory::Rewrap(JSContext *cx, HandleObject existing, HandleObject obj,
HandleObject parent)
{
MOZ_ASSERT(!IsWrapper(obj) ||
GetProxyHandler(obj) == &XrayWaiver ||
@ -495,6 +496,9 @@ WrapperFactory::Rewrap(JSContext *cx, HandleObject obj, HandleObject parent)
DEBUG_CheckUnwrapSafety(obj, wrapper, origin, target);
if (existing)
return Wrapper::Renew(cx, existing, obj, wrapper);
return Wrapper::New(cx, obj, parent, wrapper);
}

View File

@ -45,6 +45,7 @@ class WrapperFactory {
// Rewrap an object that is about to cross compartment boundaries.
static JSObject *Rewrap(JSContext *cx,
JS::HandleObject existing,
JS::HandleObject obj,
JS::HandleObject parent);