зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1612570 - Add promise support to worklet, r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D61406 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
f41dda9dcc
Коммит
c0a0edd822
|
@ -368,7 +368,9 @@ bool ExecutionRunnable::ParseAndLinkModule(
|
|||
}
|
||||
|
||||
void ExecutionRunnable::RunOnWorkletThread() {
|
||||
WorkletThread::EnsureCycleCollectedJSContext(mParentRuntime);
|
||||
WorkletThread* workletThread =
|
||||
static_cast<WorkletThread*>(NS_GetCurrentThread());
|
||||
workletThread->EnsureCycleCollectedJSContext(mParentRuntime);
|
||||
|
||||
WorkletGlobalScope* globalScope = mWorkletImpl->GetGlobalScope();
|
||||
MOZ_ASSERT(globalScope);
|
||||
|
|
|
@ -305,7 +305,33 @@ WorkletThread::DelayedDispatch(already_AddRefed<nsIRunnable>, uint32_t aFlags) {
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* static */
|
||||
static bool DispatchToEventLoop(void* aClosure,
|
||||
JS::Dispatchable* aDispatchable) {
|
||||
// This callback may execute either on the worklet thread or a random
|
||||
// JS-internal helper thread.
|
||||
|
||||
// See comment at JS::InitDispatchToEventLoop() below for how we know the
|
||||
// WorkletThread is alive.
|
||||
WorkletThread* workletThread = reinterpret_cast<WorkletThread*>(aClosure);
|
||||
|
||||
nsresult rv = workletThread->DispatchRunnable(NS_NewRunnableFunction(
|
||||
"WorkletThread::DispatchToEventLoop", [aDispatchable]() {
|
||||
CycleCollectedJSContext* ccjscx = CycleCollectedJSContext::Get();
|
||||
if (!ccjscx) {
|
||||
return;
|
||||
}
|
||||
|
||||
WorkletJSContext* wjc = ccjscx->GetAsWorkletJSContext();
|
||||
if (!wjc) {
|
||||
return;
|
||||
}
|
||||
|
||||
aDispatchable->run(wjc->Context(), JS::Dispatchable::NotShuttingDown);
|
||||
}));
|
||||
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
void WorkletThread::EnsureCycleCollectedJSContext(JSRuntime* aParentRuntime) {
|
||||
CycleCollectedJSContext* ccjscx = CycleCollectedJSContext::Get();
|
||||
if (ccjscx) {
|
||||
|
@ -328,6 +354,11 @@ void WorkletThread::EnsureCycleCollectedJSContext(JSRuntime* aParentRuntime) {
|
|||
// FIXME: JS::SetCTypesActivityCallback
|
||||
// FIXME: JS_SetGCZeal
|
||||
|
||||
// A WorkletThread lives strictly longer than its JSRuntime so we can safely
|
||||
// store a raw pointer as the callback's closure argument on the JSRuntime.
|
||||
JS::InitDispatchToEventLoop(context->Context(), DispatchToEventLoop,
|
||||
(void*)this);
|
||||
|
||||
JS_SetNativeStackQuota(context->Context(),
|
||||
WORKLET_CONTEXT_NATIVE_STACK_LIMIT);
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ class WorkletThread final : public nsThread, public nsIObserver {
|
|||
// Threads that call EnsureCycleCollectedJSContext must call
|
||||
// DeleteCycleCollectedJSContext::Get() before terminating. Clients of
|
||||
// Create() do not need to do this as Terminate() will ensure this happens.
|
||||
static void EnsureCycleCollectedJSContext(JSRuntime* aParentRuntime);
|
||||
void EnsureCycleCollectedJSContext(JSRuntime* aParentRuntime);
|
||||
static void DeleteCycleCollectedJSContext();
|
||||
|
||||
static bool IsOnWorkletThread();
|
||||
|
|
|
@ -25,3 +25,5 @@ scheme = http
|
|||
support-files=worklet_paintWorklet.js
|
||||
[test_audioWorklet_WASM.html]
|
||||
support-files=worklet_audioWorklet_WASM.js
|
||||
[test_promise.html]
|
||||
support-files=worklet_promise.js
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for promise in worklet</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="common.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
function configureTest() {
|
||||
return SpecialPowers.pushPrefEnv(
|
||||
{"set": [["dom.audioworklet.enabled", true],
|
||||
["dom.worklet.enabled", true]]});
|
||||
}
|
||||
|
||||
function runTestInIframe() {
|
||||
if (!SpecialPowers.Cu.getJSTestingFunctions().wasmIsSupported()) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
ok(window.isSecureContext, "Test should run in secure context");
|
||||
var audioContext = new AudioContext();
|
||||
ok(audioContext.audioWorklet instanceof AudioWorklet,
|
||||
"AudioContext.audioWorklet should be an instance of AudioWorklet");
|
||||
audioContext.audioWorklet.addModule("worklet_promise.js")
|
||||
.then(() => {
|
||||
const node = new AudioWorkletNode(audioContext, 'promise');
|
||||
node.port.onmessage = e => {
|
||||
ok(e.data instanceof WebAssembly.Module, "The WasmModule has been compiled into the worklet.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
const wasmTextToBinary = SpecialPowers.unwrap(SpecialPowers.Cu.getJSTestingFunctions().wasmTextToBinary);
|
||||
const fooModuleCode = wasmTextToBinary(`(module
|
||||
(func $foo (result i32) (i32.const 42))
|
||||
(export "foo" $foo)
|
||||
)`);
|
||||
|
||||
node.port.postMessage(fooModuleCode);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,22 @@
|
|||
class WasmProcessWorkletProcessor extends AudioWorkletProcessor {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.port.onmessage = e => {
|
||||
WebAssembly.compile(e.data).then(
|
||||
m => {
|
||||
this.port.postMessage(m);
|
||||
},
|
||||
() => {
|
||||
this.port.postMessage("error");
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
process(inputs, outputs, parameters) {
|
||||
// Do nothing, output silence
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
registerProcessor("promise", WasmProcessWorkletProcessor);
|
Загрузка…
Ссылка в новой задаче