Revise AudioWorkletNode IDL (AudioWorkletProcessorState, onprocessorerror)
Spec PR: https://github.com/WebAudio/web-audio-api/pull/1509
1. Remove AudioWorkletProcessorState from the implementation.
2. Add `onprocessorerror` to AudioWorkletNode IDL.
3. Modify the existing test for AudioWorkletProcessorState
to test onprocessorerror handler.
Bug: 816542
Test: http/tests/webaudio/audio-worklet/audio-worklet-node-onerror.html
Change-Id: I96280c7dbed5cdf2d608633e4ddb9c94e9b4f6e7
Reviewed-on: https://chromium-review.googlesource.com/937986
Reviewed-by: Raymond Toy <rtoy@chromium.org>
Reviewed-by: Kentaro Hara <haraken@chromium.org>
Commit-Queue: Hongchan Choi <hongchan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#539699}
diff --git a/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/audio-worklet-node-onerror.html b/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/audio-worklet-node-onerror.html
new file mode 100644
index 0000000..fd15186
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/audio-worklet-node-onerror.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>
+ Test onprocessorerror handler in AudioWorkletNode
+ </title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ <script src="../../../webaudio-resources/audit.js"></script>
+ <script src="audio-worklet-common.js"></script>
+ </head>
+ <body>
+ <script id="layout-test-code">
+ // TODO(hongchan): remove this assertion when AudioWorklet shipped.
+ assertAudioWorklet();
+
+ let audit = Audit.createTaskRunner();
+
+ const sampleRate = 48000;
+ const renderLength = sampleRate * 0.1;
+
+ let context = new OfflineAudioContext(1, renderLength, sampleRate);
+
+ // Test |onprocessorerror| called upon failure of processor constructor.
+ audit.define('constructor-error',
+ (task, should) => {
+ let constructorErrorWorkletNode =
+ new AudioWorkletNode(context, 'constructor-error');
+ constructorErrorWorkletNode.onprocessorerror = () => {
+ // Without 'processorerror' event callback, this test will be
+ // timed out.
+ task.done();
+ };
+ });
+
+ // Test |onprocessorerror| called upon failure of process() method.
+ audit.define('process-error',
+ (task, should) => {
+ let processErrorWorkletNode =
+ new AudioWorkletNode(context, 'process-error');
+ processErrorWorkletNode.connect(context.destination);
+ processErrorWorkletNode.onprocessorerror = () => {
+ // Without 'processorerror' event callback, this test will be
+ // timed out.
+ task.done();
+ };
+
+ context.startRendering();
+ });
+
+ // 'error-processor.js' contains 2 class definitions represents an error
+ // in the constructor and an error in the process method respectively.
+ context.audioWorklet.addModule('error-processor.js').then(() => {
+ audit.run();
+ });
+ </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/audio-worklet-processor-state.html b/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/audio-worklet-processor-state.html
deleted file mode 100644
index c1c51740..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/audio-worklet-processor-state.html
+++ /dev/null
@@ -1,121 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <title>
- Test AudioWorkletProcessorState in AudioWorkletNode
- </title>
- <script src="../../resources/testharness.js"></script>
- <script src="../../resources/testharnessreport.js"></script>
- <script src="../../../webaudio-resources/audit.js"></script>
- <script src="audio-worklet-common.js"></script>
- </head>
- <body>
- <script id="layout-test-code">
- // TODO(hongchan): remove this assertion when AudioWorklet shipped.
- assertAudioWorklet();
-
- let audit = Audit.createTaskRunner();
-
- const sampleRate = 48000;
- const renderLength = sampleRate * 0.1;
-
- // Test "pending", "running" and "stopped" state transition.
- audit.define('pending-running-stopped',
- (task, should) => {
- let context = new OfflineAudioContext(1, renderLength, sampleRate);
- context.audioWorklet.addModule('state-processor.js').then(() => {
- let timedWorkletNode = new AudioWorkletNode(context, 'timed');
-
- // The construction of associated processor has not been
- // completed. In this state, no audio processing can happen and
- // all messages to the processor will be queued.
- should(timedWorkletNode.processorState,
- 'Checking the processor state upon the constructor call')
- .beEqualTo('pending');
-
- timedWorkletNode.connect(context.destination);
-
- // Checks the handler of |onprocessorstatechange|. Because the
- // processor script is correct, the |running| state change MUST
- // be fired.
- let isFirstPhase = true;
- timedWorkletNode.onprocessorstatechange = () => {
- // The first phase should be "running".
- if (isFirstPhase) {
- should(timedWorkletNode.processorState,
- 'Checking the processor state upon ' +
- 'processorstatechange event')
- .beEqualTo('running');
- isFirstPhase = false;
- } else {
- // The second phase in this test must be "stopped".
- should(timedWorkletNode.processorState,
- 'Checking the processor state after ' +
- 'processor stopped processing')
- .beEqualTo('stopped');
- task.done();
- }
- };
-
- context.startRendering();
- });
- });
-
- // Test the error state caused by the failure of processor constructor.
- audit.define('constructor-error',
- (task, should) => {
- let context = new OfflineAudioContext(1, renderLength, sampleRate);
- context.audioWorklet.addModule('state-processor.js').then(() => {
- let constructorErrorWorkletNode =
- new AudioWorkletNode(context, 'constructor-error');
- should(constructorErrorWorkletNode.processorState,
- 'constructorErrorWorkletNode.processorState after ' +
- 'its construction')
- .beEqualTo('pending');
- constructorErrorWorkletNode.onprocessorstatechange = () => {
- should(constructorErrorWorkletNode.processorState,
- 'workletNode.processorState upon processorstatechange ' +
- 'event after the failure from processor.constructor()')
- .beEqualTo('error');
- task.done();
- };
- });
- });
-
- // Test the error state caused by the failure of processor's process()
- // function.
- audit.define('process-error',
- (task, should) => {
- let context = new OfflineAudioContext(1, renderLength, sampleRate);
- context.audioWorklet.addModule('state-processor.js').then(() => {
- let processErrorWorkletNode =
- new AudioWorkletNode(context, 'process-error');
- should(processErrorWorkletNode.processorState,
- 'processErrorWorkletNode.processorState after ' +
- 'its construction')
- .beEqualTo('pending');
-
- processErrorWorkletNode.connect(context.destination);
-
- let isFirstPhase = true;
- processErrorWorkletNode.onprocessorstatechange = () => {
- if (isFirstPhase) {
- // Ignore the first state change event, which is "running";
- isFirstPhase = false;
- } else {
- should(processErrorWorkletNode.processorState,
- 'workletNode.processorState upon processorstatechange ' +
- 'event after the failure from processor.process()')
- .beEqualTo('error');
- task.done();
- }
- };
-
- context.startRendering();
- });
- });
-
- audit.run();
- </script>
- </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/error-processor.js b/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/error-processor.js
new file mode 100644
index 0000000..3b010db
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/error-processor.js
@@ -0,0 +1,33 @@
+/**
+ * @class ConstructorErrorProcessor
+ * @extends AudioWorkletProcessor
+ */
+class ConstructorErrorProcessor extends AudioWorkletProcessor {
+ constructor() {
+ throw 'ConstructorErrorProcessor: an error thrown from constructor.';
+ }
+
+ process() {
+ return true;
+ }
+}
+
+
+/**
+ * @class ProcessErrorProcessor
+ * @extends AudioWorkletProcessor
+ */
+class ProcessErrorProcessor extends AudioWorkletProcessor {
+ constructor() {
+ super();
+ }
+
+ process() {
+ throw 'ProcessErrorProcessor: an error throw from process method.';
+ return true;
+ }
+}
+
+
+registerProcessor('constructor-error', ConstructorErrorProcessor);
+registerProcessor('process-error', ProcessErrorProcessor);
diff --git a/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/state-processor.js b/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/state-processor.js
deleted file mode 100644
index 66213c5..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/state-processor.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * @class TimedProcessor
- * @extends AudioWorkletProcessor
- *
- * This processor class is for the life cycle and the processor state event.
- * It only lives for 1 render quantum.
- */
-class TimedProcessor extends AudioWorkletProcessor {
- constructor() {
- super();
- this.createdAt_ = currentTime;
- this.lifetime_ = 128 / sampleRate;
- }
-
- process() {
- return currentTime - this.createdAt_ > this.lifetime_ ? false : true;
- }
-}
-
-
-/**
- * @class ConstructorErrorProcessor
- * @extends AudioWorkletProcessor
- */
-class ConstructorErrorProcessor extends AudioWorkletProcessor {
- constructor() {
- throw 'ConstructorErrorProcessor: an error thrown from constructor.';
- }
-
- process() {
- return true;
- }
-}
-
-
-/**
- * @class ProcessErrorProcessor
- * @extends AudioWorkletProcessor
- */
-class ProcessErrorProcessor extends AudioWorkletProcessor {
- constructor() {
- super();
- }
-
- process() {
- throw 'ProcessErrorProcessor: an error throw from process method.';
- return true;
- }
-}
-
-
-registerProcessor('timed', TimedProcessor);
-registerProcessor('constructor-error', ConstructorErrorProcessor);
-registerProcessor('process-error', ProcessErrorProcessor);
diff --git a/third_party/WebKit/Source/core/events/event_type_names.json5 b/third_party/WebKit/Source/core/events/event_type_names.json5
index 276c0a1..74eb74c 100644
--- a/third_party/WebKit/Source/core/events/event_type_names.json5
+++ b/third_party/WebKit/Source/core/events/event_type_names.json5
@@ -203,7 +203,7 @@
"pointerup",
"popstate",
"progress",
- "processorstatechange",
+ "processorerror",
"push",
"ratechange",
"reading",
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp
index e9c9a1c6..e9bf8844 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp
@@ -25,6 +25,7 @@
#include "modules/webaudio/AudioParamDescriptor.h"
#include "modules/webaudio/AudioWorkletProcessor.h"
#include "modules/webaudio/AudioWorkletProcessorDefinition.h"
+#include "modules/webaudio/AudioWorkletProcessorErrorState.h"
#include "modules/webaudio/CrossThreadAudioWorkletProcessorInfo.h"
#include "platform/audio/AudioBus.h"
#include "platform/audio/AudioUtilities.h"
@@ -175,7 +176,7 @@
return nullptr;
}
- // ToImplWithTypeCheck() may return nullptr whenthe type does not match.
+ // ToImplWithTypeCheck() may return nullptr when the type does not match.
AudioWorkletProcessor* processor =
V8AudioWorkletProcessor::ToImplWithTypeCheck(isolate, result);
@@ -317,7 +318,7 @@
// process() method call method call failed for some reason or an exception
// was thrown by the user supplied code. Disable the processor to exclude
// it from the subsequent rendering task.
- processor->MarkNonRunnable();
+ processor->SetErrorState(AudioWorkletProcessorErrorState::kProcessError);
return false;
}
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.cpp
index 657ae632..2da78f2 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.cpp
@@ -79,8 +79,8 @@
void AudioWorkletHandler::Process(size_t frames_to_process) {
DCHECK(Context()->IsAudioThread());
- // Render and update the node state when the processor is ready and runnable.
- if (processor_ && processor_->IsRunnable()) {
+ // Render and update the node state when the processor is ready with no error.
+ if (processor_ && !processor_->hasErrorOccured()) {
Vector<AudioBus*> inputBuses;
Vector<AudioBus*> outputBuses;
for (unsigned i = 0; i < NumberOfInputs(); ++i)
@@ -104,12 +104,12 @@
// Run the render code and check the state of processor. Finish the
// processor if needed.
if (!processor_->Process(&inputBuses, &outputBuses, ¶m_value_map_) ||
- !processor_->IsRunnable()) {
+ processor_->hasErrorOccured()) {
FinishProcessorOnRenderThread();
}
} else {
// The initialization of handler or the associated processor might not be
- // ready yet or it is in 'non-runnable' state. If so, zero out the connected
+ // ready yet or it is in the error state. If so, zero out the connected
// output.
for (unsigned i = 0; i < NumberOfOutputs(); ++i) {
Output(i).Bus()->Zero();
@@ -149,30 +149,31 @@
DCHECK(!IsMainThread());
// |processor| can be nullptr when the invocation of user-supplied constructor
- // fails. That failure sets the processor to "error" state.
- processor_ = processor;
- AudioWorkletProcessorState new_state;
- new_state = processor_ ? AudioWorkletProcessorState::kRunning
- : AudioWorkletProcessorState::kError;
- PostCrossThreadTask(
- *task_runner_, FROM_HERE,
- CrossThreadBind(&AudioWorkletHandler::NotifyProcessorStateChange,
- WrapRefCounted(this), new_state));
+ // fails. That failure fires at the node's 'onprocessorerror' event handler.
+ if (processor) {
+ processor_ = processor;
+ } else {
+ PostCrossThreadTask(
+ *task_runner_, FROM_HERE,
+ CrossThreadBind(&AudioWorkletHandler::NotifyProcessorError,
+ WrapRefCounted(this),
+ AudioWorkletProcessorErrorState::kConstructionError));
+ }
}
void AudioWorkletHandler::FinishProcessorOnRenderThread() {
DCHECK(Context()->IsAudioThread());
- // The non-runnable processor means that the processor stopped due to an
- // exception thrown by the user-supplied code.
- AudioWorkletProcessorState new_state;
- new_state = processor_->IsRunnable()
- ? AudioWorkletProcessorState::kStopped
- : AudioWorkletProcessorState::kError;
- PostCrossThreadTask(
- *task_runner_, FROM_HERE,
- CrossThreadBind(&AudioWorkletHandler::NotifyProcessorStateChange,
- WrapRefCounted(this), new_state));
+ // If the user-supplied code is not runnable (i.e. threw an exception)
+ // anymore after the process() call above. Invoke error on the main thread.
+ AudioWorkletProcessorErrorState error_state = processor_->GetErrorState();
+ if (error_state == AudioWorkletProcessorErrorState::kProcessError) {
+ PostCrossThreadTask(
+ *task_runner_, FROM_HERE,
+ CrossThreadBind(&AudioWorkletHandler::NotifyProcessorError,
+ WrapRefCounted(this),
+ error_state));
+ }
// TODO(hongchan): After this point, The handler has no more pending activity
// and ready for GC.
@@ -181,12 +182,13 @@
tail_time_ = 0;
}
-void AudioWorkletHandler::NotifyProcessorStateChange(
- AudioWorkletProcessorState state) {
+void AudioWorkletHandler::NotifyProcessorError(
+ AudioWorkletProcessorErrorState error_state) {
DCHECK(IsMainThread());
if (!Context() || !Context()->GetExecutionContext() || !GetNode())
return;
- static_cast<AudioWorkletNode*>(GetNode())->SetProcessorState(state);
+
+ static_cast<AudioWorkletNode*>(GetNode())->FireProcessorError();
}
// ----------------------------------------------------------------
@@ -198,8 +200,7 @@
const Vector<CrossThreadAudioParamInfo> param_info_list,
MessagePort* node_port)
: AudioNode(context),
- node_port_(node_port),
- processor_state_(AudioWorkletProcessorState::kPending) {
+ node_port_(node_port) {
HeapHashMap<String, Member<AudioParam>> audio_param_map;
HashMap<String, scoped_refptr<AudioParamHandler>> param_handler_map;
for (const auto& param_info : param_info_list) {
@@ -348,51 +349,18 @@
return !context()->IsContextClosed();
}
-void AudioWorkletNode::SetProcessorState(AudioWorkletProcessorState new_state) {
- DCHECK(IsMainThread());
- switch (processor_state_) {
- case AudioWorkletProcessorState::kPending:
- DCHECK(new_state == AudioWorkletProcessorState::kRunning ||
- new_state == AudioWorkletProcessorState::kError);
- break;
- case AudioWorkletProcessorState::kRunning:
- DCHECK(new_state == AudioWorkletProcessorState::kStopped ||
- new_state == AudioWorkletProcessorState::kError);
- break;
- case AudioWorkletProcessorState::kStopped:
- case AudioWorkletProcessorState::kError:
- NOTREACHED()
- << "The state never changes once it reaches kStopped or kError.";
- return;
- }
-
- processor_state_ = new_state;
- DispatchEvent(Event::Create(EventTypeNames::processorstatechange));
-}
-
AudioParamMap* AudioWorkletNode::parameters() const {
return parameter_map_;
}
-String AudioWorkletNode::processorState() const {
- switch (processor_state_) {
- case AudioWorkletProcessorState::kPending:
- return "pending";
- case AudioWorkletProcessorState::kRunning:
- return "running";
- case AudioWorkletProcessorState::kStopped:
- return "stopped";
- case AudioWorkletProcessorState::kError:
- return "error";
- }
- NOTREACHED();
- return g_empty_string;
-}
-
MessagePort* AudioWorkletNode::port() const {
return node_port_;
}
+void AudioWorkletNode::FireProcessorError() {
+ DispatchEvent(Event::Create(EventTypeNames::processorerror));
+}
+
AudioWorkletHandler& AudioWorkletNode::GetWorkletHandler() const {
return static_cast<AudioWorkletHandler&>(Handler());
}
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.h b/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.h
index 7869e86..da611e7 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.h
@@ -9,6 +9,7 @@
#include "modules/webaudio/AudioNode.h"
#include "modules/webaudio/AudioParamMap.h"
#include "modules/webaudio/AudioWorkletNodeOptions.h"
+#include "modules/webaudio/AudioWorkletProcessorErrorState.h"
#include "platform/wtf/Threading.h"
namespace blink {
@@ -21,13 +22,6 @@
class MessagePort;
class ScriptState;
-enum class AudioWorkletProcessorState {
- kPending,
- kRunning,
- kStopped,
- kError,
-};
-
// AudioWorkletNode is a user-facing interface of custom audio processor in
// Web Audio API. The integration of WebAudio renderer is done via
// AudioWorkletHandler and the actual audio processing runs on
@@ -66,7 +60,7 @@
// the user-supplied |process()| method returns false.
void FinishProcessorOnRenderThread();
- void NotifyProcessorStateChange(AudioWorkletProcessorState);
+ void NotifyProcessorError(AudioWorkletProcessorErrorState);
private:
AudioWorkletHandler(
@@ -107,13 +101,12 @@
// ActiveScriptWrappable
bool HasPendingActivity() const final;
- void SetProcessorState(AudioWorkletProcessorState);
-
// IDL
AudioParamMap* parameters() const;
MessagePort* port() const;
- String processorState() const;
- DEFINE_ATTRIBUTE_EVENT_LISTENER(processorstatechange);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(processorerror);
+
+ void FireProcessorError();
virtual void Trace(blink::Visitor*);
@@ -126,7 +119,6 @@
Member<AudioParamMap> parameter_map_;
Member<MessagePort> node_port_;
- AudioWorkletProcessorState processor_state_;
};
} // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.idl b/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.idl
index 7283c0d..a4632e9 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.idl
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.idl
@@ -4,13 +4,6 @@
// https://webaudio.github.io/web-audio-api/#AudioWorkletNode
-enum AudioWorkletProcessorState {
- "pending",
- "running",
- "stopped",
- "error"
-};
-
[
ActiveScriptWrappable,
Constructor(BaseAudioContext context, DOMString name, optional AudioWorkletNodeOptions options),
@@ -22,6 +15,5 @@
] interface AudioWorkletNode : AudioNode {
readonly attribute AudioParamMap parameters;
readonly attribute MessagePort port;
- readonly attribute AudioWorkletProcessorState processorState;
- attribute EventHandler onprocessorstatechange;
+ attribute EventHandler onprocessorerror;
};
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessor.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessor.cpp
index f513a6d..061c88a 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessor.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessor.cpp
@@ -37,11 +37,24 @@
Vector<AudioBus*>* output_buses,
HashMap<String, std::unique_ptr<AudioFloatArray>>* param_value_map) {
DCHECK(global_scope_->IsContextThread());
- DCHECK(IsRunnable());
+ DCHECK(!hasErrorOccured());
return global_scope_->Process(this, input_buses, output_buses,
param_value_map);
}
+void AudioWorkletProcessor::SetErrorState(
+ AudioWorkletProcessorErrorState error_state) {
+ error_state_ = error_state;
+}
+
+AudioWorkletProcessorErrorState AudioWorkletProcessor::GetErrorState() const {
+ return error_state_;
+}
+
+bool AudioWorkletProcessor::hasErrorOccured() const {
+ return error_state_ != AudioWorkletProcessorErrorState::kNoError;
+}
+
MessagePort* AudioWorkletProcessor::port() const {
return processor_port_.Get();
}
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessor.h b/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessor.h
index 35df1e5..66e702b6 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessor.h
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessor.h
@@ -6,6 +6,7 @@
#define AudioWorkletProcessor_h
#include "modules/ModulesExport.h"
+#include "modules/webaudio/AudioWorkletProcessorErrorState.h"
#include "platform/audio/AudioArray.h"
#include "platform/bindings/ScriptWrappable.h"
#include "platform/bindings/TraceWrapperV8Reference.h"
@@ -47,11 +48,9 @@
const String& Name() const { return name_; }
- // Mark this processor as "not runnable" so it does not execute the
- // user-supplied code even after the associated node is connected to the
- // graph.
- void MarkNonRunnable() { is_runnable_ = false; }
- bool IsRunnable() { return is_runnable_; }
+ void SetErrorState(AudioWorkletProcessorErrorState);
+ AudioWorkletProcessorErrorState GetErrorState() const;
+ bool hasErrorOccured() const;
// IDL
MessagePort* port() const;
@@ -68,9 +67,8 @@
const String name_;
- // Becomes |false| when Process() method throws an exception from the the
- // user-supplied code. It is an irreversible transition.
- bool is_runnable_ = true;
+ AudioWorkletProcessorErrorState error_state_ =
+ AudioWorkletProcessorErrorState::kNoError;
};
} // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessorErrorState.h b/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessorErrorState.h
new file mode 100644
index 0000000..9968f86
--- /dev/null
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessorErrorState.h
@@ -0,0 +1,25 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef AudioWorkletProcessorErrorState_h
+#define AudioWorkletProcessorErrorState_h
+
+namespace blink {
+
+// A list of state regarding the error in AudioWorkletProcessor object.
+enum class AudioWorkletProcessorErrorState : unsigned {
+ // The constructor or the process method in the processor has not thrown any
+ // exception.
+ kNoError = 0,
+
+ // An exception thrown from the construction failure.
+ kConstructionError = 1,
+
+ // An exception thrown from the process method.
+ kProcessError = 2,
+};
+
+} // namespace blink
+
+#endif
diff --git a/third_party/WebKit/Source/modules/webaudio/BUILD.gn b/third_party/WebKit/Source/modules/webaudio/BUILD.gn
index ee8d3e8..8c70ef0d 100644
--- a/third_party/WebKit/Source/modules/webaudio/BUILD.gn
+++ b/third_party/WebKit/Source/modules/webaudio/BUILD.gn
@@ -56,6 +56,7 @@
"AudioWorkletProcessor.h",
"AudioWorkletProcessorDefinition.cpp",
"AudioWorkletProcessorDefinition.h",
+ "AudioWorkletProcessorErrorState.h",
"AudioWorkletThread.cpp",
"AudioWorkletThread.h",
"BaseAudioContext.cpp",