Commit f40d6208 authored by Yuki Shiino's avatar Yuki Shiino Committed by Commit Bot

v8binding: Refactors legacyOutputDidListenersThrowFlag.

This patch moves IDBRequest::did_throw_in_event_handler_ to
Event::legacy_did_listeners_throw_flag_, which corresponds to
legacyOutputDidListenersThrowFlag in DOM standard:
https://dom.spec.whatwg.org/#concept-event-listener-inner-invoke
(See "Note: The legacyOutputDidListenersThrowFlag is only used by
Indexed Database API.")

There is no behavioral change. This is a small refactoring.

The reason is that it's smarter (and less fragile) to have a
bit flag inside Event to indicate exceptions than letting each
EventTarget maintain the flag. It's guaranteed that each Event
resets the bit flag, no dependency to EventTarget, ability to
detect whether any of listeners throws an exception, etc.

Change-Id: Ie37f9def9e37ac220ea755b1483656f922edfc37
Reviewed-on: https://chromium-review.googlesource.com/1179729Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarHayato Ito <hayato@chromium.org>
Reviewed-by: default avatarHitoshi Yoshida <peria@chromium.org>
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#584375}
parent 8c892903
......@@ -169,7 +169,7 @@ void V8AbstractEventListener::InvokeEventHandler(
return_value = CallListenerFunction(script_state, js_event, event);
if (try_catch.HasCaught())
event->target()->UncaughtExceptionInEventHandler();
event->LegacySetDidListenersThrowFlag();
if (!try_catch.CanContinue()) { // Result of TerminateExecution().
ExecutionContext* execution_context = ToExecutionContext(context);
......
......@@ -95,6 +95,7 @@ Event::Event(const AtomicString& event_type,
is_trusted_(false),
executed_listener_or_default_action_(false),
prevent_default_called_on_uncancelable_event_(false),
legacy_did_listeners_throw_flag_(false),
handling_passive_(PassiveMode::kNotPassiveDefault),
event_phase_(0),
current_target_(nullptr),
......
......@@ -261,6 +261,14 @@ class CORE_EXPORT Event : public ScriptWrappable {
executed_listener_or_default_action_ = true;
}
bool LegacyDidListenersThrow() const {
return legacy_did_listeners_throw_flag_;
}
void LegacySetDidListenersThrowFlag() {
legacy_did_listeners_throw_flag_ = true;
}
virtual DispatchEventResult DispatchEvent(EventDispatcher&);
void Trace(blink::Visitor*) override;
......@@ -320,6 +328,12 @@ class CORE_EXPORT Event : public ScriptWrappable {
// Whether preventDefault was called on uncancelable event.
unsigned prevent_default_called_on_uncancelable_event_ : 1;
// Whether any of listeners have thrown an exception or not.
// Corresponds to |legacyOutputDidListenersThrowFlag| in DOM standard.
// https://dom.spec.whatwg.org/#dispatching-events
// https://dom.spec.whatwg.org/#concept-event-listener-inner-invoke
unsigned legacy_did_listeners_throw_flag_ : 1;
PassiveMode handling_passive_;
unsigned short event_phase_;
Member<EventTarget> current_target_;
......
......@@ -596,8 +596,6 @@ DispatchEventResult EventTarget::DispatchEventInternal(Event& event) {
return dispatch_result;
}
void EventTarget::UncaughtExceptionInEventHandler() {}
static const AtomicString& LegacyType(const Event& event) {
if (event.type() == EventTypeNames::transitionend)
return EventTypeNames::webkitTransitionEnd;
......
......@@ -162,7 +162,6 @@ class CORE_EXPORT EventTarget : public ScriptWrappable {
// javascript originated calls. This method will validate and may adjust
// the Event object before dispatching.
bool dispatchEventForBindings(Event*, ExceptionState&);
virtual void UncaughtExceptionInEventHandler();
// Used for legacy "onEvent" attribute APIs.
bool SetAttributeEventListener(const AtomicString& event_type,
......
......@@ -694,7 +694,6 @@ DispatchEventResult IDBRequest::DispatchEventInternal(Event& event) {
if (transaction_ && ready_state_ == DONE)
transaction_->UnregisterRequest(this);
did_throw_in_event_handler_ = false;
DispatchEventResult dispatch_result =
IDBEventDispatcher::Dispatch(event, targets);
......@@ -703,7 +702,9 @@ DispatchEventResult IDBRequest::DispatchEventInternal(Event& event) {
// this request doesn't receive a second error) and before deactivating
// (which might trigger commit).
if (!request_aborted_) {
if (did_throw_in_event_handler_) {
// Transactions should be aborted after event dispatch if an exception was
// not caught.
if (event.LegacyDidListenersThrow()) {
transaction_->SetError(
DOMException::Create(DOMExceptionCode::kAbortError,
"Uncaught exception in event handler."));
......@@ -732,10 +733,6 @@ DispatchEventResult IDBRequest::DispatchEventInternal(Event& event) {
return dispatch_result;
}
void IDBRequest::UncaughtExceptionInEventHandler() {
did_throw_in_event_handler_ = true;
}
void IDBRequest::TransactionDidFinishAndDispatch() {
DCHECK(transaction_);
DCHECK(transaction_->IsVersionChange());
......
......@@ -294,7 +294,6 @@ class MODULES_EXPORT IDBRequest : public EventTargetWithInlineData,
// EventTarget
const AtomicString& InterfaceName() const override;
ExecutionContext* GetExecutionContext() const final;
void UncaughtExceptionInEventHandler() final;
// Called by a version change transaction that has finished to set this
// request back from DONE (following "upgradeneeded") back to PENDING (for
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment