From 652ef2610436aee4d92310ae7efaa1fcdd86143b 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 | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/dom.bs b/dom.bs index b4c0abd3..5f58a909 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,34 @@ 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 +991,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 +1332,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 +1360,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: