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

Side by Side Diff: third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp

Issue 2727733002: Implement AudioWorkletProcessor interface (Closed)
Patch Set: Refactored AudioWorkletGlobalScope to centralize V8 operation 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() {
ikilpatrick 2017/03/09 21:45:23 DCHECK(isContextThread()) ?
hongchan 2017/03/15 22:30:18 Done.
45 m_processorDefinitionMap.clear();
haraken 2017/03/10 13:43:22 Should we also clear m_processorInstances ?
hongchan 2017/03/15 22:30:18 Done.
46 ThreadedWorkletGlobalScope::dispose();
47 }
48
49 void AudioWorkletGlobalScope::registerProcessor(
50 ScriptState* scriptState,
haraken 2017/03/10 13:43:22 You won't need to pass in a ScriptState because Au
hongchan 2017/03/15 22:30:17 Done.
51 const String& name,
52 const ScriptValue& classDefinition,
53 ExceptionState& exceptionState) {
54 DCHECK(isContextThread());
55
56 if (m_processorDefinitionMap.contains(name)) {
57 exceptionState.throwDOMException(
58 NotSupportedError,
59 "A class with name:'" + name + "' is already registered.");
haraken 2017/03/10 13:43:22 I want to have tests for these exceptions.
hongchan 2017/03/15 22:30:18 You mean in the layout test? Or unit test?
60 return;
61 }
62
63 if (name.isEmpty()) {
64 exceptionState.throwTypeError("The empty string is not a valid name.");
65 return;
66 }
67
68 v8::Isolate* isolate = scriptState->isolate();
69 v8::Local<v8::Context> context = scriptState->context();
70
71 DCHECK(classDefinition.v8Value()->IsFunction());
72
73 v8::Local<v8::Function> constructorLocal =
74 v8::Local<v8::Function>::Cast(classDefinition.v8Value());
75
76 v8::Local<v8::Value> prototypeValue;
77 if (!v8Call(constructorLocal->Get(context, v8String(isolate, "prototype")),
haraken 2017/03/10 13:43:21 Should we probably use GetPrototype()?
hongchan 2017/03/15 22:30:17 I tried, but it doesn't seem to work. Can you show
78 prototypeValue))
79 return;
80
81 if (isUndefinedOrNull(prototypeValue)) {
82 exceptionState.throwTypeError(
83 "The 'prototype' object on the class does not exist.");
84 return;
85 }
86
87 if (!prototypeValue->IsObject()) {
88 exceptionState.throwTypeError(
89 "The 'prototype' property on the class is not an object.");
90 return;
91 }
92
93 v8::Local<v8::Object> prototype = v8::Local<v8::Object>::Cast(prototypeValue);
94
95 v8::Local<v8::Value> processValue;
96 if (!v8Call(prototype->Get(context, v8String(isolate, "process")),
97 processValue))
98 return;
99
100 if (isUndefinedOrNull(processValue)) {
101 exceptionState.throwTypeError(
102 "The 'process' function on the prototype does not exist.");
103 return;
104 }
105
106 if (!processValue->IsFunction()) {
107 exceptionState.throwTypeError(
108 "The 'process' property on the prototype is not a function.");
109 return;
110 }
111
112 v8::Local<v8::Function> processLocal =
113 v8::Local<v8::Function>::Cast(processValue);
114
115 AudioWorkletProcessorDefinition* definition =
116 AudioWorkletProcessorDefinition::create(isolate, name, constructorLocal,
117 processLocal);
118
119 m_processorDefinitionMap.set(name, definition);
120 }
121
122 AudioWorkletProcessor* AudioWorkletGlobalScope::createInstance(
haraken 2017/03/10 13:43:21 Who calls this method? I couldn't find a caller in
hongchan 2017/03/15 22:30:18 The caller part is not connected yet (AudioWorklet
123 const String& name) {
124 DCHECK(isContextThread());
125
126 AudioWorkletProcessorDefinition* definition = findDefinition(name);
127 if (!definition)
128 return nullptr;
129
130 // V8 object instance construction: this construction process is here to make
131 // the AudioWorkletProcessor class a thin wrapper of V8::Object instance.
132 v8::Isolate* isolate = scriptController()->getScriptState()->isolate();
133 v8::Local<v8::Object> instanceLocal;
134 if (!V8ObjectConstructor::newInstance(isolate,
135 definition->constructorLocal(isolate))
ikilpatrick 2017/03/09 21:45:23 what happens here if the constructor throws? i.e.
hongchan 2017/03/15 22:30:18 I have to think about it. Not sure if the construc
136 .ToLocal(&instanceLocal)) {
137 return nullptr;
138 }
139
140 AudioWorkletProcessor* processor = AudioWorkletProcessor::create(this, name);
141 processor->setInstance(isolate, instanceLocal);
142 m_processorInstances.push_back(processor);
143
144 return processor;
145 }
146
147 bool AudioWorkletGlobalScope::process(AudioWorkletProcessor* processor,
148 AudioBuffer* inputBuffer,
149 AudioBuffer* outputBuffer) {
150 ScriptState* scriptState = scriptController()->getScriptState();
151 ScriptState::Scope scope(scriptState);
152
153 v8::Isolate* isolate = scriptState->isolate();
154 AudioWorkletProcessorDefinition* definition =
155 findDefinition(processor->name());
haraken 2017/03/10 13:43:21 DCHECK(definition) ?
hongchan 2017/03/15 22:30:18 Done.
156
157 v8::Local<v8::Value> argv[] = {
158 ToV8(inputBuffer, scriptState->context()->Global(), isolate),
159 ToV8(outputBuffer, scriptState->context()->Global(), isolate)};
160
161 v8::TryCatch block(isolate);
162 block.SetVerbose(true);
163
164 // Perform JS function process() in AudioWorkletProcessor instance. The actual
165 // V8 operation happens here to make the AudioWorkletProcessor class a thin
166 // wrapper of v8::Object instance.
167 V8ScriptRunner::callFunction(
168 definition->processLocal(isolate), scriptState->getExecutionContext(),
169 processor->instanceLocal(isolate), WTF_ARRAY_LENGTH(argv), argv, isolate);
170
171 if (block.HasCaught()) {
172 return false;
173 }
174
175 return true;
176 }
177
178 AudioWorkletProcessorDefinition* AudioWorkletGlobalScope::findDefinition(
179 const String& name) {
180 return m_processorDefinitionMap.at(name);
181 }
182
183 DEFINE_TRACE(AudioWorkletGlobalScope) {
184 visitor->trace(m_processorDefinitionMap);
185 visitor->trace(m_processorInstances);
186 ThreadedWorkletGlobalScope::trace(visitor);
187 }
188
35 } // namespace blink 189 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698