bug 1558123 call AudioWorkletProcessor.process() r=padenot,bzbarsky

https://heycam.github.io/webidl/#call-a-user-objects-operation may be a
simpler option here, but there are some small optimizations possible with
using JS::Call() directly:
JS::ExposeObjectToActiveJS() is not necessary because parameters are
PersistentRooted and so won't be gray.  MaybeWrapObjectValue() is not
necessary because parameters are already in the appropriate compartment.

See also https://github.com/WebAudio/web-audio-api/issues/1967 and
https://github.com/WebAudio/web-audio-api/issues/1933

Microtask support is tracked in
https://bugzilla.mozilla.org/show_bug.cgi?id=1566312

Differential Revision: https://phabricator.services.mozilla.com/D34838

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Karl Tomlinson 2019-07-17 08:20:45 +00:00
Родитель 87d828f979
Коммит 35faeb0880
2 изменённых файлов: 45 добавлений и 7 удалений

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

@ -63,6 +63,8 @@ class WorkletNodeEngine final : public AudioNodeEngine {
private:
void SendProcessorError();
bool CallProcess(JSContext* aCx, JS::Handle<JS::Value> aCallable,
bool* aActiveRet);
void ReleaseJSResources() {
mInputs.mPorts.clearAndFree();
@ -70,6 +72,7 @@ class WorkletNodeEngine final : public AudioNodeEngine {
mInputs.mJSArray.reset();
mOutputs.mJSArray.reset();
mGlobal = nullptr;
// This is equivalent to setting [[callable process]] to false.
mProcessor.reset();
}
@ -231,6 +234,29 @@ static bool PrepareBufferArrays(JSContext* aCx, Span<const AudioBlock> aBlocks,
return !(NS_WARN_IF(!PrepareArray(aCx, aPorts->mPorts, &aPorts->mJSArray)));
}
// This runs JS script. MediaStreamGraph control messages, which would
// potentially destroy the WorkletNodeEngine and its AudioNodeStream, cannot
// be triggered by script. They are not run from an nsIThread event loop and
// do not run until after ProcessBlocksOnPorts() has returned.
bool WorkletNodeEngine::CallProcess(JSContext* aCx,
JS::Handle<JS::Value> aCallable,
bool* aActiveRet) {
JS::RootedVector<JS::Value> argv(aCx);
if (NS_WARN_IF(!argv.resize(3))) {
return false;
}
argv[0].setObject(*mInputs.mJSArray);
argv[1].setObject(*mOutputs.mJSArray);
// TODO: argv[2].setObject() for parameters.
JS::Rooted<JS::Value> rval(aCx);
if (!JS::Call(aCx, mProcessor, aCallable, argv, &rval)) {
return false;
}
*aActiveRet = JS::ToBoolean(rval);
return true;
}
static void ProduceSilence(Span<AudioBlock> aOutput) {
for (AudioBlock& output : aOutput) {
output.SetNull(WEBAUDIO_BLOCK_SIZE);
@ -262,9 +288,12 @@ void WorkletNodeEngine::ProcessBlocksOnPorts(AudioNodeStream* aStream,
AutoEntryScript aes(mGlobal, "Worklet Process");
JSContext* cx = aes.cx();
if (!PrepareBufferArrays(cx, aInput, &mInputs, ArrayElementInit::None) ||
JS::Rooted<JS::Value> process(cx);
if (!JS_GetProperty(cx, mProcessor, "process", &process) ||
!process.isObject() || !JS::IsCallable(&process.toObject()) ||
!PrepareBufferArrays(cx, aInput, &mInputs, ArrayElementInit::None) ||
!PrepareBufferArrays(cx, aOutput, &mOutputs, ArrayElementInit::Zero)) {
// OOM. Give up.
// process() not callable or OOM.
SendProcessorError();
ProduceSilence(aOutput);
return;
@ -291,7 +320,19 @@ void WorkletNodeEngine::ProcessBlocksOnPorts(AudioNodeStream* aStream,
}
}
// TODO call process() - bug 1558123
bool active;
if (!CallProcess(cx, process, &active)) {
// An exception occurred.
SendProcessorError();
/**
* https://webaudio.github.io/web-audio-api/#dom-audioworkletnode-onprocessorerror
* Note that once an exception is thrown, the processor will output silence
* throughout its lifetime.
*/
ProduceSilence(aOutput);
return;
}
// TODO: Stay active even without inputs, if active is set.
// Copy output values from JS objects.
for (size_t o = 0; o < aOutput.Length(); ++o) {

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

@ -4,12 +4,9 @@
[# AUDIT TASK RUNNER FINISHED: 1 out of 2 tasks were failed.]
expected: FAIL
[< [test\] 2 out of 2 assertions were failed.]
[< [test\] 1 out of 2 assertions were failed.]
expected: FAIL
[X AudioWorklet output[128:\]: Expected 1 for all values but found 47872 unexpected values: \n\tIndex\tActual\n\t[0\]\t0\n\t[1\]\t0\n\t[2\]\t0\n\t[3\]\t0\n\t...and 47868 more errors.]
expected: FAIL
[X AudioWorklet output[0:127\] does not equal [1,1.0575640201568604,1.11493718624115,1.171929121017456,1.2283508777618408,1.2840152978897095,1.3387378454208374,1.3923370838165283,1.4446351528167725,1.4954586029052734,1.5446388721466064,1.5920131206512451,1.6374238729476929,1.6807208061218262,1.7217600345611572,1.7604057788848877...\] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}.\n\tIndex\tActual\t\t\tExpected\t\tAbsError\t\tRelError\t\tTest threshold\n\t[0\]\t0.0000000000000000e+0\t1.0000000000000000e+0\t1.0000000000000000e+0\t1.0000000000000000e+0\t0.0000000000000000e+0\n\t[1\]\t0.0000000000000000e+0\t1.0575640201568604e+0\t1.0575640201568604e+0\t1.0000000000000000e+0\t0.0000000000000000e+0\n\t[2\]\t0.0000000000000000e+0\t1.1149371862411499e+0\t1.1149371862411499e+0\t1.0000000000000000e+0\t0.0000000000000000e+0\n\t[3\]\t0.0000000000000000e+0\t1.1719291210174561e+0\t1.1719291210174561e+0\t1.0000000000000000e+0\t0.0000000000000000e+0\n\t[4\]\t0.0000000000000000e+0\t1.2283508777618408e+0\t1.2283508777618408e+0\t1.0000000000000000e+0\t0.0000000000000000e+0\n\t...and 123 more errors.\n\tMax AbsError of 1.9998766183853149e+0 at index of 27.\n\t[27\]\t0.0000000000000000e+0\t1.9998766183853149e+0\t1.9998766183853149e+0\t1.0000000000000000e+0\t0.0000000000000000e+0\n\tMax RelError of 1.0000000000000000e+0 at index of 0.\n]
expected: FAIL