mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-18 06:45:33 +00:00
Bug 1140435 - Part 2 - Allow JS code to provide an async stack when calling a function. r=bz
This commit is contained in:
parent
6652a00032
commit
f638425f9d
@ -311,6 +311,7 @@ public:
|
||||
NS_IMETHOD GetAsyncCaller(nsIStackFrame** aAsyncCaller) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetCaller(nsIStackFrame** aCaller) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetFormattedStack(nsAString& aStack) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetNativeSavedFrame(JS::MutableHandle<JS::Value> aSavedFrame) MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
virtual bool IsJSFrame() const MOZ_OVERRIDE {
|
||||
@ -750,6 +751,19 @@ NS_IMETHODIMP StackFrame::GetFormattedStack(nsAString& aStack)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute jsval nativeSavedFrame; */
|
||||
NS_IMETHODIMP JSStackFrame::GetNativeSavedFrame(JS::MutableHandle<JS::Value> aSavedFrame)
|
||||
{
|
||||
aSavedFrame.setObjectOrNull(mStack);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP StackFrame::GetNativeSavedFrame(JS::MutableHandle<JS::Value> aSavedFrame)
|
||||
{
|
||||
aSavedFrame.setNull();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* AUTF8String toString (); */
|
||||
NS_IMETHODIMP StackFrame::ToString(nsACString& _retval)
|
||||
{
|
||||
|
@ -122,7 +122,7 @@ interface ScheduledGCCallback : nsISupports
|
||||
/**
|
||||
* interface of Components.utils
|
||||
*/
|
||||
[scriptable, uuid(2617a800-63c1-11e4-9803-0800200c9a66)]
|
||||
[scriptable, uuid(0354f8b4-08c6-4074-a466-2b6524b64ca3)]
|
||||
interface nsIXPCComponents_Utils : nsISupports
|
||||
{
|
||||
|
||||
@ -361,6 +361,20 @@ interface nsIXPCComponents_Utils : nsISupports
|
||||
[implicit_jscontext]
|
||||
jsval getJSTestingFunctions();
|
||||
|
||||
/*
|
||||
* To be called from JS only.
|
||||
*
|
||||
* Call 'function', using the provided stack as the async stack responsible
|
||||
* for the call, and propagate its return value or the exception it throws.
|
||||
* The function is called with no arguments, and 'this' is 'undefined'.
|
||||
*
|
||||
* The code in the function will see the given stack frame as the
|
||||
* asyncCaller of its own stack frame, instead of the current caller.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
jsval callFunctionWithAsyncStack(in jsval function, in nsIStackFrame stack,
|
||||
in AString asyncCause);
|
||||
|
||||
/*
|
||||
* To be called from JS only.
|
||||
*
|
||||
|
@ -2901,6 +2901,47 @@ nsXPCComponents_Utils::GetJSTestingFunctions(JSContext *cx,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* jsval callFunctionWithStack(in jsval function, in nsIStackFrame stack,
|
||||
in AString asyncCause); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::CallFunctionWithAsyncStack(HandleValue function,
|
||||
nsIStackFrame *stack,
|
||||
const nsAString &asyncCause,
|
||||
JSContext *cx,
|
||||
MutableHandleValue retval)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (!stack || asyncCause.IsEmpty()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> asyncStack(cx);
|
||||
rv = stack->GetNativeSavedFrame(&asyncStack);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (!asyncStack.isObject()) {
|
||||
JS_ReportError(cx, "Must use a native JavaScript stack frame");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> asyncStackObj(cx, &asyncStack.toObject());
|
||||
JS::Rooted<JSString*> asyncCauseString(cx, JS_NewUCStringCopyN(cx, asyncCause.BeginReading(),
|
||||
asyncCause.Length()));
|
||||
if (!asyncCauseString)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
JS::AutoSetAsyncStackForNewCalls sas(cx, asyncStackObj, asyncCauseString);
|
||||
|
||||
if (!JS_CallFunctionValue(cx, JS::NullPtr(), function,
|
||||
JS::HandleValueArray::empty(), retval))
|
||||
{
|
||||
return NS_ERROR_XPC_JAVASCRIPT_ERROR;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void getGlobalForObject(); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::GetGlobalForObject(HandleValue object,
|
||||
|
23
js/xpconnect/tests/unit/test_callFunctionWithAsyncStack.js
Normal file
23
js/xpconnect/tests/unit/test_callFunctionWithAsyncStack.js
Normal file
@ -0,0 +1,23 @@
|
||||
function run_test() {
|
||||
function getAsyncStack() {
|
||||
return Components.stack;
|
||||
}
|
||||
|
||||
// asyncCause may contain non-ASCII characters.
|
||||
let testAsyncCause = "Tes" + String.fromCharCode(355) + "String";
|
||||
|
||||
Components.utils.callFunctionWithAsyncStack(function asyncCallback() {
|
||||
let stack = Components.stack;
|
||||
|
||||
do_check_eq(stack.name, "asyncCallback");
|
||||
do_check_eq(stack.caller.name, null);
|
||||
do_check_eq(stack.asyncCause, null);
|
||||
|
||||
do_check_eq(stack.asyncCaller.name, "getAsyncStack");
|
||||
do_check_eq(stack.asyncCaller.asyncCause, testAsyncCause);
|
||||
do_check_eq(stack.asyncCaller.asyncCaller, null);
|
||||
|
||||
do_check_eq(stack.asyncCaller.caller.name, "run_test");
|
||||
do_check_eq(stack.asyncCaller.caller.asyncCause, null);
|
||||
}, getAsyncStack(), testAsyncCause);
|
||||
}
|
@ -55,6 +55,7 @@ support-files =
|
||||
[test_bug1081990.js]
|
||||
[test_bug1110546.js]
|
||||
[test_bug_442086.js]
|
||||
[test_callFunctionWithAsyncStack.js]
|
||||
[test_file.js]
|
||||
[test_blob.js]
|
||||
[test_blob2.js]
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(9787bc41-1ec9-4fe0-8b31-ffee5db6a893)]
|
||||
[scriptable, uuid(28bfb2a2-5ea6-4738-918b-049dc4d51f0b)]
|
||||
interface nsIStackFrame : nsISupports
|
||||
{
|
||||
// see nsIProgrammingLanguage for list of language consts
|
||||
@ -31,6 +31,10 @@ interface nsIStackFrame : nsISupports
|
||||
// Only works on JS-language stack frames.
|
||||
readonly attribute AString formattedStack;
|
||||
|
||||
// Returns the underlying SavedFrame object for native JavaScript stacks,
|
||||
// or null if this is not a native JavaScript stack frame.
|
||||
readonly attribute jsval nativeSavedFrame;
|
||||
|
||||
AUTF8String toString();
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user