bug 580128 - Fix bugs dealing with transplanting when navigating. r=gal

This commit is contained in:
Blake Kaplan 2010-09-28 17:02:43 -07:00
Родитель 85c8778863
Коммит d4dbc19ff6
1 изменённых файлов: 25 добавлений и 4 удалений

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

@ -1237,6 +1237,13 @@ JS_TransplantWrapper(JSContext *cx, JSObject *wrapper, JSObject *target)
* compartment.
*/
JSCompartment *destination = target->getCompartment();
if (wrapper->getCompartment() == destination) {
// If the wrapper is in the same compartment as the destination, then
// we know that we won't find wrapper in the destination's cross
// compartment map and that the same object will continue to work.
wrapper->swap(target);
return wrapper;
}
JSObject *obj;
WrapperMap &map = destination->crossCompartmentWrappers;
@ -1260,7 +1267,7 @@ JS_TransplantWrapper(JSContext *cx, JSObject *wrapper, JSObject *target)
// outer window. They need to be updated to point at the new outer window.
// They also might transition between different types of security wrappers
// based on whether the new compartment is same origin with them.
Value targetv = ObjectValue(*target);
Value targetv = ObjectValue(*obj);
WrapperVector &vector = cx->runtime->compartments;
for (JSCompartment **p = vector.begin(), **end = vector.end(); p != end; ++p) {
WrapperMap &pmap = (*p)->crossCompartmentWrappers;
@ -1268,6 +1275,11 @@ JS_TransplantWrapper(JSContext *cx, JSObject *wrapper, JSObject *target)
// We found a wrapper around the outer window!
JSObject *wobj = &wp->value.toObject();
// NB: Can't use wp after this point. We remove wp from the map in
// order to ensure that we create a wrapper with the proper guts
// for the brain transplant.
pmap.remove(wp);
// First, we wrap it in the new compartment. This will return a
// new wrapper.
JSAutoEnterCompartment ec;
@ -1278,14 +1290,23 @@ JS_TransplantWrapper(JSContext *cx, JSObject *wrapper, JSObject *target)
// Now, because we need to maintain object identity, we do a brain
// transplant on the old object. At the same time, we update the
// entry in the compartment's wrapper map to point to the old
// wrapper, and remove the old outer window from the wrapper map,
// since it is now an obsolete reference.
// wrapper.
JS_ASSERT(tobj != wobj);
wobj->swap(tobj);
pmap.put(targetv, ObjectValue(*wobj));
pmap.remove(wp);
}
}
// Lastly, update the old outer window proxy to point to the new one.
{
JSAutoEnterCompartment ac;
JSObject *tobj = obj;
if (!ac.enter(cx, wrapper) || !JS_WrapObject(cx, &tobj))
return NULL;
wrapper->swap(tobj);
wrapper->getCompartment()->crossCompartmentWrappers.put(targetv, wrapperv);
}
return obj;
}