From 04477fab41a9f6b20704397df89f837ee92cdbc6 Mon Sep 17 00:00:00 2001 From: Joey Arhar Date: Thu, 12 Nov 2020 06:17:04 +0000 Subject: [PATCH] Prototype of adding AbortController to addEventListener I2P: https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/9396JedBBOM This feature adds a new AbortSignal option, named "signal", to the options parameter of addEventListener. This new option can be used to remove the event listener with an AbortController by calling abort(). More context: https://github.com/whatwg/dom/issues/911 Bug: 1146467 Change-Id: I8ab1b93ec8be859c6876296fda4a9b808253c7d3 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2527343 Commit-Queue: Joey Arhar Reviewed-by: Mason Freed Cr-Commit-Position: refs/heads/master@{#826659} GitOrigin-RevId: f0bbc3f3ab2bf91bea606fbc5fda751f5e60a0d3 --- .../mojom/web_feature/web_feature.mojom | 1 + .../dom/events/add_event_listener_options.idl | 1 + .../add_event_listener_options_resolved.cc | 2 ++ .../renderer/core/dom/events/event_target.cc | 17 +++++++++++++ .../core/dom/events/event_target_test.cc | 15 ++++++++++++ .../platform/runtime_enabled_features.json5 | 4 ++++ ...ventListenerAbortController.tentative.html | 24 +++++++++++++++++++ 7 files changed, 64 insertions(+) create mode 100644 blink/web_tests/external/wpt/dom/abort/addEventListenerAbortController.tentative.html diff --git a/blink/public/mojom/web_feature/web_feature.mojom b/blink/public/mojom/web_feature/web_feature.mojom index 89efd55ee60d..e7e3732ae20d 100644 --- a/blink/public/mojom/web_feature/web_feature.mojom +++ b/blink/public/mojom/web_feature/web_feature.mojom @@ -3056,6 +3056,7 @@ enum WebFeature { kAdFrameDetected = 3727, kMediaStreamTrackGenerator = 3728, kMediaStreamTrackProcessor = 3729, + kAddEventListenerWithAbortSignal = 3730, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots. diff --git a/blink/renderer/core/dom/events/add_event_listener_options.idl b/blink/renderer/core/dom/events/add_event_listener_options.idl index 1d9e744e7f15..db453f85d632 100644 --- a/blink/renderer/core/dom/events/add_event_listener_options.idl +++ b/blink/renderer/core/dom/events/add_event_listener_options.idl @@ -7,4 +7,5 @@ dictionary AddEventListenerOptions : EventListenerOptions { boolean passive; boolean once = false; + [RuntimeEnabled=AddEventListenerAbortSignal] AbortSignal signal; }; diff --git a/blink/renderer/core/dom/events/add_event_listener_options_resolved.cc b/blink/renderer/core/dom/events/add_event_listener_options_resolved.cc index a4573199630a..b25a0c445065 100644 --- a/blink/renderer/core/dom/events/add_event_listener_options_resolved.cc +++ b/blink/renderer/core/dom/events/add_event_listener_options_resolved.cc @@ -18,6 +18,8 @@ AddEventListenerOptionsResolved::AddEventListenerOptionsResolved( setPassive(options->passive()); if (options->hasOnce()) setOnce(options->once()); + if (options->hasSignal()) + setSignal(options->signal()); // EventListenerOptions if (options->hasCapture()) setCapture(options->capture()); diff --git a/blink/renderer/core/dom/events/event_target.cc b/blink/renderer/core/dom/events/event_target.cc index 30c6510a4027..5576d440a71c 100644 --- a/blink/renderer/core/dom/events/event_target.cc +++ b/blink/renderer/core/dom/events/event_target.cc @@ -40,6 +40,7 @@ #include "third_party/blink/renderer/bindings/core/v8/js_based_event_listener.h" #include "third_party/blink/renderer/bindings/core/v8/js_event_listener.h" #include "third_party/blink/renderer/bindings/core/v8/source_location.h" +#include "third_party/blink/renderer/core/dom/abort_signal.h" #include "third_party/blink/renderer/core/dom/events/add_event_listener_options_resolved.h" #include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h" @@ -474,6 +475,8 @@ bool EventTarget::addEventListener( resolved_options->setOnce(options->once()); if (options->hasCapture()) resolved_options->setCapture(options->capture()); + if (options->hasSignal()) + resolved_options->setSignal(options->signal()); return addEventListener(event_type, event_listener, resolved_options); } @@ -530,6 +533,20 @@ bool EventTarget::AddEventListenerInternal( bool added = EnsureEventTargetData().event_listener_map.Add( event_type, listener, options, ®istered_listener); if (added) { + if (options->signal()) { + options->signal()->AddAlgorithm(WTF::Bind( + [](EventTarget* event_target, const AtomicString& event_type, + const EventListener* listener) { + event_target->removeEventListener(event_type, listener); + }, + WrapWeakPersistent(this), event_type, WrapWeakPersistent(listener))); + if (const LocalDOMWindow* executing_window = ExecutingWindow()) { + if (const Document* document = executing_window->document()) { + document->CountUse(WebFeature::kAddEventListenerWithAbortSignal); + } + } + } + AddedEventListener(event_type, registered_listener); if (IsA(listener) && IsInstrumentedForAsyncStack(event_type)) { diff --git a/blink/renderer/core/dom/events/event_target_test.cc b/blink/renderer/core/dom/events/event_target_test.cc index 18d1f5b40fc8..1d19bdafa097 100644 --- a/blink/renderer/core/dom/events/event_target_test.cc +++ b/blink/renderer/core/dom/events/event_target_test.cc @@ -69,4 +69,19 @@ TEST_F(EventTargetTest, UseCountBeforematch) { GetDocument().IsUseCounted(WebFeature::kBeforematchHandlerRegistered)); } +TEST_F(EventTargetTest, UseCountAbortSignal) { + EXPECT_FALSE( + GetDocument().IsUseCounted(WebFeature::kAddEventListenerWithAbortSignal)); + GetDocument().GetSettings()->SetScriptEnabled(true); + ClassicScript::CreateUnspecifiedScript(ScriptSourceCode(R"HTML( + const element = document.createElement('div'); + const ac = new AbortController(); + element.addEventListener( + 'test', () => {}, {signal: ac.signal}); + )HTML")) + ->RunScript(GetDocument().domWindow()); + EXPECT_TRUE( + GetDocument().IsUseCounted(WebFeature::kAddEventListenerWithAbortSignal)); +} + } // namespace blink diff --git a/blink/renderer/platform/runtime_enabled_features.json5 b/blink/renderer/platform/runtime_enabled_features.json5 index c3d70074ee96..a544197362ed 100644 --- a/blink/renderer/platform/runtime_enabled_features.json5 +++ b/blink/renderer/platform/runtime_enabled_features.json5 @@ -133,6 +133,10 @@ name: "AccessibilityUseAXPositionForDocumentMarkers", status: "test", }, + { + name: "AddEventListenerAbortSignal", + status: "experimental", + }, { name: "AddressSpace", status: "experimental", diff --git a/blink/web_tests/external/wpt/dom/abort/addEventListenerAbortController.tentative.html b/blink/web_tests/external/wpt/dom/abort/addEventListenerAbortController.tentative.html new file mode 100644 index 000000000000..36373507c192 --- /dev/null +++ b/blink/web_tests/external/wpt/dom/abort/addEventListenerAbortController.tentative.html @@ -0,0 +1,24 @@ + + + + + + + + + + + +