From 8de9564c58e15c6835878e324c414b37730a1c7b Mon Sep 17 00:00:00 2001 From: Keith Cirkel Date: Mon, 9 Oct 2023 12:36:01 +0100 Subject: [PATCH] Allow for customisation of the "get the parent" algorithm This modifies the EventTarget IDL to allow assignment of a parent EventTarget to an EventTarget instance, while also modifying the "get the parent" algorithm to default to returning that instance. It also modifies the Event Dispatch algorithm to ensure that custom parent chains cannot cause loops. --- dom.bs | 48 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/dom.bs b/dom.bs index b4c0abd3..9f8c12ee 100644 --- a/dom.bs +++ b/dom.bs @@ -908,9 +908,16 @@ for historical reasons.

Interface {{EventTarget}}

+[Exposed=*]
+interface EventTargetInternals {
+  attribute EventTarget parent;
+}
+
+callback EventTargetCallback = undefined (EventTargetInternals internals);
+
 [Exposed=*]
 interface EventTarget {
-  constructor();
+  constructor(optional EventTargetCallback cb);
 
   undefined addEventListener(DOMString type, EventListener? callback, optional (AddEventListenerOptions or boolean) options = {});
   undefined removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options = {});
@@ -939,6 +946,33 @@ when something has occurred.
 list of zero or more event listeners). It is initially the empty list.
 
 
+

Each {{EventTarget}} object has an associated attached internals (null +or an {{EventTargetInternals}} object), initially null. + + +

When a constructor of the {{EventTarget}} +interface, or of an interface that inherits from the {{EventTarget}} interface, is invoked, these steps +must be run, given the arguments eventTargetCallback: + +

    +
  1. Let eventTarget be the result of creating a new object using this interface. + +

  2. Initialize eventTarget's {{EventTarget/event listener list}} attribute to the empty list. + +

  3. Initialize eventTarget's {{EventTarget/parent}} attribute to null. + +

  4. Let eventTargetInternals a new {{EventTargetInternals}} instance. + +

  5. If eventTargetCallback is not null, then invoke eventTargetCallback with « + eventTargetInternals and with eventTarget aas the callback this value. + +

  6. Set eventTarget's {{Eventtarget/attached internals}} attribute to + eventTargetInternals. + +

  7. Return eventTarget. +

+

An event listener can be used to observe a specific event and consists of: @@ -956,8 +990,9 @@ when something has occurred. object, an event listener is a broader concept as can be seen above.

Each {{EventTarget}} object also has an associated get the parent algorithm, -which takes an event event, and returns an {{EventTarget}} object. Unless -specified otherwise it returns null. +which takes an event event, and returns an {{EventTarget}}. Unless otherwise +specified otherwise it returns the associated attached internalsparent attribute.

Nodes, shadow roots, and documents override the get the parent algorithm. @@ -1296,6 +1331,8 @@ property of the event being dispatched.

  1. Let touchTargets be a new list. +

  2. Let parentTargets be a new list. +

  3. For each touchTarget of event's touch target list, append the result of retargeting touchTarget against target to touchTargets. @@ -1322,6 +1359,11 @@ property of the event being dispatched.

    While parent is non-null:

      +
    1. If parentTargets contains parent then throw a + "{{HierarchyRequestError!!exception}}" {{DOMException}}. + +
    2. Append parent to parentTargets. +
    3. If slottable is non-null: