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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "modules/webaudio/AudioWorkletGlobalScope.h" 5 #include "modules/webaudio/AudioWorkletGlobalScope.h"
6 6
7 #include "bindings/core/v8/ToV8.h"
8 #include "bindings/core/v8/V8Binding.h"
9 #include "bindings/core/v8/V8BindingMacros.h"
10 #include "bindings/core/v8/V8ObjectConstructor.h"
11 #include "bindings/core/v8/WorkerOrWorkletScriptController.h"
12 #include "core/dom/ExceptionCode.h"
13 #include "modules/webaudio/AudioBuffer.h"
14 #include "modules/webaudio/AudioWorkletProcessor.h"
15 #include "modules/webaudio/AudioWorkletProcessorDefinition.h"
7 #include "platform/weborigin/SecurityOrigin.h" 16 #include "platform/weborigin/SecurityOrigin.h"
8 17
9 namespace blink { 18 namespace blink {
10 19
11 AudioWorkletGlobalScope* AudioWorkletGlobalScope::create( 20 AudioWorkletGlobalScope* AudioWorkletGlobalScope::create(
12 const KURL& url, 21 const KURL& url,
13 const String& userAgent, 22 const String& userAgent,
14 PassRefPtr<SecurityOrigin> securityOrigin, 23 PassRefPtr<SecurityOrigin> securityOrigin,
15 v8::Isolate* isolate, 24 v8::Isolate* isolate,
16 WorkerThread* thread) { 25 WorkerThread* thread) {
17 return new AudioWorkletGlobalScope(url, userAgent, std::move(securityOrigin), 26 return new AudioWorkletGlobalScope(url, userAgent, std::move(securityOrigin),
18 isolate, thread); 27 isolate, thread);
19 } 28 }
20 29
21 AudioWorkletGlobalScope::AudioWorkletGlobalScope( 30 AudioWorkletGlobalScope::AudioWorkletGlobalScope(
22 const KURL& url, 31 const KURL& url,
23 const String& userAgent, 32 const String& userAgent,
24 PassRefPtr<SecurityOrigin> securityOrigin, 33 PassRefPtr<SecurityOrigin> securityOrigin,
25 v8::Isolate* isolate, 34 v8::Isolate* isolate,
26 WorkerThread* thread) 35 WorkerThread* thread)
27 : ThreadedWorkletGlobalScope(url, 36 : ThreadedWorkletGlobalScope(url,
28 userAgent, 37 userAgent,
29 std::move(securityOrigin), 38 std::move(securityOrigin),
30 isolate, 39 isolate,
31 thread) {} 40 thread) {}
32 41
33 AudioWorkletGlobalScope::~AudioWorkletGlobalScope() {} 42 AudioWorkletGlobalScope::~AudioWorkletGlobalScope() {}
34 43
44 void AudioWorkletGlobalScope::dispose() {
45 DCHECK(isContextThread());
46 m_processorDefinitionMap.clear();
47 m_processorInstances.clear();
48 ThreadedWorkletGlobalScope::dispose();
49 }
50
51 void AudioWorkletGlobalScope::registerProcessor(
52 const String& name,
53 const ScriptValue& classDefinition,
54 ExceptionState& exceptionState) {
55 DCHECK(isContextThread());
56
57 if (m_processorDefinitionMap.contains(name)) {
58 exceptionState.throwDOMException(
59 NotSupportedError,
60 "A class with name:'" + name + "' is already registered.");
61 return;
62 }
63
64 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.
65 exceptionState.throwTypeError("The empty string is not a valid name.");
66 return;
67 }
68
69 v8::Isolate* isolate = scriptController()->getScriptState()->isolate();
70 v8::Local<v8::Context> context =
71 scriptController()->getScriptState()->context();
72
73 DCHECK(classDefinition.v8Value()->IsFunction());
74 v8::Local<v8::Function> classDefinitionLocal =
75 classDefinition.v8Value().As<v8::Function>();
76
77 // This does not work. prototypeValue is not valid after this line.
78 // 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
79
80 v8::Local<v8::Value> prototypeValueLocal;
81 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.
82 classDefinitionLocal->Get(context, v8String(isolate, "prototype"))
83 .ToLocal(&prototypeValueLocal);
84 DCHECK(prototypeExtraced);
85
86 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
87 exceptionState.throwTypeError(
88 "The 'prototype' object on the class does not exist.");
89 return;
90 }
91
92 if (!prototypeValueLocal->IsObject()) {
93 exceptionState.throwTypeError(
94 "The 'prototype' property on the class is not an object.");
95 return;
96 }
97
98 v8::Local<v8::Object> prototypeObjectLocal =
99 prototypeValueLocal.As<v8::Object>();
100
101 v8::Local<v8::Value> processValueLocal;
102 bool processExtracted =
103 prototypeObjectLocal->Get(context, v8String(isolate, "process"))
104 .ToLocal(&processValueLocal);
105 DCHECK(processExtracted);
106
107 if (processValueLocal->IsNullOrUndefined()) {
108 exceptionState.throwTypeError(
109 "The 'process' function does not exist in the prototype.");
110 return;
111 }
112
113 if (!processValueLocal->IsFunction()) {
114 exceptionState.throwTypeError(
115 "The 'process' property on the prototype is not a function.");
116 return;
117 }
118
119 v8::Local<v8::Function> processFunctionLocal =
120 processValueLocal.As<v8::Function>();
121
122 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.
123 AudioWorkletProcessorDefinition::create(
124 isolate, name, classDefinitionLocal, processFunctionLocal);
125
126 m_processorDefinitionMap.set(name, definition);
127 }
128
129 AudioWorkletProcessor* AudioWorkletGlobalScope::createInstance(
130 const String& name) {
131 DCHECK(isContextThread());
132
133 AudioWorkletProcessorDefinition* definition = findDefinition(name);
134 if (!definition)
135 return nullptr;
136
137 // V8 object instance construction: this construction process is here to make
138 // the AudioWorkletProcessor class a thin wrapper of V8::Object instance.
139 v8::Isolate* isolate = scriptController()->getScriptState()->isolate();
140 v8::Local<v8::Object> instanceLocal;
141 if (!V8ObjectConstructor::newInstance(isolate,
142 definition->constructorLocal(isolate))
143 .ToLocal(&instanceLocal)) {
144 return nullptr;
145 }
146
147 AudioWorkletProcessor* processor = AudioWorkletProcessor::create(this, name);
Raymond Toy 2017/03/17 16:45:31 DCHECK(processor)?
hongchan 2017/03/20 17:03:32 Done.
148 processor->setInstance(isolate, instanceLocal);
149 m_processorInstances.push_back(processor);
150
151 return processor;
152 }
153
154 bool AudioWorkletGlobalScope::process(AudioWorkletProcessor* processor,
155 AudioBuffer* inputBuffer,
156 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.
157 ScriptState* scriptState = scriptController()->getScriptState();
158 ScriptState::Scope scope(scriptState);
159
160 v8::Isolate* isolate = scriptState->isolate();
161 AudioWorkletProcessorDefinition* definition =
162 findDefinition(processor->name());
163 DCHECK(definition);
164
165 v8::Local<v8::Value> argv[] = {
166 ToV8(inputBuffer, scriptState->context()->Global(), isolate),
167 ToV8(outputBuffer, scriptState->context()->Global(), isolate)};
168
169 v8::TryCatch block(isolate);
170 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.
171
172 // Perform JS function process() in AudioWorkletProcessor instance. The actual
173 // V8 operation happens here to make the AudioWorkletProcessor class a thin
174 // wrapper of v8::Object instance.
175 V8ScriptRunner::callFunction(
176 definition->processLocal(isolate), scriptState->getExecutionContext(),
177 processor->instanceLocal(isolate), WTF_ARRAY_LENGTH(argv), argv, isolate);
178
179 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.
180 return false;
181 }
182
183 return true;
184 }
185
186 AudioWorkletProcessorDefinition* AudioWorkletGlobalScope::findDefinition(
187 const String& name) {
188 return m_processorDefinitionMap.at(name);
189 }
190
191 DEFINE_TRACE(AudioWorkletGlobalScope) {
192 visitor->trace(m_processorDefinitionMap);
193 visitor->trace(m_processorInstances);
194 ThreadedWorkletGlobalScope::trace(visitor);
195 }
196
35 } // namespace blink 197 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698