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

Side by Side Diff: third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp

Issue 2170383002: CustomElements: adopt node (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: patch update Created 4 years, 4 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 "bindings/core/v8/ScriptCustomElementDefinition.h" 5 #include "bindings/core/v8/ScriptCustomElementDefinition.h"
6 6
7 #include "bindings/core/v8/ScriptState.h" 7 #include "bindings/core/v8/ScriptState.h"
8 #include "bindings/core/v8/V8Binding.h" 8 #include "bindings/core/v8/V8Binding.h"
9 #include "bindings/core/v8/V8BindingMacros.h" 9 #include "bindings/core/v8/V8BindingMacros.h"
10 #include "bindings/core/v8/V8CustomElementsRegistry.h" 10 #include "bindings/core/v8/V8CustomElementsRegistry.h"
11 #include "bindings/core/v8/V8Element.h" 11 #include "bindings/core/v8/V8Element.h"
12 #include "bindings/core/v8/V8ErrorHandler.h"
12 #include "bindings/core/v8/V8HiddenValue.h" 13 #include "bindings/core/v8/V8HiddenValue.h"
13 #include "bindings/core/v8/V8ScriptRunner.h" 14 #include "bindings/core/v8/V8ScriptRunner.h"
14 #include "bindings/core/v8/V8ThrowException.h" 15 #include "bindings/core/v8/V8ThrowException.h"
15 #include "core/dom/ExceptionCode.h" 16 #include "core/dom/ExceptionCode.h"
16 #include "core/dom/custom/CustomElement.h" 17 #include "core/dom/custom/CustomElement.h"
18 #include "core/events/ErrorEvent.h"
17 #include "core/html/HTMLElement.h" 19 #include "core/html/HTMLElement.h"
18 #include "v8.h" 20 #include "v8.h"
19 #include "wtf/Allocator.h" 21 #include "wtf/Allocator.h"
20 22
21 namespace blink { 23 namespace blink {
22 24
23 // Retrieves the custom elements constructor -> name map, creating it 25 // Retrieves the custom elements constructor -> name map, creating it
24 // if necessary. The same map is used to keep prototypes alive. 26 // if necessary. The same map is used to keep prototypes alive.
25 static v8::Local<v8::Map> ensureCustomElementsRegistryMap( 27 static v8::Local<v8::Map> ensureCustomElementsRegistryMap(
26 ScriptState* scriptState, 28 ScriptState* scriptState,
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 } 100 }
99 101
100 ScriptCustomElementDefinition* ScriptCustomElementDefinition::create( 102 ScriptCustomElementDefinition* ScriptCustomElementDefinition::create(
101 ScriptState* scriptState, 103 ScriptState* scriptState,
102 CustomElementsRegistry* registry, 104 CustomElementsRegistry* registry,
103 const CustomElementDescriptor& descriptor, 105 const CustomElementDescriptor& descriptor,
104 const v8::Local<v8::Object>& constructor, 106 const v8::Local<v8::Object>& constructor,
105 const v8::Local<v8::Object>& prototype, 107 const v8::Local<v8::Object>& prototype,
106 const v8::Local<v8::Function>& connectedCallback, 108 const v8::Local<v8::Function>& connectedCallback,
107 const v8::Local<v8::Function>& disconnectedCallback, 109 const v8::Local<v8::Function>& disconnectedCallback,
110 const v8::Local<v8::Function>& adoptedCallback,
108 const v8::Local<v8::Function>& attributeChangedCallback, 111 const v8::Local<v8::Function>& attributeChangedCallback,
109 const HashSet<AtomicString>& observedAttributes) 112 const HashSet<AtomicString>& observedAttributes)
110 { 113 {
111 ScriptCustomElementDefinition* definition = 114 ScriptCustomElementDefinition* definition =
112 new ScriptCustomElementDefinition( 115 new ScriptCustomElementDefinition(
113 scriptState, 116 scriptState,
114 descriptor, 117 descriptor,
115 constructor, 118 constructor,
116 prototype, 119 prototype,
117 connectedCallback, 120 connectedCallback,
118 disconnectedCallback, 121 disconnectedCallback,
122 adoptedCallback,
119 attributeChangedCallback, 123 attributeChangedCallback,
120 observedAttributes); 124 observedAttributes);
121 125
122 // Add a constructor -> name mapping to the registry. 126 // Add a constructor -> name mapping to the registry.
123 v8::Local<v8::Value> nameValue = 127 v8::Local<v8::Value> nameValue =
124 v8String(scriptState->isolate(), descriptor.name()); 128 v8String(scriptState->isolate(), descriptor.name());
125 v8::Local<v8::Map> map = 129 v8::Local<v8::Map> map =
126 ensureCustomElementsRegistryMap(scriptState, registry); 130 ensureCustomElementsRegistryMap(scriptState, registry);
127 v8CallOrCrash(map->Set(scriptState->context(), constructor, nameValue)); 131 v8CallOrCrash(map->Set(scriptState->context(), constructor, nameValue));
128 definition->m_constructor.setPhantom(); 132 definition->m_constructor.setPhantom();
129 133
130 // We add the prototype and callbacks here to keep them alive. We use the 134 // We add the prototype and callbacks here to keep them alive. We use the
131 // name as the key because it is unique per-registry. 135 // name as the key because it is unique per-registry.
132 v8::Local<v8::Array> array = v8::Array::New(scriptState->isolate(), 4); 136 v8::Local<v8::Array> array = v8::Array::New(scriptState->isolate(), 5);
133 keepAlive(array, 0, prototype, definition->m_prototype, scriptState); 137 keepAlive(array, 0, prototype, definition->m_prototype, scriptState);
134 keepAlive(array, 1, connectedCallback, definition->m_connectedCallback, scri ptState); 138 keepAlive(array, 1, connectedCallback, definition->m_connectedCallback, scri ptState);
135 keepAlive(array, 2, disconnectedCallback, definition->m_disconnectedCallback , scriptState); 139 keepAlive(array, 2, disconnectedCallback, definition->m_disconnectedCallback , scriptState);
136 keepAlive(array, 3, attributeChangedCallback, definition->m_attributeChanged Callback, scriptState); 140 keepAlive(array, 3, attributeChangedCallback, definition->m_attributeChanged Callback, scriptState);
141 keepAlive(array, 4, adoptedCallback, definition->m_adoptedCallback, scriptSt ate);
137 v8CallOrCrash(map->Set(scriptState->context(), nameValue, array)); 142 v8CallOrCrash(map->Set(scriptState->context(), nameValue, array));
138 143
139 return definition; 144 return definition;
140 } 145 }
141 146
142 ScriptCustomElementDefinition::ScriptCustomElementDefinition( 147 ScriptCustomElementDefinition::ScriptCustomElementDefinition(
143 ScriptState* scriptState, 148 ScriptState* scriptState,
144 const CustomElementDescriptor& descriptor, 149 const CustomElementDescriptor& descriptor,
145 const v8::Local<v8::Object>& constructor, 150 const v8::Local<v8::Object>& constructor,
146 const v8::Local<v8::Object>& prototype, 151 const v8::Local<v8::Object>& prototype,
147 const v8::Local<v8::Function>& connectedCallback, 152 const v8::Local<v8::Function>& connectedCallback,
148 const v8::Local<v8::Function>& disconnectedCallback, 153 const v8::Local<v8::Function>& disconnectedCallback,
154 const v8::Local<v8::Function>& adoptedCallback,
149 const v8::Local<v8::Function>& attributeChangedCallback, 155 const v8::Local<v8::Function>& attributeChangedCallback,
150 const HashSet<AtomicString>& observedAttributes) 156 const HashSet<AtomicString>& observedAttributes)
151 : CustomElementDefinition(descriptor, observedAttributes) 157 : CustomElementDefinition(descriptor, observedAttributes)
152 , m_scriptState(scriptState) 158 , m_scriptState(scriptState)
153 , m_constructor(scriptState->isolate(), constructor) 159 , m_constructor(scriptState->isolate(), constructor)
154 { 160 {
155 } 161 }
156 162
157 HTMLElement* ScriptCustomElementDefinition::createElementSync( 163 HTMLElement* ScriptCustomElementDefinition::createElementSync(
158 Document& document, const QualifiedName& tagName, 164 Document& document, const QualifiedName& tagName,
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 return false; 223 return false;
218 ScriptState::Scope scope(m_scriptState.get()); 224 ScriptState::Scope scope(m_scriptState.get());
219 v8::Isolate* isolate = m_scriptState->isolate(); 225 v8::Isolate* isolate = m_scriptState->isolate();
220 226
221 // Step 5 says to rethrow the exception; but there is no one to 227 // Step 5 says to rethrow the exception; but there is no one to
222 // catch it. The side effect is to report the error. 228 // catch it. The side effect is to report the error.
223 v8::TryCatch tryCatch(isolate); 229 v8::TryCatch tryCatch(isolate);
224 tryCatch.SetVerbose(true); 230 tryCatch.SetVerbose(true);
225 231
226 Element* result = runConstructor(); 232 Element* result = runConstructor();
227 if (!result) 233
234 // To report exception thrown from runConstructor()
235 if (tryCatch.HasCaught())
228 return false; 236 return false;
229 237
238 // To report InvalidStateError Exception, when the constructor returns some differnt object
dominicc (has gone to gerrit) 2016/08/02 07:48:57 Spelling: different
230 if (result != element) { 239 if (result != element) {
231 V8ThrowException::throwException( 240 const String& message = "custom element constructors must call super() f irst and must "
232 V8ThrowException::createDOMException( 241 "not return a different object";
233 m_scriptState->isolate(), 242
dominicc (has gone to gerrit) 2016/08/02 07:48:57 Maybe delete this blank line; since the message an
234 InvalidStateError, 243 std::unique_ptr<SourceLocation> location = SourceLocation::fromFunction( constructor().As<v8::Function>());
235 "custom element constructors must call super() first and must " 244 v8::Local<v8::Value> exception = V8ThrowException::createDOMException(
236 "not return a different object", 245 m_scriptState->isolate(),
237 constructor()), 246 InvalidStateError,
238 m_scriptState->isolate()); 247 message,
248 constructor());
249 fireErrorEvent(m_scriptState.get(), message, exception, std::move(locati on));
239 return false; 250 return false;
240 } 251 }
241 252
242 return true; 253 return true;
243 } 254 }
244 255
245 Element* ScriptCustomElementDefinition::runConstructor() 256 Element* ScriptCustomElementDefinition::runConstructor()
246 { 257 {
247 v8::Isolate* isolate = m_scriptState->isolate(); 258 v8::Isolate* isolate = m_scriptState->isolate();
248 DCHECK(ScriptState::current(isolate) == m_scriptState); 259 DCHECK(ScriptState::current(isolate) == m_scriptState);
249 ExecutionContext* executionContext = m_scriptState->getExecutionContext(); 260 ExecutionContext* executionContext = m_scriptState->getExecutionContext();
250 v8::Local<v8::Value> result; 261 v8::Local<v8::Value> result;
251 if (!v8Call(V8ScriptRunner::callAsConstructor( 262 if (!v8Call(V8ScriptRunner::callAsConstructor(
252 isolate, 263 isolate,
253 constructor(), 264 constructor(),
254 executionContext, 265 executionContext,
255 0, 266 0,
256 nullptr), 267 nullptr),
257 result)) { 268 result)) {
258 return nullptr; 269 return nullptr;
259 } 270 }
260 return V8Element::toImplWithTypeCheck(isolate, result); 271 return V8Element::toImplWithTypeCheck(isolate, result);
261 } 272 }
262 273
274 void ScriptCustomElementDefinition::fireErrorEvent(ScriptState* scriptState, con st String& message, v8::Local<v8::Value> exception, std::unique_ptr<SourceLocati on> location)
275 {
276 ErrorEvent* event = ErrorEvent::create(message, std::move(location), &script State->world());
277 V8ErrorHandler::storeExceptionOnErrorEventWrapper(scriptState, event, except ion, scriptState->context()->Global());
278 ExecutionContext* executionContext = scriptState->getExecutionContext();
279 executionContext->reportException(event, NotSharableCrossOrigin);
280 }
281
263 v8::Local<v8::Object> ScriptCustomElementDefinition::constructor() const 282 v8::Local<v8::Object> ScriptCustomElementDefinition::constructor() const
264 { 283 {
265 DCHECK(!m_constructor.isEmpty()); 284 DCHECK(!m_constructor.isEmpty());
266 return m_constructor.newLocal(m_scriptState->isolate()); 285 return m_constructor.newLocal(m_scriptState->isolate());
267 } 286 }
268 287
269 v8::Local<v8::Object> ScriptCustomElementDefinition::prototype() const 288 v8::Local<v8::Object> ScriptCustomElementDefinition::prototype() const
270 { 289 {
271 DCHECK(!m_prototype.isEmpty()); 290 DCHECK(!m_prototype.isEmpty());
272 return m_prototype.newLocal(m_scriptState->isolate()); 291 return m_prototype.newLocal(m_scriptState->isolate());
273 } 292 }
274 293
275 // CustomElementDefinition 294 // CustomElementDefinition
276 ScriptValue ScriptCustomElementDefinition::getConstructorForScript() 295 ScriptValue ScriptCustomElementDefinition::getConstructorForScript()
277 { 296 {
278 return ScriptValue(m_scriptState.get(), constructor()); 297 return ScriptValue(m_scriptState.get(), constructor());
279 } 298 }
280 299
281 bool ScriptCustomElementDefinition::hasConnectedCallback() const 300 bool ScriptCustomElementDefinition::hasConnectedCallback() const
282 { 301 {
283 return !m_connectedCallback.isEmpty(); 302 return !m_connectedCallback.isEmpty();
284 } 303 }
285 304
286 bool ScriptCustomElementDefinition::hasDisconnectedCallback() const 305 bool ScriptCustomElementDefinition::hasDisconnectedCallback() const
287 { 306 {
288 return !m_disconnectedCallback.isEmpty(); 307 return !m_disconnectedCallback.isEmpty();
289 } 308 }
290 309
310 bool ScriptCustomElementDefinition::hasAdoptedCallback() const
311 {
312 return !m_adoptedCallback.isEmpty();
313 }
314
291 void ScriptCustomElementDefinition::runCallback( 315 void ScriptCustomElementDefinition::runCallback(
292 v8::Local<v8::Function> callback, 316 v8::Local<v8::Function> callback,
293 Element* element, int argc, v8::Local<v8::Value> argv[]) 317 Element* element, int argc, v8::Local<v8::Value> argv[])
294 { 318 {
295 DCHECK(ScriptState::current(m_scriptState->isolate()) == m_scriptState); 319 DCHECK(ScriptState::current(m_scriptState->isolate()) == m_scriptState);
296 v8::Isolate* isolate = m_scriptState->isolate(); 320 v8::Isolate* isolate = m_scriptState->isolate();
297 321
298 // Invoke custom element reactions 322 // Invoke custom element reactions
299 // https://html.spec.whatwg.org/multipage/scripting.html#invoke-custom-eleme nt-reactions 323 // https://html.spec.whatwg.org/multipage/scripting.html#invoke-custom-eleme nt-reactions
300 // If this throws any exception, then report the exception. 324 // If this throws any exception, then report the exception.
(...skipping 21 matching lines...) Expand all
322 346
323 void ScriptCustomElementDefinition::runDisconnectedCallback(Element* element) 347 void ScriptCustomElementDefinition::runDisconnectedCallback(Element* element)
324 { 348 {
325 if (!m_scriptState->contextIsValid()) 349 if (!m_scriptState->contextIsValid())
326 return; 350 return;
327 ScriptState::Scope scope(m_scriptState.get()); 351 ScriptState::Scope scope(m_scriptState.get());
328 v8::Isolate* isolate = m_scriptState->isolate(); 352 v8::Isolate* isolate = m_scriptState->isolate();
329 runCallback(m_disconnectedCallback.newLocal(isolate), element); 353 runCallback(m_disconnectedCallback.newLocal(isolate), element);
330 } 354 }
331 355
356 void ScriptCustomElementDefinition::runAdoptedCallback(Element* element)
357 {
358 if (!m_scriptState->contextIsValid())
359 return;
360 ScriptState::Scope scope(m_scriptState.get());
361 v8::Isolate* isolate = m_scriptState->isolate();
362 runCallback(m_adoptedCallback.newLocal(isolate), element);
363 }
364
332 void ScriptCustomElementDefinition::runAttributeChangedCallback( 365 void ScriptCustomElementDefinition::runAttributeChangedCallback(
333 Element* element, const QualifiedName& name, 366 Element* element, const QualifiedName& name,
334 const AtomicString& oldValue, const AtomicString& newValue) 367 const AtomicString& oldValue, const AtomicString& newValue)
335 { 368 {
336 if (!m_scriptState->contextIsValid()) 369 if (!m_scriptState->contextIsValid())
337 return; 370 return;
338 ScriptState::Scope scope(m_scriptState.get()); 371 ScriptState::Scope scope(m_scriptState.get());
339 v8::Isolate* isolate = m_scriptState->isolate(); 372 v8::Isolate* isolate = m_scriptState->isolate();
340 const int argc = 4; 373 const int argc = 4;
341 v8::Local<v8::Value> argv[argc] = { 374 v8::Local<v8::Value> argv[argc] = {
342 v8String(isolate, name.localName()), 375 v8String(isolate, name.localName()),
343 v8StringOrNull(isolate, oldValue), 376 v8StringOrNull(isolate, oldValue),
344 v8StringOrNull(isolate, newValue), 377 v8StringOrNull(isolate, newValue),
345 v8String(isolate, name.namespaceURI()), 378 v8String(isolate, name.namespaceURI()),
346 }; 379 };
347 runCallback(m_attributeChangedCallback.newLocal(isolate), element, 380 runCallback(m_attributeChangedCallback.newLocal(isolate), element,
348 argc, argv); 381 argc, argv);
349 } 382 }
350 383
351 } // namespace blink 384 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698