зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1473467: implement AudioWorkletGlobalScope::RegisterProcessor(). r=baku,karlt
Differential Revision: https://phabricator.services.mozilla.com/D6368 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
81a039f147
Коммит
bb6b29da9d
|
@ -98,6 +98,10 @@ DOMInterfaces = {
|
||||||
'nativeType': 'mozilla::dom::Worklet',
|
'nativeType': 'mozilla::dom::Worklet',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'AudioWorkletGlobalScope': {
|
||||||
|
'implicitJSContext': [ 'registerProcessor' ],
|
||||||
|
},
|
||||||
|
|
||||||
'BarProp': {
|
'BarProp': {
|
||||||
'headerFile': 'mozilla/dom/BarProps.h',
|
'headerFile': 'mozilla/dom/BarProps.h',
|
||||||
},
|
},
|
||||||
|
|
|
@ -115,3 +115,4 @@ MSG_DEF(MSG_VALUE_OUT_OF_RANGE, 1, JSEXN_RANGEERR, "The value for the {0} is out
|
||||||
MSG_DEF(MSG_INVALID_PANNERNODE_REFDISTANCE_ERROR, 0, JSEXN_RANGEERR, "The refDistance value passed to PannerNode must not be negative.")
|
MSG_DEF(MSG_INVALID_PANNERNODE_REFDISTANCE_ERROR, 0, JSEXN_RANGEERR, "The refDistance value passed to PannerNode must not be negative.")
|
||||||
MSG_DEF(MSG_INVALID_PANNERNODE_MAXDISTANCE_ERROR, 0, JSEXN_RANGEERR, "The maxDistance value passed to PannerNode must be positive.")
|
MSG_DEF(MSG_INVALID_PANNERNODE_MAXDISTANCE_ERROR, 0, JSEXN_RANGEERR, "The maxDistance value passed to PannerNode must be positive.")
|
||||||
MSG_DEF(MSG_INVALID_PANNERNODE_ROLLOFF_ERROR, 0, JSEXN_RANGEERR, "The rolloffFactor value passed to PannerNode must not be negative.")
|
MSG_DEF(MSG_INVALID_PANNERNODE_ROLLOFF_ERROR, 0, JSEXN_RANGEERR, "The rolloffFactor value passed to PannerNode must not be negative.")
|
||||||
|
MSG_DEF(MSG_NOT_ARRAY_NOR_UNDEFINED, 1, JSEXN_TYPEERR, "{0} is neither an array nor undefined.")
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
[Global=(Worklet,AudioWorklet),Exposed=AudioWorklet]
|
[Global=(Worklet,AudioWorklet),Exposed=AudioWorklet]
|
||||||
interface AudioWorkletGlobalScope : WorkletGlobalScope {
|
interface AudioWorkletGlobalScope : WorkletGlobalScope {
|
||||||
|
[Throws]
|
||||||
void registerProcessor (DOMString name, VoidFunction processorCtor);
|
void registerProcessor (DOMString name, VoidFunction processorCtor);
|
||||||
readonly attribute unsigned long long currentFrame;
|
readonly attribute unsigned long long currentFrame;
|
||||||
readonly attribute double currentTime;
|
readonly attribute double currentTime;
|
||||||
|
|
|
@ -5,13 +5,22 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "AudioWorkletGlobalScope.h"
|
#include "AudioWorkletGlobalScope.h"
|
||||||
#include "WorkletPrincipal.h"
|
#include "jsapi.h"
|
||||||
#include "mozilla/dom/AudioWorkletGlobalScopeBinding.h"
|
#include "mozilla/dom/AudioWorkletGlobalScopeBinding.h"
|
||||||
#include "mozilla/dom/FunctionBinding.h"
|
#include "WorkletPrincipal.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_INHERITED(AudioWorkletGlobalScope, WorkletGlobalScope,
|
||||||
|
mNameToProcessorMap);
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AudioWorkletGlobalScope)
|
||||||
|
NS_INTERFACE_MAP_END_INHERITING(WorkletGlobalScope)
|
||||||
|
|
||||||
|
NS_IMPL_ADDREF_INHERITED(AudioWorkletGlobalScope, WorkletGlobalScope)
|
||||||
|
NS_IMPL_RELEASE_INHERITED(AudioWorkletGlobalScope, WorkletGlobalScope)
|
||||||
|
|
||||||
AudioWorkletGlobalScope::AudioWorkletGlobalScope(WorkletImpl* aImpl)
|
AudioWorkletGlobalScope::AudioWorkletGlobalScope(WorkletImpl* aImpl)
|
||||||
: WorkletGlobalScope(aImpl)
|
: WorkletGlobalScope(aImpl)
|
||||||
, mCurrentFrame(0)
|
, mCurrentFrame(0)
|
||||||
|
@ -31,10 +40,153 @@ AudioWorkletGlobalScope::WrapGlobalObject(JSContext* aCx,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioWorkletGlobalScope::RegisterProcessor(const nsAString& aType,
|
AudioWorkletGlobalScope::RegisterProcessor(JSContext* aCx,
|
||||||
VoidFunction& aProcessorCtor)
|
const nsAString& aName,
|
||||||
|
VoidFunction& aProcessorCtor,
|
||||||
|
ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
// Nothing to do here.
|
JS::Rooted<JSObject*> processorConstructor(aCx, aProcessorCtor.CallableOrNull());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. If the name is the empty string, throw a NotSupportedError
|
||||||
|
* exception and abort these steps because the empty string is not
|
||||||
|
* a valid key.
|
||||||
|
*/
|
||||||
|
if (aName.IsEmpty()) {
|
||||||
|
aRv.ThrowDOMException(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
|
||||||
|
NS_LITERAL_CSTRING(
|
||||||
|
"Argument 1 of AudioWorkletGlobalScope.registerProcessor "
|
||||||
|
"should not be an empty string."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2. If the name exists as a key in the node name to processor
|
||||||
|
* definition map, throw a NotSupportedError exception and abort
|
||||||
|
* these steps because registering a definition with a duplicated
|
||||||
|
* key is not allowed.
|
||||||
|
*/
|
||||||
|
if (mNameToProcessorMap.GetWeak(aName)) {
|
||||||
|
// Duplicate names are not allowed
|
||||||
|
aRv.ThrowDOMException(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
|
||||||
|
NS_LITERAL_CSTRING(
|
||||||
|
"Argument 1 of AudioWorkletGlobalScope.registerProcessor "
|
||||||
|
"is invalid: a class with the same name is already registered."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Rooted<JSObject*> constructorUnwrapped(
|
||||||
|
aCx, js::CheckedUnwrap(processorConstructor));
|
||||||
|
if (!constructorUnwrapped) {
|
||||||
|
// If the caller's compartment does not have permission to access the
|
||||||
|
// unwrapped constructor then throw.
|
||||||
|
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 3. If the result of IsConstructor(argument=processorCtor) is false,
|
||||||
|
* throw a TypeError and abort these steps.
|
||||||
|
*/
|
||||||
|
if (!JS::IsConstructor(constructorUnwrapped)) {
|
||||||
|
aRv.ThrowTypeError<MSG_NOT_CONSTRUCTOR>(NS_LITERAL_STRING(
|
||||||
|
"Argument 2 of AudioWorkletGlobalScope.registerProcessor"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 4. Let prototype be the result of Get(O=processorCtor, P="prototype").
|
||||||
|
*/
|
||||||
|
// The .prototype on the constructor passed could be an "expando" of a
|
||||||
|
// wrapper. So we should get it from wrapper instead of the underlying
|
||||||
|
// object.
|
||||||
|
JS::Rooted<JS::Value> prototype(aCx);
|
||||||
|
if (!JS_GetProperty(aCx, processorConstructor, "prototype", &prototype)) {
|
||||||
|
aRv.NoteJSContextException(aCx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 5. If the result of Type(argument=prototype) is not Object, throw a
|
||||||
|
* TypeError and abort all these steps.
|
||||||
|
*/
|
||||||
|
if (!prototype.isObject()) {
|
||||||
|
aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING(
|
||||||
|
"Argument 2 of AudioWorkletGlobalScope.registerProcessor "
|
||||||
|
"processorCtor.prototype"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 6. If the result of IsCallable(argument=Get(O=prototype, P="process"))
|
||||||
|
* is false, throw a TypeError and abort these steps.
|
||||||
|
*/
|
||||||
|
JS::Rooted<JS::Value> process(aCx);
|
||||||
|
JS::Rooted<JSObject*> prototypeObject(aCx, &prototype.toObject());
|
||||||
|
if (!JS_GetProperty(aCx, prototypeObject, "process", &process)) {
|
||||||
|
aRv.NoteJSContextException(aCx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!process.isObjectOrNull() ||
|
||||||
|
!JS::IsCallable(process.toObjectOrNull())) {
|
||||||
|
aRv.ThrowTypeError<MSG_NOT_CALLABLE>(NS_LITERAL_STRING(
|
||||||
|
"Argument 2 of AudioWorkletGlobalScope.registerProcessor "
|
||||||
|
"constructor.process"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 7. Let descriptors be the result of Get(O=processorCtor,
|
||||||
|
* P="parameterDescriptors").
|
||||||
|
*/
|
||||||
|
JS::Rooted<JS::Value> descriptors(aCx);
|
||||||
|
if (!JS_GetProperty(aCx, processorConstructor, "parameterDescriptors",
|
||||||
|
&descriptors)) {
|
||||||
|
aRv.NoteJSContextException(aCx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 8. If descriptors is neither an array nor undefined, throw a
|
||||||
|
* TypeError and abort these steps.
|
||||||
|
*/
|
||||||
|
bool isArray = false;
|
||||||
|
if (!JS_IsArrayObject(aCx, descriptors, &isArray)) {
|
||||||
|
// I would assume isArray won't be set to true if JS_IsArrayObject
|
||||||
|
// failed, but just in case, force it to false
|
||||||
|
isArray = false;
|
||||||
|
JS_ClearPendingException(aCx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!descriptors.isUndefined() && !isArray) {
|
||||||
|
aRv.ThrowTypeError<MSG_NOT_ARRAY_NOR_UNDEFINED>(NS_LITERAL_STRING(
|
||||||
|
"Argument 2 of AudioWorkletGlobalScope.registerProcessor "
|
||||||
|
"constructor.parameterDescriptors"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 9. Let definition be a new AudioWorkletProcessor definition with:
|
||||||
|
* - node name being name
|
||||||
|
* - processor class constructor being processorCtor
|
||||||
|
* 10. Add the key-value pair (name - definition) to the node name to
|
||||||
|
* processor definition map of the associated AudioWorkletGlobalScope.
|
||||||
|
*/
|
||||||
|
if (!mNameToProcessorMap.Put(aName, &aProcessorCtor, fallible)) {
|
||||||
|
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 11. Queue a task to the control thread to add the key-value pair
|
||||||
|
* (name - descriptors) to the node name to parameter descriptor
|
||||||
|
* map of the associated BaseAudioContext.
|
||||||
|
*/
|
||||||
|
// TODO: we don't have a proper mechanism to communicate with the
|
||||||
|
// control thread currently. See
|
||||||
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1473467#c3
|
||||||
|
// and https://bugzilla.mozilla.org/show_bug.cgi?id=1492014
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t AudioWorkletGlobalScope::CurrentFrame() const
|
uint64_t AudioWorkletGlobalScope::CurrentFrame() const
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
#ifndef mozilla_dom_AudioWorkletGlobalScope_h
|
#ifndef mozilla_dom_AudioWorkletGlobalScope_h
|
||||||
#define mozilla_dom_AudioWorkletGlobalScope_h
|
#define mozilla_dom_AudioWorkletGlobalScope_h
|
||||||
|
|
||||||
|
#include "mozilla/dom/FunctionBinding.h"
|
||||||
#include "mozilla/dom/WorkletGlobalScope.h"
|
#include "mozilla/dom/WorkletGlobalScope.h"
|
||||||
|
#include "nsRefPtrHashtable.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
@ -15,11 +17,13 @@ class WorkletImpl;
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
class VoidFunction;
|
|
||||||
|
|
||||||
class AudioWorkletGlobalScope final : public WorkletGlobalScope
|
class AudioWorkletGlobalScope final : public WorkletGlobalScope
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioWorkletGlobalScope, WorkletGlobalScope);
|
||||||
|
|
||||||
explicit AudioWorkletGlobalScope(WorkletImpl* aImpl);
|
explicit AudioWorkletGlobalScope(WorkletImpl* aImpl);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -27,8 +31,9 @@ public:
|
||||||
JS::MutableHandle<JSObject*> aReflector) override;
|
JS::MutableHandle<JSObject*> aReflector) override;
|
||||||
|
|
||||||
void
|
void
|
||||||
RegisterProcessor(const nsAString& aType,
|
RegisterProcessor(JSContext* aCx, const nsAString& aName,
|
||||||
VoidFunction& aProcessorCtor);
|
VoidFunction& aProcessorCtor,
|
||||||
|
ErrorResult& aRv);
|
||||||
|
|
||||||
uint64_t CurrentFrame() const;
|
uint64_t CurrentFrame() const;
|
||||||
|
|
||||||
|
@ -42,6 +47,9 @@ private:
|
||||||
uint64_t mCurrentFrame;
|
uint64_t mCurrentFrame;
|
||||||
double mCurrentTime;
|
double mCurrentTime;
|
||||||
float mSampleRate;
|
float mSampleRate;
|
||||||
|
|
||||||
|
typedef nsRefPtrHashtable<nsStringHashKey, VoidFunction> NodeNameToProcessorDefinitionMap;
|
||||||
|
NodeNameToProcessorDefinitionMap mNameToProcessorMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
|
@ -16,6 +16,8 @@ support-files=worklet_dump.js
|
||||||
scheme = http
|
scheme = http
|
||||||
[test_audioWorklet.html]
|
[test_audioWorklet.html]
|
||||||
support-files=worklet_audioWorklet.js
|
support-files=worklet_audioWorklet.js
|
||||||
|
[test_audioWorkletGlobalScopeRegisterProcessor.html]
|
||||||
|
support-files=worklet_test_audioWorkletGlobalScopeRegisterProcessor.js
|
||||||
[test_exception.html]
|
[test_exception.html]
|
||||||
support-files=worklet_exception.js
|
support-files=worklet_exception.js
|
||||||
[test_paintWorklet.html]
|
[test_paintWorklet.html]
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test for AudioWorklet</title>
|
||||||
|
<script type="application/javascript" 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() {
|
||||||
|
|
||||||
|
var expected_errors = [
|
||||||
|
"TypeError: Argument 2 of AudioWorkletGlobalScope.registerProcessor is not a constructor.",
|
||||||
|
"NotSupportedError: Argument 1 of AudioWorkletGlobalScope.registerProcessor should not be an empty string.",
|
||||||
|
"TypeError: Argument 2 of AudioWorkletGlobalScope.registerProcessor is not an object.",
|
||||||
|
"TypeError: Argument 2 of AudioWorkletGlobalScope.registerProcessor constructor.process is not callable.",
|
||||||
|
"TypeError: Argument 2 of AudioWorkletGlobalScope.registerProcessor constructor.process is not callable.",
|
||||||
|
"TypeError: Argument 2 of AudioWorkletGlobalScope.registerProcessor constructor.parameterDescriptors is neither an array nor undefined.",
|
||||||
|
"NotSupportedError: Argument 1 of AudioWorkletGlobalScope.registerProcessor is invalid: a class with the same name is already registered.",
|
||||||
|
];
|
||||||
|
|
||||||
|
var expected_errors_i = 0;
|
||||||
|
|
||||||
|
function consoleListener() {
|
||||||
|
SpecialPowers.addObserver(this, "console-api-log-event");
|
||||||
|
}
|
||||||
|
|
||||||
|
consoleListener.prototype = {
|
||||||
|
observe: function(aSubject, aTopic, aData) {
|
||||||
|
if (aTopic == "console-api-log-event") {
|
||||||
|
var obj = aSubject.wrappedJSObject;
|
||||||
|
if (obj.arguments[0] == expected_errors[expected_errors_i]) {
|
||||||
|
ok(true, "Expected error received: " + obj.arguments[0]);
|
||||||
|
expected_errors_i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expected_errors_i == expected_errors.length) {
|
||||||
|
// All errors have been received, this test has been completed
|
||||||
|
// succesfully!
|
||||||
|
SpecialPowers.removeObserver(this, "console-api-log-event");
|
||||||
|
SimpleTest.finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var cl = new consoleListener();
|
||||||
|
|
||||||
|
return SpecialPowers.pushPrefEnv(
|
||||||
|
{"set": [["dom.audioworklet.enabled", true],
|
||||||
|
["dom.worklet.enabled", true]]});
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is called into an iframe.
|
||||||
|
function runTestInIframe() {
|
||||||
|
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_test_audioWorkletGlobalScopeRegisterProcessor.js")
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,3 +1,12 @@
|
||||||
// This should work for real... at some point.
|
class DummyProcessWorkletProcessor extends AudioWorkletProcessor {
|
||||||
registerProcessor("sure!", () => {});
|
constructor() { super(); }
|
||||||
|
|
||||||
|
process() {
|
||||||
|
// Do nothing, output silence
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to pass a valid AudioWorkletProcessor here, otherwise, it will fail,
|
||||||
|
// and the console.log won't be executed
|
||||||
|
registerProcessor("sure!", DummyProcessWorkletProcessor);
|
||||||
console.log(this instanceof AudioWorkletGlobalScope ? "So far so good" : "error");
|
console.log(this instanceof AudioWorkletGlobalScope ? "So far so good" : "error");
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
// Define several classes.
|
||||||
|
// Only the last ones are valid.
|
||||||
|
class EmptyWorkletProcessor extends AudioWorkletProcessor {
|
||||||
|
}
|
||||||
|
|
||||||
|
class NoProcessWorkletProcessor extends AudioWorkletProcessor {
|
||||||
|
constructor() { super(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
class BadDescriptorsWorkletProcessor extends AudioWorkletProcessor {
|
||||||
|
constructor() { super(); }
|
||||||
|
|
||||||
|
process() {
|
||||||
|
// Do nothing, output silence
|
||||||
|
}
|
||||||
|
|
||||||
|
static get parameterDescriptors() {
|
||||||
|
return "A string";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GoodDescriptorsWorkletProcessor extends AudioWorkletProcessor {
|
||||||
|
constructor() { super(); }
|
||||||
|
|
||||||
|
process() {
|
||||||
|
// Do nothing, output silence
|
||||||
|
}
|
||||||
|
|
||||||
|
static get parameterDescriptors() {
|
||||||
|
return [{
|
||||||
|
name: 'myParam', defaultValue: 0.707
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DummyProcessWorkletProcessor extends AudioWorkletProcessor {
|
||||||
|
constructor() { super(); }
|
||||||
|
|
||||||
|
process() {
|
||||||
|
// Do nothing, output silence
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test not a constructor
|
||||||
|
// "TypeError: Argument 2 of AudioWorkletGlobalScope.registerProcessor is not a constructor."
|
||||||
|
try {
|
||||||
|
registerProcessor("sure!", () => {});
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test empty name
|
||||||
|
// "NotSupportedError: Argument 1 of AudioWorkletGlobalScope.registerProcessor should not be an empty string."
|
||||||
|
try {
|
||||||
|
registerProcessor("", EmptyWorkletProcessor);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test not an object
|
||||||
|
// "TypeError: Argument 2 of AudioWorkletGlobalScope.registerProcessor is not an object."
|
||||||
|
try {
|
||||||
|
registerProcessor("my-worklet-processor", "");
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Empty class definition
|
||||||
|
// "TypeError: Argument 2 of AudioWorkletGlobalScope.registerProcessor constructor.process is not callable."
|
||||||
|
try {
|
||||||
|
registerProcessor("empty-worklet-processor", EmptyWorkletProcessor);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test class with constructor but not process function
|
||||||
|
// "TypeError: Argument 2 of AudioWorkletGlobalScope.registerProcessor constructor.process is not callable."
|
||||||
|
try {
|
||||||
|
registerProcessor("no-worklet-processor", NoProcessWorkletProcessor);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test class with parameterDescriptors not being array nor undefined
|
||||||
|
// "TypeError: Argument 2 of AudioWorkletGlobalScope.registerProcessor constructor.parameterDescriptors is neither an array nor undefined."
|
||||||
|
try {
|
||||||
|
registerProcessor("bad-descriptors-worklet-processor", BadDescriptorsWorkletProcessor);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test class with good parameterDescriptors
|
||||||
|
// No error expected here
|
||||||
|
registerProcessor("good-descriptors-worklet-processor", GoodDescriptorsWorkletProcessor);
|
||||||
|
|
||||||
|
// Test class with constructor and process function
|
||||||
|
// No error expected here
|
||||||
|
registerProcessor("dummy-worklet-processor", DummyProcessWorkletProcessor);
|
||||||
|
|
||||||
|
// Test class adding class with the same name twice
|
||||||
|
// "NotSupportedError: Operation is not supported: Argument 1 of AudioWorkletGlobalScope.registerProcessor is invalid: a class with the same name is already registered."
|
||||||
|
try {
|
||||||
|
registerProcessor("dummy-worklet-processor", DummyProcessWorkletProcessor);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче