Bug 1598114 - Initialize the javascript objects necessary to pass the third parameter to `process`. r=karlt

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Paul Adenot 2020-03-04 15:22:51 +00:00
Родитель ae9705970c
Коммит a67b86366f
1 изменённых файлов: 53 добавлений и 7 удалений

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

@ -97,8 +97,13 @@ class WorkletNodeEngine final : public AudioNodeEngine {
Vector<Channels, 1> mPorts;
JS::PersistentRooted<JSObject*> mJSArray;
};
struct ParameterValues {
Vector<JS::PersistentRooted<JSObject*>> mFloat32Arrays;
JS::PersistentRooted<JSObject*> mJSObject;
};
private:
size_t ParameterCount() { return mParamTimelines.Length(); }
void SendProcessorError();
bool CallProcess(AudioNodeTrack* aTrack, JSContext* aCx,
JS::Handle<JS::Value> aCallable);
@ -107,8 +112,10 @@ class WorkletNodeEngine final : public AudioNodeEngine {
void ReleaseJSResources() {
mInputs.mPorts.clearAndFree();
mOutputs.mPorts.clearAndFree();
mParameters.mFloat32Arrays.clearAndFree();
mInputs.mJSArray.reset();
mOutputs.mJSArray.reset();
mParameters.mJSObject.reset();
mGlobal = nullptr;
// This is equivalent to setting [[callable process]] to false.
mProcessor.reset();
@ -126,14 +133,15 @@ class WorkletNodeEngine final : public AudioNodeEngine {
// process shutdown, in which case NotifyForcedShutdown() is called on the
// rendering thread.
//
// mInputs and mOutputs keep references to all objects passed to process(),
// for reuse of the same objects. The JS objects are all in the compartment
// of the realm of mGlobal. Properties on the objects may be replaced by
// script, so don't assume that getting indexed properties on the JS arrays
// will return the same objects. Only objects and buffers created by the
// implementation are modified or read by the implementation.
// mInputs, mOutputs and mParameters keep references to all objects passed to
// process(), for reuse of the same objects. The JS objects are all in the
// compartment of the realm of mGlobal. Properties on the objects may be
// replaced by script, so don't assume that getting indexed properties on the
// JS arrays will return the same objects. Only objects and buffers created
// by the implementation are modified or read by the implementation.
Ports mInputs;
Ports mOutputs;
ParameterValues mParameters;
RefPtr<AudioWorkletGlobalScope> mGlobal;
JS::PersistentRooted<JSObject*> mProcessor;
@ -172,7 +180,12 @@ void WorkletNodeEngine::ConstructProcessor(
MOZ_ASSERT(mInputs.mPorts.empty() && mOutputs.mPorts.empty());
RefPtr<AudioWorkletGlobalScope> global = aWorkletImpl->GetGlobalScope();
MOZ_ASSERT(global); // global has already been used to register processor
JS::RootingContext* cx = RootingCx();
AutoJSAPI api;
if (NS_WARN_IF(!api.Init(global))) {
SendProcessorError();
return;
}
JSContext* cx = api.cx();
mProcessor.init(cx);
if (!global->ConstructProcessor(aName, aSerializedOptions, aPortIdentifier,
&mProcessor) ||
@ -192,6 +205,39 @@ void WorkletNodeEngine::ConstructProcessor(
for (auto& port : mOutputs.mPorts) {
port.mJSArray.init(cx);
}
JSObject* object = JS_NewPlainObject(cx);
if (NS_WARN_IF(!object)) {
SendProcessorError();
return;
}
mParameters.mJSObject.init(cx, object);
if (NS_WARN_IF(!mParameters.mFloat32Arrays.growBy(ParameterCount()))) {
SendProcessorError();
return;
}
for (size_t i = 0; i < mParamTimelines.Length(); i++) {
auto& float32ArraysRef = mParameters.mFloat32Arrays;
float32ArraysRef[i].init(cx);
JSObject* array = JS_NewFloat32Array(cx, WEBAUDIO_BLOCK_SIZE);
if (NS_WARN_IF(!array)) {
SendProcessorError();
return;
}
float32ArraysRef[i] = array;
if (NS_WARN_IF(!JS_DefineUCProperty(
cx, mParameters.mJSObject, mParamTimelines[i].mName.get(),
mParamTimelines[i].mName.Length(), float32ArraysRef[i],
JSPROP_ENUMERATE))) {
SendProcessorError();
return;
}
}
if (NS_WARN_IF(!JS_FreezeObject(cx, mParameters.mJSObject))) {
SendProcessorError();
return;
}
}
// Type T should support the length() and operator[]() methods and the return