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

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

Issue 2244203002: Fix "report the exception" in Custom Elements V1 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: yukishiino review 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
« no previous file with comments | « third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 182
183 // 6.1.3. through 6.1.9. 183 // 6.1.3. through 6.1.9.
184 checkConstructorResult(element, document, tagName, exceptionState); 184 checkConstructorResult(element, document, tagName, exceptionState);
185 if (exceptionState.hadException()) 185 if (exceptionState.hadException())
186 return nullptr; 186 return nullptr;
187 187
188 DCHECK_EQ(element->getCustomElementState(), CustomElementState::Custom); 188 DCHECK_EQ(element->getCustomElementState(), CustomElementState::Custom);
189 return toHTMLElement(element); 189 return toHTMLElement(element);
190 } 190 }
191 191
192 static AccessControlStatus accessControlStatusFromScriptOriginOptions(
193 const v8::ScriptOriginOptions& scriptOriginOptions)
194 {
195 if (scriptOriginOptions.IsOpaque())
196 return OpaqueResource;
197 if (scriptOriginOptions.IsSharedCrossOrigin())
198 return SharableCrossOrigin;
199 return NotSharableCrossOrigin;
haraken 2016/08/18 09:03:02 Can you create a helper function and share the cod
200 }
201
202 static void reportException(ScriptState* scriptState,
haraken 2016/08/18 09:03:03 Would you move this function to V8ThrowException?
Yuki 2016/08/18 09:34:26 I opposed putting this function in V8ThrowExceptio
203 v8::Local<v8::Value> exception,
204 const String& eventMessage,
205 std::unique_ptr<SourceLocation> location,
206 const v8::ScriptOriginOptions& scriptOriginOptions)
207 {
208 // Report an exception:
209 // https://html.spec.whatwg.org/multipage/webappapis.html#report-the-excepti on
210 ErrorEvent* event = ErrorEvent::create(eventMessage, std::move(location),
211 &scriptState->world());
212 V8ErrorHandler::storeExceptionOnErrorEventWrapper(scriptState, event,
213 exception, scriptState->context()->Global());
214 scriptState->getExecutionContext()->reportException(event,
215 accessControlStatusFromScriptOriginOptions(scriptOriginOptions));
216 }
217
218 static void reportException(ScriptState* scriptState,
219 v8::Local<v8::Value> exception,
220 const String& message,
221 v8::Local<v8::Function> function)
222 {
223 reportException(scriptState, exception, message,
224 SourceLocation::fromFunction(function),
225 function->GetScriptOrigin().Options());
226 }
227
228 static void reportException(ScriptState* scriptState,
229 ExceptionState& exceptionState,
230 v8::Local<v8::Function> function)
231 {
232 DCHECK(exceptionState.hadException());
233 v8::Local<v8::Value> exception = exceptionState.getException();
234 const String& message = exceptionState.message();
235 if (!message.isEmpty()) {
haraken 2016/08/18 09:03:02 It looks nasty to have this branch. Wouldn't it b
kojii 2016/08/18 10:15:14 There's no place to report, this is similar to unh
236 // The exception was created in C++ but was not thrown in JavaScript.
237 // It does not have proper SourceLocation nor ScriptOrigin, so use the
238 // given information.
239 reportException(scriptState, exception, message, function);
240 } else {
241 // The exception was thrown in JavaScript, caught, and set by
242 // rethrowV8Exception(). It has SourceLocation and ScriptOrigin.
243 v8::Isolate* isolate = scriptState->isolate();
244 v8::Local<v8::Message> message = v8::Exception::CreateMessage(
245 isolate, exception);
246 reportException(scriptState, exception,
247 toCoreStringWithNullCheck(message->Get()),
248 SourceLocation::fromMessage(isolate, message,
249 scriptState->getExecutionContext()),
250 message->GetScriptOrigin().Options());
251 }
252 exceptionState.clearException();
253 }
254
192 HTMLElement* ScriptCustomElementDefinition::createElementSync( 255 HTMLElement* ScriptCustomElementDefinition::createElementSync(
193 Document& document, const QualifiedName& tagName) 256 Document& document, const QualifiedName& tagName)
194 { 257 {
195 ScriptState::Scope scope(m_scriptState.get()); 258 ScriptState::Scope scope(m_scriptState.get());
196 v8::Isolate* isolate = m_scriptState->isolate(); 259 v8::Isolate* isolate = m_scriptState->isolate();
197 260
198 // When invoked from "create an element for a token": 261 // When invoked from "create an element for a token":
199 // https://html.spec.whatwg.org/multipage/syntax.html#create-an-element-for- the-token 262 // https://html.spec.whatwg.org/multipage/syntax.html#create-an-element-for- the-token
200 263
201 ExceptionState exceptionState(ExceptionState::ConstructionContext, 264 ExceptionState exceptionState(ExceptionState::ConstructionContext,
202 "CustomElement", constructor(), isolate); 265 "CustomElement", constructor(), isolate);
203 HTMLElement* element = createElementSync(document, tagName, exceptionState); 266 HTMLElement* element = createElementSync(document, tagName, exceptionState);
204 267
205 if (exceptionState.hadException() || !element) { 268 if (exceptionState.hadException()) {
269 DCHECK(!element);
206 // 7. If this step throws an exception, then report the exception, ... 270 // 7. If this step throws an exception, then report the exception, ...
207 { 271 reportException(m_scriptState.get(), exceptionState,
208 v8::TryCatch tryCatch(isolate); 272 constructor().As<v8::Function>());
haraken 2016/08/18 09:03:02 Why do you pass in constructor()? Here you're hand
kojii 2016/08/18 10:15:14 This code path comes from the document parser, whe
209 tryCatch.SetVerbose(true);
210 exceptionState.throwIfNeeded();
211 }
212
213 return CustomElement::createFailedElement(document, tagName); 273 return CustomElement::createFailedElement(document, tagName);
214 } 274 }
275 DCHECK(element);
215 return element; 276 return element;
216 } 277 }
217 278
218 // https://html.spec.whatwg.org/multipage/scripting.html#upgrades 279 // https://html.spec.whatwg.org/multipage/scripting.html#upgrades
219 bool ScriptCustomElementDefinition::runConstructor(Element* element) 280 bool ScriptCustomElementDefinition::runConstructor(Element* element)
220 { 281 {
221 if (!m_scriptState->contextIsValid()) 282 if (!m_scriptState->contextIsValid())
222 return false; 283 return false;
223 ScriptState::Scope scope(m_scriptState.get()); 284 ScriptState::Scope scope(m_scriptState.get());
224 v8::Isolate* isolate = m_scriptState->isolate(); 285 v8::Isolate* isolate = m_scriptState->isolate();
225 286
226 // Step 5 says to rethrow the exception; but there is no one to 287 // Step 5 says to rethrow the exception; but there is no one to
227 // catch it. The side effect is to report the error. 288 // catch it. The side effect is to report the error.
228 v8::TryCatch tryCatch(isolate); 289 v8::TryCatch tryCatch(isolate);
229 tryCatch.SetVerbose(true); 290 tryCatch.SetVerbose(true);
230 291
231 Element* result = runConstructor(); 292 Element* result = runConstructor();
232 293
233 // To report exception thrown from runConstructor() 294 // To report exception thrown from runConstructor()
234 if (tryCatch.HasCaught()) 295 if (tryCatch.HasCaught())
235 return false; 296 return false;
236 297
237 // To report InvalidStateError Exception, when the constructor returns some different object 298 // To report InvalidStateError Exception, when the constructor returns some different object
238 if (result != element) { 299 if (result != element) {
239 const String& message = "custom element constructors must call super() f irst and must " 300 const String& message = "custom element constructors must call super() f irst and must "
240 "not return a different object"; 301 "not return a different object";
241 std::unique_ptr<SourceLocation> location = SourceLocation::fromFunction( constructor().As<v8::Function>());
242 v8::Local<v8::Value> exception = V8ThrowException::createDOMException( 302 v8::Local<v8::Value> exception = V8ThrowException::createDOMException(
243 m_scriptState->isolate(), 303 m_scriptState->isolate(),
244 InvalidStateError, 304 InvalidStateError,
245 message); 305 message);
246 fireErrorEvent(m_scriptState.get(), message, exception, std::move(locati on)); 306 reportException(m_scriptState.get(), exception, message,
307 constructor().As<v8::Function>());
247 return false; 308 return false;
248 } 309 }
249 310
250 return true; 311 return true;
251 } 312 }
252 313
253 Element* ScriptCustomElementDefinition::runConstructor() 314 Element* ScriptCustomElementDefinition::runConstructor()
254 { 315 {
255 v8::Isolate* isolate = m_scriptState->isolate(); 316 v8::Isolate* isolate = m_scriptState->isolate();
256 DCHECK(ScriptState::current(isolate) == m_scriptState); 317 DCHECK(ScriptState::current(isolate) == m_scriptState);
257 ExecutionContext* executionContext = m_scriptState->getExecutionContext(); 318 ExecutionContext* executionContext = m_scriptState->getExecutionContext();
258 v8::Local<v8::Value> result; 319 v8::Local<v8::Value> result;
259 if (!v8Call(V8ScriptRunner::callAsConstructor( 320 if (!v8Call(V8ScriptRunner::callAsConstructor(
260 isolate, 321 isolate,
261 constructor(), 322 constructor(),
262 executionContext, 323 executionContext,
263 0, 324 0,
264 nullptr), 325 nullptr),
265 result)) { 326 result)) {
266 return nullptr; 327 return nullptr;
267 } 328 }
268 return V8Element::toImplWithTypeCheck(isolate, result); 329 return V8Element::toImplWithTypeCheck(isolate, result);
269 } 330 }
270 331
271 void ScriptCustomElementDefinition::fireErrorEvent(ScriptState* scriptState, con st String& message, v8::Local<v8::Value> exception, std::unique_ptr<SourceLocati on> location)
272 {
273 ErrorEvent* event = ErrorEvent::create(message, std::move(location), &script State->world());
274 V8ErrorHandler::storeExceptionOnErrorEventWrapper(scriptState, event, except ion, scriptState->context()->Global());
275 ExecutionContext* executionContext = scriptState->getExecutionContext();
276 executionContext->reportException(event, NotSharableCrossOrigin);
277 }
278
279 v8::Local<v8::Object> ScriptCustomElementDefinition::constructor() const 332 v8::Local<v8::Object> ScriptCustomElementDefinition::constructor() const
280 { 333 {
281 DCHECK(!m_constructor.isEmpty()); 334 DCHECK(!m_constructor.isEmpty());
282 return m_constructor.newLocal(m_scriptState->isolate()); 335 return m_constructor.newLocal(m_scriptState->isolate());
283 } 336 }
284 337
285 v8::Local<v8::Object> ScriptCustomElementDefinition::prototype() const 338 v8::Local<v8::Object> ScriptCustomElementDefinition::prototype() const
286 { 339 {
287 DCHECK(!m_prototype.isEmpty()); 340 DCHECK(!m_prototype.isEmpty());
288 return m_prototype.newLocal(m_scriptState->isolate()); 341 return m_prototype.newLocal(m_scriptState->isolate());
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 v8String(isolate, name.localName()), 425 v8String(isolate, name.localName()),
373 v8StringOrNull(isolate, oldValue), 426 v8StringOrNull(isolate, oldValue),
374 v8StringOrNull(isolate, newValue), 427 v8StringOrNull(isolate, newValue),
375 v8String(isolate, name.namespaceURI()), 428 v8String(isolate, name.namespaceURI()),
376 }; 429 };
377 runCallback(m_attributeChangedCallback.newLocal(isolate), element, 430 runCallback(m_attributeChangedCallback.newLocal(isolate), element,
378 argc, argv); 431 argc, argv);
379 } 432 }
380 433
381 } // namespace blink 434 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698