Back out Bug 810644 part 2 to fix b2g test_closeOnGC.html orange.

This commit is contained in:
Boris Zbarsky 2013-04-08 22:55:15 -04:00
parent 8ab0900cf5
commit 899a6e9137
4 changed files with 122 additions and 3 deletions

View File

@ -45,8 +45,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContextPrincipal,
NS_ISCRIPTCONTEXTPRINCIPAL_IID)
#define NS_ISCRIPTCONTEXT_IID \
{ 0x5eb84406, 0x118f, 0x4eb5, \
{ 0xab, 0xd5, 0xdd, 0xc9, 0x14, 0xfe, 0xfe, 0xe4 } }
{ 0x739d69c1, 0x5248, 0x4386, \
{ 0x82, 0xa6, 0x60, 0x28, 0xf7, 0x7f, 0xb8, 0x9c } }
/* This MUST match JSVERSION_DEFAULT. This version stuff if we don't
know what language we have is a little silly... */
@ -123,6 +123,22 @@ public:
virtual nsresult ExecuteScript(JSScript* aScriptObject,
JSObject* aScopeObject) = 0;
/**
* Call the function object with given args and return its boolean result,
* or true if the result isn't boolean.
*
* @param aTarget the event target
* @param aScript an object telling the scope in which to call the compiled
* event handler function.
* @param aHandler function object (function and static scope) to invoke.
* @param argv array of arguments. Note each element is assumed to
* be an nsIVariant.
* @param rval out parameter returning result
**/
virtual nsresult CallEventHandler(nsISupports* aTarget,
JSObject* aScope, JSObject* aHandler,
nsIArray *argv, nsIVariant **rval) = 0;
/**
* Bind an already-compiled event handler function to the given
* target. Scripting languages with static scoping must re-bind the

View File

@ -1499,6 +1499,106 @@ nsJSContext::JSObjectFromInterface(nsISupports* aTarget, JSObject* aScope, JSObj
}
nsresult
nsJSContext::CallEventHandler(nsISupports* aTarget, JSObject* aScope,
JSObject* aHandler, nsIArray* aargv,
nsIVariant** arv)
{
NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
if (!mScriptsEnabled) {
return NS_OK;
}
PROFILER_LABEL("JS", "CallEventHandler");
nsAutoMicroTask mt;
xpc_UnmarkGrayObject(aScope);
xpc_UnmarkGrayObject(aHandler);
nsCxPusher pusher;
pusher.Push(mContext);
XPCAutoRequest ar(mContext);
JSObject* target = nullptr;
nsresult rv = JSObjectFromInterface(aTarget, aScope, &target);
NS_ENSURE_SUCCESS(rv, rv);
JS::AutoObjectRooter targetVal(mContext, target);
jsval rval = JSVAL_VOID;
// This one's a lot easier than EvaluateString because we don't have to
// hassle with principals: they're already compiled into the JS function.
// xxxmarkh - this comment is no longer true - principals are not used at
// all now, and never were in some cases.
// check if the event handler can be run on the object in question
rv = sSecurityManager->CheckFunctionAccess(mContext, aHandler, target);
nsJSContext::TerminationFuncHolder holder(this);
if (NS_SUCCEEDED(rv)) {
// Convert args to jsvals.
uint32_t argc = 0;
jsval *argv = nullptr;
JSObject *funobj = aHandler;
jsval funval = OBJECT_TO_JSVAL(funobj);
JSAutoCompartment ac(mContext, funobj);
if (!JS_WrapObject(mContext, &target)) {
ReportPendingException();
return NS_ERROR_FAILURE;
}
Maybe<nsRootedJSValueArray> tempStorage;
// Use |target| as the scope for wrapping the arguments, since aScope is
// the safe scope in many cases, which isn't very useful. Wrapping aTarget
// was OK because those typically have PreCreate methods that give them the
// right scope anyway, and we want to make sure that the arguments end up
// in the same scope as aTarget.
rv = ConvertSupportsTojsvals(aargv, target, &argc, &argv, tempStorage);
NS_ENSURE_SUCCESS(rv, rv);
for (uint32_t i = 0; i < argc; i++) {
if (!JSVAL_IS_PRIMITIVE(argv[i])) {
xpc_UnmarkGrayObject(JSVAL_TO_OBJECT(argv[i]));
}
}
++mExecuteDepth;
bool ok = ::JS_CallFunctionValue(mContext, target,
funval, argc, argv, &rval);
--mExecuteDepth;
if (!ok) {
// Don't pass back results from failed calls.
rval = JSVAL_VOID;
// Tell the caller that the handler threw an error.
rv = NS_ERROR_FAILURE;
} else if (rval == JSVAL_NULL) {
*arv = nullptr;
} else if (!JS_WrapValue(mContext, &rval)) {
rv = NS_ERROR_FAILURE;
} else {
rv = nsContentUtils::XPConnect()->JSToVariant(mContext, rval, arv);
}
// Tell XPConnect about any pending exceptions. This is needed
// to avoid dropping JS exceptions in case we got here through
// nested calls through XPConnect.
if (NS_FAILED(rv))
ReportPendingException();
}
pusher.Pop();
// ScriptEvaluated needs to come after we pop the stack
ScriptEvaluated(true);
return rv;
}
nsresult
nsJSContext::BindCompiledEventHandler(nsISupports* aTarget, JSObject* aScope,
JSObject* aHandler,

View File

@ -61,6 +61,9 @@ public:
virtual nsresult ExecuteScript(JSScript* aScriptObject,
JSObject* aScopeObject);
virtual nsresult CallEventHandler(nsISupports* aTarget, JSObject* aScope,
JSObject* aHandler,
nsIArray *argv, nsIVariant **rv);
virtual nsresult BindCompiledEventHandler(nsISupports *aTarget,
JSObject *aScope,
JSObject* aHandler,

View File

@ -97,7 +97,7 @@ CallbackObject::CallSetup::CallSetup(JSObject* const aCallback,
// After this point we guarantee calling ScriptEvaluated() if we
// have an nsIScriptContext.
// XXXbz Why, if, say CheckFunctionAccess fails? I know that's how
// nsJSContext::CallEventHandler used to work, but is it required?
// nsJSContext::CallEventHandler works, but is it required?
// FIXME: Bug 807369.
mCtx = ctx;