зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 3fb25cc2c040 due to orange.
This commit is contained in:
Родитель
0897d986a2
Коммит
44938af8df
|
@ -3178,12 +3178,20 @@ nsJSContext::ClearScope(void *aGlobalObj, PRBool aClearFromProtoChain)
|
|||
JS_ClearPendingException(mContext);
|
||||
}
|
||||
|
||||
if (!JS_ClearScope(mContext, obj))
|
||||
JS_ClearPendingException(mContext);
|
||||
// Hack fix for bug 611653. Originally, this always called JS_ClearScope,
|
||||
// which was required to avoid leaks. But for native objects, the JS
|
||||
// engine has an optimization that requires that permanent properties of
|
||||
// the global object are never deleted. So instead, we call a new special
|
||||
// API that clears the values of the global, thus avoiding leaks without
|
||||
// deleting any properties.
|
||||
if (obj->isNative()) {
|
||||
js_UnbrandAndClearSlots(mContext, obj);
|
||||
} else {
|
||||
JS_ClearScope(mContext, obj);
|
||||
}
|
||||
|
||||
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
|
||||
if (!JS_ClearScope(mContext, &obj->getProxyExtra().toObject()))
|
||||
JS_ClearPendingException(mContext);
|
||||
JS_ClearScope(mContext, &obj->getProxyExtra().toObject());
|
||||
}
|
||||
|
||||
if (window != JSVAL_VOID) {
|
||||
|
@ -3221,8 +3229,7 @@ nsJSContext::ClearScope(void *aGlobalObj, PRBool aClearFromProtoChain)
|
|||
// Clear up obj's prototype chain, but not Object.prototype.
|
||||
for (JSObject *o = ::JS_GetPrototype(mContext, obj), *next;
|
||||
o && (next = ::JS_GetPrototype(mContext, o)); o = next)
|
||||
if (!::JS_ClearScope(mContext, o))
|
||||
JS_ClearPendingException(mContext);
|
||||
::JS_ClearScope(mContext, o);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -524,8 +524,7 @@ Clear(JSContext *cx,
|
|||
{
|
||||
jsval *argv = JS_ARGV(cx, vp);
|
||||
if (argc > 0 && !JSVAL_IS_PRIMITIVE(argv[0])) {
|
||||
if (!JS_ClearScope(cx, JSVAL_TO_OBJECT(argv[0])))
|
||||
return JS_FALSE;
|
||||
JS_ClearScope(cx, JSVAL_TO_OBJECT(argv[0]));
|
||||
} else {
|
||||
JS_ReportError(cx, "'clear' requires an object");
|
||||
return JS_FALSE;
|
||||
|
|
|
@ -3922,14 +3922,12 @@ JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name)
|
|||
return JS_DeleteProperty2(cx, obj, name, &junk);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ClearScope(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj);
|
||||
|
||||
uint32 span = obj->slotSpan();
|
||||
|
||||
JSFinalizeOp clearOp = obj->getOps()->clear;
|
||||
if (clearOp)
|
||||
clearOp(cx, obj);
|
||||
|
@ -3937,36 +3935,16 @@ JS_ClearScope(JSContext *cx, JSObject *obj)
|
|||
if (obj->isNative())
|
||||
js_ClearNative(cx, obj);
|
||||
|
||||
js_InitRandom(cx);
|
||||
|
||||
/* Clear cached class objects on the global object. */
|
||||
if (obj->isGlobal()) {
|
||||
if (!obj->unbrand(cx))
|
||||
return false;
|
||||
|
||||
for (int key = JSProto_Null; key < JSProto_LIMIT * 3; key++)
|
||||
JS_SetReservedSlot(cx, obj, key, JSVAL_VOID);
|
||||
|
||||
/* Clear regexp statics. */
|
||||
RegExpStatics::extractFrom(obj)->clear();
|
||||
|
||||
/* Clear the CSP eval-is-allowed cache. */
|
||||
JS_SetReservedSlot(cx, obj, JSRESERVED_GLOBAL_EVAL_ALLOWED, JSVAL_VOID);
|
||||
|
||||
/*
|
||||
* Compile-and-go scripts might rely on these slots to be present,
|
||||
* so set a bunch of dummy properties to make sure compiled code
|
||||
* doesn't reach into empty space.
|
||||
*/
|
||||
uint32 n = 0;
|
||||
while (obj->slotSpan() < span) {
|
||||
if (!JS_DefinePropertyById(cx, obj, INT_TO_JSID(n), JSVAL_VOID, NULL, NULL, 0))
|
||||
return false;
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
js_InitRandom(cx);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSIdArray *)
|
||||
|
|
|
@ -2469,7 +2469,7 @@ JS_DeleteElement(JSContext *cx, JSObject *obj, jsint index);
|
|||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_DeleteElement2(JSContext *cx, JSObject *obj, jsint index, jsval *rval);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ClearScope(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JS_PUBLIC_API(JSIdArray *)
|
||||
|
|
|
@ -270,14 +270,8 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
|
|||
/* If we already have a wrapper for this value, use it. */
|
||||
if (WrapperMap::Ptr p = crossCompartmentWrappers.lookup(*vp)) {
|
||||
*vp = p->value;
|
||||
if (vp->isObject()) {
|
||||
JSObject *obj = &vp->toObject();
|
||||
do {
|
||||
JS_ASSERT(obj->isWrapper());
|
||||
obj->setParent(global);
|
||||
obj = obj->getProto();
|
||||
} while (obj);
|
||||
}
|
||||
if (vp->isObject())
|
||||
vp->toObject().setParent(global);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -4450,6 +4450,40 @@ JSObject::freeSlot(JSContext *cx, uint32 slot)
|
|||
return false;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js_UnbrandAndClearSlots(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
JS_ASSERT(obj->isGlobal());
|
||||
|
||||
/* This can return false but that doesn't mean it failed. */
|
||||
obj->unbrand(cx);
|
||||
|
||||
/*
|
||||
* Clear the prototype cache. We must not clear the other global
|
||||
* reserved slots, as other code will crash if they are arbitrarily
|
||||
* reset (e.g., regexp statics).
|
||||
*/
|
||||
for (int key = JSProto_Null; key < JSRESERVED_GLOBAL_THIS; key++)
|
||||
JS_SetReservedSlot(cx, obj, key, JSVAL_VOID);
|
||||
|
||||
/*
|
||||
* Clear the non-reserved slots.
|
||||
*/
|
||||
ClearValueRange(obj->slots + JSCLASS_RESERVED_SLOTS(obj->clasp),
|
||||
obj->capacity - JSCLASS_RESERVED_SLOTS(obj->clasp),
|
||||
obj->clasp == &js_ArrayClass);
|
||||
|
||||
/*
|
||||
* We just overwrote all slots to undefined, so the freelist has
|
||||
* been trashed. We need to clear the head pointer or else we will
|
||||
* crash later. This leaks slots but the object is all but dead
|
||||
* anyway.
|
||||
*/
|
||||
if (obj->hasPropertyTable())
|
||||
obj->lastProperty()->getTable()->freelist = SHAPE_INVALID_SLOT;
|
||||
}
|
||||
|
||||
/* JSBOXEDWORD_INT_MAX as a string */
|
||||
#define JSBOXEDWORD_INT_MAX_STRING "1073741823"
|
||||
|
||||
|
|
|
@ -1768,6 +1768,15 @@ extern JSBool
|
|||
js_SetNativeAttributes(JSContext *cx, JSObject *obj, js::Shape *shape,
|
||||
uintN attrs);
|
||||
|
||||
/*
|
||||
* Hack fix for bug 611653: Do not use for any other purpose.
|
||||
*
|
||||
* Unbrand and set all slot values to undefined (except reserved slots that
|
||||
* are not used for cached prototypes).
|
||||
*/
|
||||
JS_FRIEND_API(void)
|
||||
js_UnbrandAndClearSlots(JSContext *cx, JSObject *obj);
|
||||
|
||||
namespace js {
|
||||
|
||||
/*
|
||||
|
|
|
@ -297,6 +297,7 @@ struct Shape : public JSObjectMap
|
|||
friend class js::PropertyTree;
|
||||
friend class js::Bindings;
|
||||
friend bool IsShapeAboutToBeFinalized(JSContext *cx, const js::Shape *shape);
|
||||
friend JS_FRIEND_API(void) ::js_UnbrandAndClearSlots(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* numLinearSearches starts at zero and is incremented initially on each
|
||||
|
|
|
@ -2733,11 +2733,10 @@ Clear(JSContext *cx, uintN argc, jsval *vp)
|
|||
{
|
||||
JSObject *obj;
|
||||
if (argc != 0 && !JS_ValueToObject(cx, JS_ARGV(cx, vp)[0], &obj))
|
||||
return false;
|
||||
if (!JS_ClearScope(cx, obj))
|
||||
return false;
|
||||
return JS_FALSE;
|
||||
JS_ClearScope(cx, obj);
|
||||
JS_SET_RVAL(cx, vp, JSVAL_VOID);
|
||||
return true;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -4685,8 +4684,7 @@ split_setup(JSContext *cx, JSBool evalcx)
|
|||
}
|
||||
}
|
||||
|
||||
if (!JS_ClearScope(cx, outer))
|
||||
return NULL;
|
||||
JS_ClearScope(cx, outer);
|
||||
|
||||
#ifndef LAZY_STANDARD_CLASSES
|
||||
if (!JS_InitStandardClasses(cx, inner))
|
||||
|
|
|
@ -178,8 +178,7 @@ class mozJSComponentLoader : public mozilla::ModuleLoader,
|
|||
JSAutoEnterCompartment ac;
|
||||
ac.enterAndIgnoreErrors(sSelf->mContext, global);
|
||||
|
||||
if (!JS_ClearScope(sSelf->mContext, global))
|
||||
JS_ClearPendingException(sSelf->mContext);
|
||||
JS_ClearScope(sSelf->mContext, global);
|
||||
JS_RemoveObjectRoot(sSelf->mContext, &global);
|
||||
}
|
||||
|
||||
|
|
|
@ -679,8 +679,7 @@ static JSBool
|
|||
Clear(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
if (argc > 0 && !JSVAL_IS_PRIMITIVE(JS_ARGV(cx, vp)[0])) {
|
||||
if (!JS_ClearScope(cx, JSVAL_TO_OBJECT(JS_ARGV(cx, vp)[0])))
|
||||
return JS_FALSE;
|
||||
JS_ClearScope(cx, JSVAL_TO_OBJECT(JS_ARGV(cx, vp)[0]));
|
||||
} else {
|
||||
JS_ReportError(cx, "'clear' requires an object");
|
||||
return JS_FALSE;
|
||||
|
@ -2020,8 +2019,7 @@ main(int argc, char **argv)
|
|||
(void**) getter_AddRefs(bogus));
|
||||
#endif
|
||||
JSPRINCIPALS_DROP(cx, gJSPrincipals);
|
||||
if (!JS_ClearScope(cx, glob))
|
||||
NS_ERROR("clearing scope failed");
|
||||
JS_ClearScope(cx, glob);
|
||||
JS_GC(cx);
|
||||
JSContext *oldcx;
|
||||
cxstack->Pop(&oldcx);
|
||||
|
|
|
@ -558,9 +558,8 @@ nsIDOMHTMLDocument_Write_customMethodCallCode = """
|
|||
|
||||
nsIDOMStorage_Clear_customMethodCallCode = """
|
||||
rv = self->Clear();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = JS_ClearScope(cx, obj) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
if (NS_SUCCEEDED(rv))
|
||||
JS_ClearScope(cx, obj);
|
||||
"""
|
||||
|
||||
CUSTOM_QS = {
|
||||
|
|
|
@ -856,8 +856,7 @@ int main()
|
|||
|
||||
{
|
||||
JSAutoRequest ar(jscontext);
|
||||
if (!JS_ClearScope(jscontext, glob))
|
||||
DIE("FAILED to clear scope");
|
||||
JS_ClearScope(jscontext, glob);
|
||||
JS_GC(jscontext);
|
||||
JS_GC(jscontext);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче