Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for customisation of the "get the parent" algorithm #1230

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 72 additions & 1 deletion dom.bs
Original file line number Diff line number Diff line change
Expand Up @@ -908,9 +908,14 @@ for historical reasons.
<h3 id=interface-eventtarget>Interface {{EventTarget}}</h3>

<pre class=idl>
[Exposed=*]
interface EventTargetInternals {
attribute EventTarget parent;
};

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels a bit cumbersome API, one needs to pass a callback and then use its param to change a property value.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you prefer an init dictionary? One downside to this, as explained in #583 (comment) is that an init dictionary cannot allow setting the parent post-construction.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I suppose we could also do what new Promise() does, but it doesn't seem as extensible:

new EventTarget(setParent => {
  setParent(someParent);
}

I think as long as the capability is only granted to whoever constructed the EventTarget object I'm okay, so alternative proposals welcome.

[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 = {});
Expand All @@ -930,6 +935,8 @@ dictionary AddEventListenerOptions : EventListenerOptions {
boolean once = false;
AbortSignal signal;
};

callback EventTargetCallback = undefined (EventTargetInternals internals);
</pre>

<p>An {{EventTarget}} object represents a target to which an <a>event</a> can be <a>dispatched</a>
Expand All @@ -939,6 +946,70 @@ when something has occurred.
<a for=/>list</a> of zero or more <a>event listeners</a>). It is initially the empty list.
<!-- Intentionally not exported. -->

<p>Each {{EventTarget}} object has an associated <dfn for=EventTarget>attached internals</dfn> (null
or an {{EventTargetInternals}} object), initially null.

<p>Each {{EventTargetInternals}} object has an associated <dfn
for=EventTargetInternals>eventTarget</dfn> (an {{EventTarget}} object).

<p>Each {{EventTargetInternals}} object has an associated <dfn
for=EventTargetInternals>parent</dfn> (an {{EventTarget}} object).

<p>The <dfn export for=Event id=concept-eventtarget-constructor>new EventTarget(cb)</dfn> constructor steps are:

<ol>
<li><p>If <var>cb</var> is not null then:

<ol>
<li><p>Let <var>eventTargetInternals</var> a new {{EventTargetInternals}} instance.

<li><p>Set <var>eventTargetInternals</var>'s <a for=EventTargetInternals>eventTarget</a> to
<var>this</var>.

<li><a>Invoke</a> <var>cb</var> with « <var>eventTargetInternals</var> » and with <var>this</var>
as the <a>callback this value</a>.

<li><p>Set <var>this</var>'s <a for="EventTarget">attached internals</a> to
<var>eventTargetInternals</var>.
</ol>
</ol>

<p>The <a for=EventTargetInternals>parent</a> getter steps are to return <var>this</var>'s
<a for=EventTargetInternals>parent</a>.

<p>The <a for=EventTargetInternals>parent</a> setter steps are:

<ol>
<li><p>Let <var>theParent</var> be the given value.

<li><p>Let <var>targets</var> be a new <a for=/>list</a>.

<li>Append <var>this</var>'s <a for=EventTargetInternals>eventTarget</a> to <var>targets</var>.

<li><p>Let <var>parent</var> be <var>theParent</var>.

<li>
<p>While <var>parent</var> is non-null:</p>

<ol>
<li>If <var>targets</var> <a for=set>contains</a> <var>parent</var> then <a>throw</a> a
"{{HierarchyRequestError!!exception}}" {{DOMException}}.

<li>Append <var>parent</var> to <var>targets</var>.

<li>Let <var>parentInternals</var> be <var>parent</var>'s <a for=EventTarget>attached internals</a>.

<li>Set <var>parent</var> to <var>parentInternals</var>'s <a
for=EventTargetInternals>eventTarget</a>.

</ol>

<li>Set <var>this</var>'s <a for=EventTargetInternals>eventTarget</a> <a>get the parent</a>
algorithm to return <var>theParent</var>.

<li>Set <var>this</var>'s {{EventTargetInternals/parent}} to <var>theParent</var>.
</ol>

<p>An <dfn export id=concept-event-listener>event listener</dfn> can be used to observe a specific
<a>event</a> and consists of:

Expand Down