Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1088)

Unified Diff: third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp

Issue 2727733002: Implement AudioWorkletProcessor interface (Closed)
Patch Set: Added more unit test for parsing Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp
index 33abafe5dd2497fded72ea08c2b587cd44bcadeb..2b8d6760387930e74243d0b6f841f5784a9f7ff2 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp
@@ -4,6 +4,15 @@
#include "modules/webaudio/AudioWorkletGlobalScope.h"
+#include "bindings/core/v8/ToV8.h"
+#include "bindings/core/v8/V8Binding.h"
+#include "bindings/core/v8/V8BindingMacros.h"
+#include "bindings/core/v8/V8ObjectConstructor.h"
+#include "bindings/core/v8/WorkerOrWorkletScriptController.h"
+#include "core/dom/ExceptionCode.h"
+#include "modules/webaudio/AudioBuffer.h"
+#include "modules/webaudio/AudioWorkletProcessor.h"
+#include "modules/webaudio/AudioWorkletProcessorDefinition.h"
#include "platform/weborigin/SecurityOrigin.h"
namespace blink {
@@ -32,4 +41,157 @@ AudioWorkletGlobalScope::AudioWorkletGlobalScope(
AudioWorkletGlobalScope::~AudioWorkletGlobalScope() {}
+void AudioWorkletGlobalScope::dispose() {
+ DCHECK(isContextThread());
+ m_processorDefinitionMap.clear();
+ m_processorInstances.clear();
+ ThreadedWorkletGlobalScope::dispose();
+}
+
+void AudioWorkletGlobalScope::registerProcessor(
+ const String& name,
+ const ScriptValue& classDefinition,
+ ExceptionState& exceptionState) {
+ DCHECK(isContextThread());
+
+ if (m_processorDefinitionMap.contains(name)) {
+ exceptionState.throwDOMException(
+ NotSupportedError,
+ "A class with name:'" + name + "' is already registered.");
+ return;
+ }
+
+ if (name.isEmpty()) {
Raymond Toy 2017/03/17 16:45:32 I think this isn't stated in the spec. File an is
hongchan 2017/03/20 17:03:32 Done.
+ exceptionState.throwTypeError("The empty string is not a valid name.");
+ return;
+ }
+
+ v8::Isolate* isolate = scriptController()->getScriptState()->isolate();
+ v8::Local<v8::Context> context =
+ scriptController()->getScriptState()->context();
+
+ DCHECK(classDefinition.v8Value()->IsFunction());
+ v8::Local<v8::Function> classDefinitionLocal =
+ classDefinition.v8Value().As<v8::Function>();
+
+ // This does not work. prototypeValue is not valid after this line.
+ // v8::Local<v8::Value> prototypeValue = constructorLocal->GetPrototype();
Raymond Toy 2017/03/17 16:45:31 Clarify what you mean by "not valid" after which l
hongchan 2017/03/20 17:03:32 I am going to remove this line since it just does
+
+ v8::Local<v8::Value> prototypeValueLocal;
+ bool prototypeExtraced =
Raymond Toy 2017/03/17 16:45:31 Did you mean "prototypeExtracted" instead of "prot
hongchan 2017/03/20 17:03:31 Typo! Done.
+ classDefinitionLocal->Get(context, v8String(isolate, "prototype"))
+ .ToLocal(&prototypeValueLocal);
+ DCHECK(prototypeExtraced);
+
+ if (prototypeValueLocal->IsNullOrUndefined()) {
Raymond Toy 2017/03/17 16:45:31 The spec doesn't require the distinction between n
hongchan 2017/03/20 17:03:32 Hmm. This is a good point. The class definition mu
+ exceptionState.throwTypeError(
+ "The 'prototype' object on the class does not exist.");
+ return;
+ }
+
+ if (!prototypeValueLocal->IsObject()) {
+ exceptionState.throwTypeError(
+ "The 'prototype' property on the class is not an object.");
+ return;
+ }
+
+ v8::Local<v8::Object> prototypeObjectLocal =
+ prototypeValueLocal.As<v8::Object>();
+
+ v8::Local<v8::Value> processValueLocal;
+ bool processExtracted =
+ prototypeObjectLocal->Get(context, v8String(isolate, "process"))
+ .ToLocal(&processValueLocal);
+ DCHECK(processExtracted);
+
+ if (processValueLocal->IsNullOrUndefined()) {
+ exceptionState.throwTypeError(
+ "The 'process' function does not exist in the prototype.");
+ return;
+ }
+
+ if (!processValueLocal->IsFunction()) {
+ exceptionState.throwTypeError(
+ "The 'process' property on the prototype is not a function.");
+ return;
+ }
+
+ v8::Local<v8::Function> processFunctionLocal =
+ processValueLocal.As<v8::Function>();
+
+ AudioWorkletProcessorDefinition* definition =
Raymond Toy 2017/03/17 16:45:31 DCHECK(definition), just to be sure it was created
hongchan 2017/03/20 17:03:32 DCHECK is good enough here, I think.
+ AudioWorkletProcessorDefinition::create(
+ isolate, name, classDefinitionLocal, processFunctionLocal);
+
+ m_processorDefinitionMap.set(name, definition);
+}
+
+AudioWorkletProcessor* AudioWorkletGlobalScope::createInstance(
+ const String& name) {
+ DCHECK(isContextThread());
+
+ AudioWorkletProcessorDefinition* definition = findDefinition(name);
+ if (!definition)
+ return nullptr;
+
+ // V8 object instance construction: this construction process is here to make
+ // the AudioWorkletProcessor class a thin wrapper of V8::Object instance.
+ v8::Isolate* isolate = scriptController()->getScriptState()->isolate();
+ v8::Local<v8::Object> instanceLocal;
+ if (!V8ObjectConstructor::newInstance(isolate,
+ definition->constructorLocal(isolate))
+ .ToLocal(&instanceLocal)) {
+ return nullptr;
+ }
+
+ AudioWorkletProcessor* processor = AudioWorkletProcessor::create(this, name);
Raymond Toy 2017/03/17 16:45:31 DCHECK(processor)?
hongchan 2017/03/20 17:03:32 Done.
+ processor->setInstance(isolate, instanceLocal);
+ m_processorInstances.push_back(processor);
+
+ return processor;
+}
+
+bool AudioWorkletGlobalScope::process(AudioWorkletProcessor* processor,
+ AudioBuffer* inputBuffer,
+ AudioBuffer* outputBuffer) {
Raymond Toy 2017/03/17 16:45:31 DCHECK (or CHECK) that input pointers are not null
hongchan 2017/03/20 17:03:32 Done.
+ ScriptState* scriptState = scriptController()->getScriptState();
+ ScriptState::Scope scope(scriptState);
+
+ v8::Isolate* isolate = scriptState->isolate();
+ AudioWorkletProcessorDefinition* definition =
+ findDefinition(processor->name());
+ DCHECK(definition);
+
+ v8::Local<v8::Value> argv[] = {
+ ToV8(inputBuffer, scriptState->context()->Global(), isolate),
+ ToV8(outputBuffer, scriptState->context()->Global(), isolate)};
+
+ v8::TryCatch block(isolate);
+ block.SetVerbose(true);
Raymond Toy 2017/03/17 16:45:31 Being unfamiliar with this v8 stuff, what does Set
hongchan 2017/03/20 17:03:32 Done.
+
+ // Perform JS function process() in AudioWorkletProcessor instance. The actual
+ // V8 operation happens here to make the AudioWorkletProcessor class a thin
+ // wrapper of v8::Object instance.
+ V8ScriptRunner::callFunction(
+ definition->processLocal(isolate), scriptState->getExecutionContext(),
+ processor->instanceLocal(isolate), WTF_ARRAY_LENGTH(argv), argv, isolate);
+
+ if (block.HasCaught()) {
Raymond Toy 2017/03/17 16:45:31 Maybe replace lines 179-183 with return !block.Ha
hongchan 2017/03/20 17:03:31 Done.
+ return false;
+ }
+
+ return true;
+}
+
+AudioWorkletProcessorDefinition* AudioWorkletGlobalScope::findDefinition(
+ const String& name) {
+ return m_processorDefinitionMap.at(name);
+}
+
+DEFINE_TRACE(AudioWorkletGlobalScope) {
+ visitor->trace(m_processorDefinitionMap);
+ visitor->trace(m_processorInstances);
+ ThreadedWorkletGlobalScope::trace(visitor);
+}
+
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698