Bug 1951240 - Implement AudioWorklet.port, r=padenot,webidl,saschanaz

Differential Revision: https://phabricator.services.mozilla.com/D240104
This commit is contained in:
Andrea Marchesini
2025-03-03 14:35:51 +00:00
parent 6f967ea7c1
commit 88dae9c65e
22 changed files with 163 additions and 39 deletions

View File

@@ -60,10 +60,6 @@ DOMInterfaces = {
'implicitJSContext': [ 'buffer' ], 'implicitJSContext': [ 'buffer' ],
}, },
'AudioWorklet': {
'nativeType': 'mozilla::dom::Worklet',
},
'AudioWorkletGlobalScope': { 'AudioWorkletGlobalScope': {
'implicitJSContext': [ 'registerProcessor' ], 'implicitJSContext': [ 'registerProcessor' ],
}, },

View File

@@ -19,6 +19,7 @@
#include "mozilla/dom/AnalyserNodeBinding.h" #include "mozilla/dom/AnalyserNodeBinding.h"
#include "mozilla/dom/AudioBufferSourceNodeBinding.h" #include "mozilla/dom/AudioBufferSourceNodeBinding.h"
#include "mozilla/dom/AudioContextBinding.h" #include "mozilla/dom/AudioContextBinding.h"
#include "mozilla/dom/AudioWorklet.h"
#include "mozilla/dom/BaseAudioContextBinding.h" #include "mozilla/dom/BaseAudioContextBinding.h"
#include "mozilla/dom/BiquadFilterNodeBinding.h" #include "mozilla/dom/BiquadFilterNodeBinding.h"
#include "mozilla/dom/BrowsingContext.h" #include "mozilla/dom/BrowsingContext.h"
@@ -43,7 +44,6 @@
#include "mozilla/dom/Promise.h" #include "mozilla/dom/Promise.h"
#include "mozilla/dom/StereoPannerNodeBinding.h" #include "mozilla/dom/StereoPannerNodeBinding.h"
#include "mozilla/dom/WaveShaperNodeBinding.h" #include "mozilla/dom/WaveShaperNodeBinding.h"
#include "mozilla/dom/Worklet.h"
#include "AudioBuffer.h" #include "AudioBuffer.h"
#include "AudioBufferSourceNode.h" #include "AudioBufferSourceNode.h"
@@ -594,7 +594,7 @@ void AudioContext::GetOutputTimestamp(AudioTimestamp& aTimeStamp) {
} }
} }
Worklet* AudioContext::GetAudioWorklet(ErrorResult& aRv) { AudioWorklet* AudioContext::GetAudioWorklet(ErrorResult& aRv) {
if (!mWorklet) { if (!mWorklet) {
mWorklet = AudioWorkletImpl::CreateWorklet(this, aRv); mWorklet = AudioWorkletImpl::CreateWorklet(this, aRv);
} }

View File

@@ -50,6 +50,7 @@ class AudioBufferSourceNode;
class AudioDestinationNode; class AudioDestinationNode;
class AudioListener; class AudioListener;
class AudioNode; class AudioNode;
class AudioWorklet;
class BiquadFilterNode; class BiquadFilterNode;
class BrowsingContext; class BrowsingContext;
class ChannelMergerNode; class ChannelMergerNode;
@@ -72,7 +73,6 @@ class PannerNode;
class ScriptProcessorNode; class ScriptProcessorNode;
class StereoPannerNode; class StereoPannerNode;
class WaveShaperNode; class WaveShaperNode;
class Worklet;
class PeriodicWave; class PeriodicWave;
struct PeriodicWaveConstraints; struct PeriodicWaveConstraints;
class Promise; class Promise;
@@ -202,7 +202,7 @@ class AudioContext final : public DOMEventTargetHelper,
void GetOutputTimestamp(AudioTimestamp& aTimeStamp); void GetOutputTimestamp(AudioTimestamp& aTimeStamp);
Worklet* GetAudioWorklet(ErrorResult& aRv); AudioWorklet* GetAudioWorklet(ErrorResult& aRv);
bool IsRunning() const; bool IsRunning() const;
@@ -393,7 +393,7 @@ class AudioContext final : public DOMEventTargetHelper,
AudioContextState mAudioContextState; AudioContextState mAudioContextState;
RefPtr<AudioDestinationNode> mDestination; RefPtr<AudioDestinationNode> mDestination;
RefPtr<AudioListener> mListener; RefPtr<AudioListener> mListener;
RefPtr<Worklet> mWorklet; RefPtr<AudioWorklet> mWorklet;
nsTArray<UniquePtr<WebAudioDecodeJob>> mDecodeJobs; nsTArray<UniquePtr<WebAudioDecodeJob>> mDecodeJobs;
// This array is used to keep the suspend/close promises alive until // This array is used to keep the suspend/close promises alive until
// they are resolved, so we can safely pass them accross threads. // they are resolved, so we can safely pass them accross threads.

View File

@@ -0,0 +1,36 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AudioWorklet.h"
#include "mozilla/dom/MessagePort.h"
#include "mozilla/dom/WorkletImpl.h"
namespace mozilla::dom {
NS_IMPL_ADDREF_INHERITED(AudioWorklet, Worklet)
NS_IMPL_RELEASE_INHERITED(AudioWorklet, Worklet)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AudioWorklet)
NS_INTERFACE_MAP_END_INHERITING(Worklet)
NS_IMPL_CYCLE_COLLECTION_CLASS(AudioWorklet)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(AudioWorklet, Worklet)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPort)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(AudioWorklet, Worklet)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPort)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
AudioWorklet::AudioWorklet(nsPIDOMWindowInner* aWindow,
RefPtr<WorkletImpl> aImpl, nsISupports* aOwnedObject,
MessagePort* aPort)
: Worklet(aWindow, aImpl, aOwnedObject), mPort(aPort) {
MOZ_ASSERT(aPort);
}
} // namespace mozilla::dom

View File

@@ -0,0 +1,34 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_AudioWorklet_h
#define mozilla_dom_AudioWorklet_h
#include "mozilla/dom/Worklet.h"
namespace mozilla::dom {
class MessagePort;
class AudioWorklet final : public Worklet {
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioWorklet, Worklet)
AudioWorklet(nsPIDOMWindowInner* aWindow, RefPtr<WorkletImpl> aImpl,
nsISupports* aOwnedObject, MessagePort* aPort);
MessagePort* Port() const { return mPort; };
private:
~AudioWorklet() = default;
RefPtr<MessagePort> mPort;
};
} // namespace mozilla::dom
#endif // mozilla_dom_AudioWorklet_h

View File

@@ -26,7 +26,7 @@
namespace mozilla::dom { namespace mozilla::dom {
NS_IMPL_CYCLE_COLLECTION_INHERITED(AudioWorkletGlobalScope, WorkletGlobalScope, NS_IMPL_CYCLE_COLLECTION_INHERITED(AudioWorkletGlobalScope, WorkletGlobalScope,
mNameToProcessorMap); mNameToProcessorMap, mPort);
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AudioWorkletGlobalScope) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AudioWorkletGlobalScope)
NS_INTERFACE_MAP_END_INHERITING(WorkletGlobalScope) NS_INTERFACE_MAP_END_INHERITING(WorkletGlobalScope)

View File

@@ -47,6 +47,10 @@ class AudioWorkletGlobalScope final : public WorkletGlobalScope {
float SampleRate() const; float SampleRate() const;
MessagePort* Port() const { return mPort; };
void SetPort(MessagePort* aPort) { mPort = aPort; }
// If successful, returns true and sets aRetProcessor, which will be in the // If successful, returns true and sets aRetProcessor, which will be in the
// compartment for the realm of this global. Returns false on failure. // compartment for the realm of this global. Returns false on failure.
MOZ_CAN_RUN_SCRIPT MOZ_CAN_RUN_SCRIPT
@@ -76,6 +80,8 @@ class AudioWorkletGlobalScope final : public WorkletGlobalScope {
// This does not need to be traversed during cycle-collection because it is // This does not need to be traversed during cycle-collection because it is
// only set while this AudioWorkletGlobalScope is on the stack. // only set while this AudioWorkletGlobalScope is on the stack.
RefPtr<MessagePort> mPortForProcessor; RefPtr<MessagePort> mPortForProcessor;
RefPtr<MessagePort> mPort;
}; };
} // namespace dom } // namespace dom

View File

@@ -8,17 +8,19 @@
#include "AudioContext.h" #include "AudioContext.h"
#include "AudioNodeTrack.h" #include "AudioNodeTrack.h"
#include "AudioWorklet.h"
#include "GeckoProfiler.h" #include "GeckoProfiler.h"
#include "mozilla/dom/AudioWorkletBinding.h" #include "mozilla/dom/AudioWorkletBinding.h"
#include "mozilla/dom/AudioWorkletGlobalScope.h" #include "mozilla/dom/AudioWorkletGlobalScope.h"
#include "mozilla/dom/Worklet.h" #include "mozilla/dom/MessageChannel.h"
#include "mozilla/dom/MessagePort.h"
#include "mozilla/dom/WorkletThread.h" #include "mozilla/dom/WorkletThread.h"
#include "nsGlobalWindowInner.h" #include "nsGlobalWindowInner.h"
namespace mozilla { namespace mozilla {
/* static */ already_AddRefed<dom::Worklet> AudioWorkletImpl::CreateWorklet( /* static */ already_AddRefed<dom::AudioWorklet>
dom::AudioContext* aContext, ErrorResult& aRv) { AudioWorkletImpl::CreateWorklet(dom::AudioContext* aContext, ErrorResult& aRv) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
nsGlobalWindowInner* window = aContext->GetOwnerWindow(); nsGlobalWindowInner* window = aContext->GetOwnerWindow();
@@ -32,27 +34,41 @@ namespace mozilla {
return nullptr; return nullptr;
} }
RefPtr<dom::MessageChannel> messageChannel =
dom::MessageChannel::Constructor(window, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
dom::UniqueMessagePortId globalScopePortId;
messageChannel->Port2()->CloneAndDisentangle(globalScopePortId);
RefPtr<AudioWorkletImpl> impl = RefPtr<AudioWorkletImpl> impl =
new AudioWorkletImpl(window, principal, aContext->DestinationTrack()); new AudioWorkletImpl(window, principal, aContext->DestinationTrack(),
std::move(globalScopePortId));
// The Worklet owns a reference to the AudioContext so as to keep the graph // The Worklet owns a reference to the AudioContext so as to keep the graph
// thread running as long as the Worklet is alive by keeping the // thread running as long as the Worklet is alive by keeping the
// AudioDestinationNode alive. // AudioDestinationNode alive.
return MakeAndAddRef<dom::Worklet>(window, std::move(impl), return MakeAndAddRef<dom::AudioWorklet>(
ToSupports(aContext)); window, std::move(impl), ToSupports(aContext), messageChannel->Port1());
} }
AudioWorkletImpl::AudioWorkletImpl(nsPIDOMWindowInner* aWindow, AudioWorkletImpl::AudioWorkletImpl(nsPIDOMWindowInner* aWindow,
nsIPrincipal* aPrincipal, nsIPrincipal* aPrincipal,
AudioNodeTrack* aDestinationTrack) AudioNodeTrack* aDestinationTrack,
: WorkletImpl(aWindow, aPrincipal), mDestinationTrack(aDestinationTrack) {} dom::UniqueMessagePortId&& aPortIdentifier)
: WorkletImpl(aWindow, aPrincipal),
mDestinationTrack(aDestinationTrack),
mGlobalScopePortIdentifier(std::move(aPortIdentifier)) {}
AudioWorkletImpl::~AudioWorkletImpl() = default; AudioWorkletImpl::~AudioWorkletImpl() = default;
JSObject* AudioWorkletImpl::WrapWorklet(JSContext* aCx, dom::Worklet* aWorklet, JSObject* AudioWorkletImpl::WrapWorklet(JSContext* aCx, dom::Worklet* aWorklet,
JS::Handle<JSObject*> aGivenProto) { JS::Handle<JSObject*> aGivenProto) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
return dom::AudioWorklet_Binding::Wrap(aCx, aWorklet, aGivenProto); return dom::AudioWorklet_Binding::Wrap(
aCx, static_cast<dom::AudioWorklet*>(aWorklet), aGivenProto);
} }
nsresult AudioWorkletImpl::SendControlMessage( nsresult AudioWorkletImpl::SendControlMessage(
@@ -78,10 +94,23 @@ void AudioWorkletImpl::OnAddModulePromiseSettled() const {
} }
already_AddRefed<dom::WorkletGlobalScope> already_AddRefed<dom::WorkletGlobalScope>
AudioWorkletImpl::ConstructGlobalScope() { AudioWorkletImpl::ConstructGlobalScope(JSContext* aCx) {
dom::WorkletThread::AssertIsOnWorkletThread(); dom::WorkletThread::AssertIsOnWorkletThread();
return MakeAndAddRef<dom::AudioWorkletGlobalScope>(this); RefPtr<dom::AudioWorkletGlobalScope> globalScope =
new dom::AudioWorkletGlobalScope(this);
ErrorResult rv;
RefPtr<dom::MessagePort> deserializedPort =
dom::MessagePort::Create(globalScope, mGlobalScopePortIdentifier, rv);
if (NS_WARN_IF(rv.MaybeSetPendingException(aCx))) {
// The exception will be propagated into the global
return globalScope.forget();
}
globalScope->SetPort(deserializedPort);
return globalScope.forget();
} }
} // namespace mozilla } // namespace mozilla

View File

@@ -9,6 +9,7 @@
#include "mozilla/dom/WorkletImpl.h" #include "mozilla/dom/WorkletImpl.h"
#include "mozilla/dom/AudioWorkletGlobalScope.h" #include "mozilla/dom/AudioWorkletGlobalScope.h"
#include "mozilla/dom/MessagePort.h"
namespace mozilla { namespace mozilla {
@@ -16,13 +17,14 @@ class AudioNodeTrack;
namespace dom { namespace dom {
class AudioContext; class AudioContext;
} class AudioWorklet;
} // namespace dom
class AudioWorkletImpl final : public WorkletImpl { class AudioWorkletImpl final : public WorkletImpl {
public: public:
// Methods for parent thread only: // Methods for parent thread only:
static already_AddRefed<dom::Worklet> CreateWorklet( static already_AddRefed<dom::AudioWorklet> CreateWorklet(
dom::AudioContext* aContext, ErrorResult& aRv); dom::AudioContext* aContext, ErrorResult& aRv);
JSObject* WrapWorklet(JSContext* aCx, dom::Worklet* aWorklet, JSObject* WrapWorklet(JSContext* aCx, dom::Worklet* aWorklet,
@@ -48,14 +50,17 @@ class AudioWorkletImpl final : public WorkletImpl {
protected: protected:
// Execution thread only. // Execution thread only.
already_AddRefed<dom::WorkletGlobalScope> ConstructGlobalScope() override; already_AddRefed<dom::WorkletGlobalScope> ConstructGlobalScope(
JSContext* aCx) override;
private: private:
AudioWorkletImpl(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal, AudioWorkletImpl(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal,
AudioNodeTrack* aDestinationTrack); AudioNodeTrack* aDestinationTrack,
dom::UniqueMessagePortId&& aPortIdentifier);
~AudioWorkletImpl(); ~AudioWorkletImpl();
const RefPtr<AudioNodeTrack> mDestinationTrack; const RefPtr<AudioNodeTrack> mDestinationTrack;
dom::UniqueMessagePortId mGlobalScopePortIdentifier;
}; };
} // namespace mozilla } // namespace mozilla

View File

@@ -8,6 +8,7 @@
#include "AudioNodeEngine.h" #include "AudioNodeEngine.h"
#include "AudioParamMap.h" #include "AudioParamMap.h"
#include "AudioWorklet.h"
#include "AudioWorkletImpl.h" #include "AudioWorkletImpl.h"
#include "js/Array.h" // JS::{Get,Set}ArrayLength, JS::NewArrayLength #include "js/Array.h" // JS::{Get,Set}ArrayLength, JS::NewArrayLength
#include "js/CallAndConstruct.h" // JS::Call, JS::IsCallable #include "js/CallAndConstruct.h" // JS::Call, JS::IsCallable

View File

@@ -54,6 +54,7 @@ EXPORTS.mozilla.dom += [
"AudioParamMap.h", "AudioParamMap.h",
"AudioProcessingEvent.h", "AudioProcessingEvent.h",
"AudioScheduledSourceNode.h", "AudioScheduledSourceNode.h",
"AudioWorklet.h",
"AudioWorkletGlobalScope.h", "AudioWorkletGlobalScope.h",
"AudioWorkletNode.h", "AudioWorkletNode.h",
"AudioWorkletProcessor.h", "AudioWorkletProcessor.h",
@@ -95,6 +96,7 @@ UNIFIED_SOURCES += [
"AudioParamMap.cpp", "AudioParamMap.cpp",
"AudioProcessingEvent.cpp", "AudioProcessingEvent.cpp",
"AudioScheduledSourceNode.cpp", "AudioScheduledSourceNode.cpp",
"AudioWorklet.cpp",
"AudioWorkletGlobalScope.cpp", "AudioWorkletGlobalScope.cpp",
"AudioWorkletImpl.cpp", "AudioWorkletImpl.cpp",
"AudioWorkletNode.cpp", "AudioWorkletNode.cpp",

View File

@@ -821,7 +821,8 @@ void MessagePort::ForceClose(const MessagePortIdentifier& aIdentifier) {
mozilla::ipc::PBackgroundChild* actorChild = mozilla::ipc::PBackgroundChild* actorChild =
mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread(); mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
if (NS_WARN_IF(!actorChild)) { if (NS_WARN_IF(!actorChild)) {
MOZ_CRASH("Failed to create a PBackgroundChild actor!"); // We are shutting down this process. This port will be leaked.
return;
} }
Unused << actorChild->SendMessagePortForceClose(aIdentifier.uuid(), Unused << actorChild->SendMessagePortForceClose(aIdentifier.uuid(),

View File

@@ -12,4 +12,5 @@
[Exposed=Window, SecureContext] [Exposed=Window, SecureContext]
interface AudioWorklet : Worklet { interface AudioWorklet : Worklet {
readonly attribute MessagePort port;
}; };

View File

@@ -16,4 +16,5 @@ interface AudioWorkletGlobalScope : WorkletGlobalScope {
readonly attribute unsigned long long currentFrame; readonly attribute unsigned long long currentFrame;
readonly attribute double currentTime; readonly attribute double currentTime;
readonly attribute float sampleRate; readonly attribute float sampleRate;
readonly attribute MessagePort port;
}; };

View File

@@ -27,7 +27,7 @@ class WorkletScriptHandler;
struct WorkletOptions; struct WorkletOptions;
enum class CallerType : uint32_t; enum class CallerType : uint32_t;
class Worklet final : public nsISupports, public nsWrapperCache { class Worklet : public nsISupports, public nsWrapperCache {
public: public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(Worklet) NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(Worklet)
@@ -54,9 +54,10 @@ class Worklet final : public nsISupports, public nsWrapperCache {
return mLocalizedStrings; return mLocalizedStrings;
} }
private: protected:
~Worklet(); virtual ~Worklet();
private:
WorkletFetchHandler* GetImportFetchHandler(const nsACString& aURI); WorkletFetchHandler* GetImportFetchHandler(const nsACString& aURI);
void AddImportFetchHandler(const nsACString& aURI, void AddImportFetchHandler(const nsACString& aURI,

View File

@@ -91,7 +91,7 @@ dom::WorkletGlobalScope* WorkletImpl::GetGlobalScope() {
jsapi.Init(); jsapi.Init();
JSContext* cx = jsapi.cx(); JSContext* cx = jsapi.cx();
mGlobalScope = ConstructGlobalScope(); mGlobalScope = ConstructGlobalScope(cx);
JS::Rooted<JSObject*> global(cx); JS::Rooted<JSObject*> global(cx);
NS_ENSURE_TRUE(mGlobalScope->WrapGlobalObject(cx, &global), nullptr); NS_ENSURE_TRUE(mGlobalScope->WrapGlobalObject(cx, &global), nullptr);

View File

@@ -103,7 +103,8 @@ class WorkletImpl {
WorkletImpl(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal); WorkletImpl(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal);
virtual ~WorkletImpl(); virtual ~WorkletImpl();
virtual already_AddRefed<dom::WorkletGlobalScope> ConstructGlobalScope() = 0; virtual already_AddRefed<dom::WorkletGlobalScope> ConstructGlobalScope(
JSContext* aCx) = 0;
// Modified only in constructor. // Modified only in constructor.
ipc::PrincipalInfo mPrincipalInfo; ipc::PrincipalInfo mPrincipalInfo;

View File

@@ -31,7 +31,7 @@ PaintWorkletImpl::PaintWorkletImpl(nsPIDOMWindowInner* aWindow,
PaintWorkletImpl::~PaintWorkletImpl() = default; PaintWorkletImpl::~PaintWorkletImpl() = default;
already_AddRefed<dom::WorkletGlobalScope> already_AddRefed<dom::WorkletGlobalScope>
PaintWorkletImpl::ConstructGlobalScope() { PaintWorkletImpl::ConstructGlobalScope(JSContext* aCx) {
dom::WorkletThread::AssertIsOnWorkletThread(); dom::WorkletThread::AssertIsOnWorkletThread();
return MakeAndAddRef<dom::PaintWorkletGlobalScope>(this); return MakeAndAddRef<dom::PaintWorkletGlobalScope>(this);

View File

@@ -24,7 +24,8 @@ class PaintWorkletImpl final : public WorkletImpl {
protected: protected:
// Execution thread only. // Execution thread only.
already_AddRefed<dom::WorkletGlobalScope> ConstructGlobalScope() override; already_AddRefed<dom::WorkletGlobalScope> ConstructGlobalScope(
JSContext* aCx) override;
private: private:
PaintWorkletImpl(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal); PaintWorkletImpl(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal);

View File

@@ -167,12 +167,6 @@
[AudioRenderCapacityEvent interface: attribute underrunRatio] [AudioRenderCapacityEvent interface: attribute underrunRatio]
expected: FAIL expected: FAIL
[AudioWorklet interface: attribute port]
expected: FAIL
[AudioWorklet interface: context.audioWorklet must inherit property "port" with the proper type]
expected: FAIL
[AudioContext interface: attribute sinkId] [AudioContext interface: attribute sinkId]
expected: FAIL expected: FAIL

View File

@@ -16,6 +16,19 @@
let filePath = 'processors/port-processor.js'; let filePath = 'processors/port-processor.js';
// AudioWorket to global communication.
audit.define(
'Test postMessage from AudioWorklet to AudioWorkletGlobalScope',
(task, should) => {
context.audioWorklet.port.onmessage = (event) => {
should(event.data,
'The response from AudioWorkletGlobalscope')
.beEqualTo('hello world');
task.done();
};
context.audioWorklet.port.postMessage("hello world");
});
// Creates an AudioWorkletNode and sets an EventHandler on MessagePort // Creates an AudioWorkletNode and sets an EventHandler on MessagePort
// object. The associated PortProcessor will post a message upon its // object. The associated PortProcessor will post a message upon its
// construction. Test if the message is received correctly. // construction. Test if the message is received correctly.

View File

@@ -32,3 +32,5 @@ class PortProcessor extends AudioWorkletProcessor {
} }
registerProcessor('port-processor', PortProcessor); registerProcessor('port-processor', PortProcessor);
port.onmessage = (event) => port.postMessage(event.data);