@@ -13,7 +13,7 @@ No Editor: true
1313!Tests : <a href=https://github.com/w3c/web-platform-tests/tree/master/dom>web-platform-tests dom/</a> (<a href=https://github.com/w3c/web-platform-tests/labels/dom>ongoing work</a>)
1414!Translation (non-normative): <span title=Japanese><a href=https://triple-underscore.github.io/DOM4-ja.html lang=ja hreflang=ja rel=alternate>日本語</a></span>
1515Logo : https://resources.whatwg.org/logo-dom.svg
16- Abstract : DOM defines a platform-neutral model for events and node trees.
16+ Abstract : DOM defines a platform-neutral model for events, aborting activities, and node trees.
1717Ignored Terms : EmptyString, Array, Document
1818Boilerplate : omit feedback-header, omit conformance
1919</pre>
@@ -562,7 +562,7 @@ algorithm below.
562562 the operation that caused <var> event</var> to be <a>dispatched</a> that it needs to be canceled.
563563
564564 <dt><code><var> event</var> . {{Event/defaultPrevented}} </code>
565- <dd> Returns true if {{Event/preventDefault()}} was invoked successfully to indicate cancellation ,
565+ <dd> Returns true if {{Event/preventDefault()}} was invoked successfully to indicate cancelation ,
566566 and false otherwise.
567567
568568 <dt><code><var> event</var> . {{Event/composed}} </code>
@@ -1445,6 +1445,228 @@ can only be used to influence an ongoing one.
14451445
14461446
14471447
1448+ <h2 id=aborting-ongoing-activities>Aborting ongoing activities</h3>
1449+
1450+ <p> Though promises do not have a built-in aborting mechanism, many APIs using them require abort
1451+ semantics. {{AbortController}} is meant to support these requirements by providing an
1452+ {{AbortController/abort()}} method that toggles the state of a corresponding {{AbortSignal}} object.
1453+ The API which wishes to support aborting can accept an {{AbortSignal}} object, and use its state to
1454+ determine how to proceed.
1455+
1456+ <p> APIs that rely upon {{AbortController}} are encouraged to respond to {{AbortController/abort()}}
1457+ by rejecting any unsettled promise with a new {{DOMException}} with [=error name=] "{{AbortError}} ".
1458+
1459+ <div class=example id=aborting-ongoing-activities-example>
1460+ <p> A hypothetical <code> doAmazingness({ ... })</code> method could accept an {{AbortSignal}} object
1461+ in order to support aborting as follows:
1462+
1463+ <pre><code class=lang-javascript>
1464+ const controller = new AbortController();
1465+ const signal = controller.signal;
1466+
1467+ startSpinner();
1468+
1469+ doAmazingness({ ..., signal })
1470+ .then(result => ...)
1471+ .catch(err => {
1472+ if (err.name == 'AbortError' ) return;
1473+ showUserErrorMessage();
1474+ })
1475+ .then(() => stopSpinner());
1476+
1477+ // …
1478+
1479+ controller.abort();</code></pre>
1480+
1481+ <p><code> doAmazingness</code> could be implemented as follows:
1482+
1483+ <pre><code class=lang-javascript>
1484+ function doAmazingness({signal}) {
1485+ return new Promise((resolve, reject) => {
1486+ // Begin doing amazingness, and call resolve(result) when done.
1487+ // But also, watch for signals:
1488+ signal.addEventListener('abort' , () => {
1489+ // Stop doing amazingness, and:
1490+ reject(new DOMException('Aborted' , 'AbortError' ));
1491+ });
1492+ });
1493+ }
1494+ </code></pre>
1495+
1496+ <p> APIs that require more granular control could extend both {{AbortController}} and
1497+ {{AbortSignal}} objects according to their needs.
1498+ </div>
1499+
1500+
1501+ <h3 id=interface-abortcontroller>Interface {{AbortController}}</h3>
1502+
1503+ <pre class="idl">
1504+ [Constructor,
1505+ Exposed=(Window,Worker)]
1506+ interface AbortController {
1507+ [SameObject] readonly attribute AbortSignal signal;
1508+
1509+ void abort();
1510+ };</pre>
1511+
1512+ <dl class=domintro>
1513+ <dt><code><var> controller</var> = new <a constructor lt=AbortController()>AbortController</a> ()</code>
1514+ <dd> Returns a new <var> controller</var> whose {{AbortController/signal}} is set to a newly
1515+ created {{AbortSignal}} object.
1516+
1517+ <dt><code><var> controller</var> . <a attribute for=AbortController>signal</a> </code>
1518+ <dd> Returns the {{AbortSignal}} object associated with this object.
1519+
1520+ <dt><code><var> controller</var> . <a method for=AbortController lt=abort()>abort</a> ()</code>
1521+ <dd> Invoking this method will set this object's {{AbortSignal}} 's [=AbortSignal/aborted flag=] and
1522+ signal to any observers that the associated activity is to be aborted.
1523+ </dl>
1524+
1525+ <p> An {{AbortController}} object has an associated <dfn for=AbortController>signal</dfn> (an
1526+ {{AbortSignal}} object).
1527+
1528+ <p> The <dfn constructor for=AbortController><code>AbortController()</code></dfn> constructor, when
1529+ invoked, must run these steps:
1530+
1531+ <ol>
1532+ <li><p> Let <var> signal</var> be a new {{AbortSignal}} object.
1533+
1534+ <li><p> Let <var> controller</var> be a new {{AbortController}} object whose
1535+ <a for=AbortController>signal</a> is <var> signal</var> .
1536+
1537+ <li><p> Return <var> controller</var> .
1538+ </ol>
1539+
1540+ <p> The <dfn attribute for=AbortController><code>signal</code></dfn> attribute's getter must return
1541+ <a>context object</a> 's <a for=AbortController>signal</a> .
1542+
1543+ <p> The <dfn method for=AbortController><code>abort()</code></dfn> method, when invoked, must
1544+ <a for=AbortSignal>signal abort</a> on <a>context object</a> 's <a for=AbortController>signal</a> .
1545+
1546+
1547+ <h3 id=interface-AbortSignal>Interface {{AbortSignal}}</h3>
1548+
1549+ <pre class="idl">
1550+ [Exposed=(Window,Worker)]
1551+ interface AbortSignal : EventTarget {
1552+ readonly attribute boolean aborted;
1553+
1554+ attribute EventHandler onabort;
1555+ };</pre>
1556+
1557+ <dl class=domintro>
1558+ <dt><code><var> signal</var> . <a attribute for=AbortSignal>aborted</a> </code>
1559+ <dd> Returns true if this {{AbortSignal}} 's {{AbortController}} has signaled to abort, and false
1560+ otherwise.
1561+ </dl>
1562+
1563+ <p> An {{AbortSignal}} object has an associated <dfn for=AbortSignal>aborted flag</dfn> . It is unset
1564+ unless specified otherwise.
1565+
1566+ <p> An {{AbortSignal}} object has associated <dfn for=AbortSignal>abort algorithms</dfn> , which is a
1567+ <a for=/>set</a> of algorithms which are to be executed when its [=AbortSignal/aborted flag=] is
1568+ set. Unless specified otherwise, its value is the empty set.
1569+
1570+ <p> To <dfn export for=AbortSignal>add</dfn> an algorithm <var> algorithm</var> to an {{AbortSignal}}
1571+ object <var> signal</var> , run these steps:
1572+
1573+ <ol>
1574+ <li><p> If <var> signal</var> 's <a for=AbortSignal>aborted flag</a> is set, then return.
1575+
1576+ <li><p> <a for=set>Append</a> <var> algorithm</var> to <var> signal</var> 's
1577+ <a for=AbortSignal>abort algorithms</a> .
1578+ </ol>
1579+
1580+ <p> To <dfn export for=AbortSignal>remove</dfn> an algorithm <var> algorithm</var> from an
1581+ {{AbortSignal}} <var> signal</var> , <a for=set>remove</a> <var> algorithm</var> from
1582+ <var> signal</var> 's <a for=AbortSignal>abort algorithms</a> .
1583+
1584+ <p class="note no-backref"> The [=AbortSignal/abort algorithms=] enable APIs with complex
1585+ requirements to react in a reasonable way to {{AbortController/abort()}} . For example, a given API's
1586+ [=AbortSignal/aborted flag=] might need to be propagated to a cross-thread environment, such as a
1587+ service worker.
1588+
1589+ <p> The <dfn attribute for=AbortSignal>aborted</dfn> attribute's getter must return true if
1590+ <a>context object</a> 's [=AbortSignal/aborted flag=] is set, and false otherwise.
1591+
1592+ <p class=note> Changes to an {{AbortSignal}} object represent the wishes of the corresponding
1593+ {{AbortController}} object, but an API observing the {{AbortSignal}} object can chose to ignore
1594+ them. For instance, if the operation has already completed.
1595+
1596+ <p> To <dfn export for=AbortSignal>signal abort</dfn> , given a {{AbortSignal}} object
1597+ <var> signal</var> , run these steps:
1598+
1599+ <ol>
1600+ <li><p> If <var> signal</var> 's [=AbortSignal/aborted flag=] is set, then return.
1601+
1602+ <li><p> Set <var> signal</var> 's [=AbortSignal/aborted flag=] .
1603+
1604+ <li><p> <a for=set>For each</a> <var> algorithm</var> in <var> signal</var> 's
1605+ [=AbortSignal/abort algorithms=] : run <var> algorithm</var> .
1606+
1607+ <li><p> <a for=set>Empty</a> <var> signal</var> 's <a for=AbortSignal>abort algorithms</a> .
1608+
1609+ <li><p> [=Fire an event=] named <code event for=AbortSignal> abort</code> at <var> signal</var> .
1610+ </ol>
1611+
1612+
1613+ <h3 id=abortcontroller-api-integration>Using {{AbortController}} and {{AbortSignal}} objects in
1614+ APIs</h3>
1615+
1616+ <p> Any web platform API using promises to represent operations that can be aborted must adhere to
1617+ the following:
1618+
1619+ <ul class=brief>
1620+ <li> Accept {{AbortSignal}} objects through a <code> signal</code> dictionary member.
1621+ <li> Convey that the operation got aborted by rejecting the promise with an "{{AbortError}} "
1622+ {{DOMException}} .
1623+ <li> Reject immediately if the {{AbortSignal}} 's [=AbortSignal/aborted flag=] is already set,
1624+ otherwise:
1625+ <li> Use the [=AbortSignal/abort algorithms=] mechanism to observe changes to the {{AbortSignal}}
1626+ object and do so in a manner that does not lead to clashes with other observers.
1627+ </ul>
1628+
1629+ <div class=example id=aborting-ongoing-activities-spec-example>
1630+ <p> The steps for a promise-returning method <code> doAmazingness(options)</code> could be as
1631+ follows:
1632+
1633+ <ol>
1634+ <li><p> Let |p| be [=a new promise=] .
1635+
1636+ <li>
1637+ <p> If |options|' <code> signal</code> member is present, then:
1638+
1639+ <ol>
1640+ <li><p> If |options|' <code>signal</code>' s [=AbortSignal/aborted flag=] is set, then [=reject=]
1641+ |p| with an "{{AbortError}} " {{DOMException}} and return |p|.
1642+
1643+ <li>
1644+ <p> [=AbortSignal/Add|Add the following abort steps=] to |options|' <code> signal</code> :
1645+
1646+ <ol>
1647+ <li><p> Stop doing amazing things.
1648+
1649+ <li><p> [=Reject=] |p| with an "{{AbortError}} " {{DOMException}} .
1650+ </ol>
1651+ </ol>
1652+
1653+ <li>
1654+ <p> Run these steps [=in parallel=] :
1655+
1656+ <ol>
1657+ <li><p> Let |amazingResult| be the result of doing some amazing things.
1658+
1659+ <li><p> [=Resolve=] |p| with |amazingResult|.
1660+ </ol>
1661+
1662+ <li><p> Return |p|.
1663+ </ol>
1664+ </div>
1665+
1666+ <p> APIs not using promises should still adhere to the above as much as possible.
1667+
1668+
1669+
14481670<h2 id=nodes>Nodes</h2>
14491671
14501672<h3 id=introduction-to-the-dom>Introduction to "The DOM"</h3>
@@ -1963,7 +2185,7 @@ before a <var>child</var>, with an optional <i>suppress observers flag</i>, run
19632185
19642186 <li> If <var> node</var> is a {{DocumentFragment}}
19652187 <a>node</a> ,
1966- <a>remove</a> its
2188+ <a for=/ >remove</a> its
19672189 <a>children</a> with the
19682190 <i> suppress observers flag</i> set.
19692191
@@ -2135,7 +2357,7 @@ within a <var>parent</var>, run these steps:
21352357 <ol>
21362358 <li><p> Set <var> removedNodes</var> to a list solely containing <var> child</var> .
21372359
2138- <li><p> <a>Remove</a> <var> child</var> from its <var> parent</var> with the
2360+ <li><p> <a for=/ >Remove</a> <var> child</var> from its <var> parent</var> with the
21392361 <i> suppress observers flag</i> set.
21402362 </ol>
21412363
@@ -2176,7 +2398,7 @@ To <dfn export for=Node id=concept-node-replace-all>replace all</dfn> with a
21762398 <a>node</a> , and a list containing <var> node</var>
21772399 otherwise.
21782400
2179- <li> <a>Remove</a> all
2401+ <li> <a for=/ >Remove</a> all
21802402 <var> parent</var> 's <a>children</a> , in
21812403 <a>tree order</a> , with the
21822404 <i> suppress observers flag</i> set.
@@ -2201,8 +2423,7 @@ To <dfn export id=concept-node-pre-remove>pre-remove</dfn> a <var>child</var> fr
22012423 <li> If <var> child</var> 's <a for=tree>parent</a> is not <var> parent</var> , then <a>throw</a> a
22022424 {{NotFoundError}} .
22032425
2204- <li> <a>Remove</a> <var> child</var>
2205- from <var> parent</var> .
2426+ <li> <a for=/>Remove</a> <var> child</var> from <var> parent</var> .
22062427
22072428 <li> Return <var> child</var> .
22082429 <!-- technically this is post-remove -->
@@ -2212,7 +2433,7 @@ To <dfn export id=concept-node-pre-remove>pre-remove</dfn> a <var>child</var> fr
22122433<p> <a lt="Other applicable specifications">Specifications</a> may define
22132434<dfn export id=concept-node-remove-ext>removing steps</dfn> for all or some <a>nodes</a> . The
22142435algorithm is passed <var ignore> removedNode</var> , and optionally <var ignore> oldParent</var> , as
2215- indicated in the <a>remove</a> algorithm below.
2436+ indicated in the <a for=/ >remove</a> algorithm below.
22162437
22172438<p> To <dfn export id=concept-node-remove>remove</dfn> a <var> node</var> from a <var> parent</var> ,
22182439with an optional <i> suppress observers flag</i> , run these steps:
@@ -2683,7 +2904,7 @@ steps:
26832904<ol>
26842905 <li><p> If <a>context object</a> 's <a for=tree>parent</a> is null, then return.
26852906
2686- <li><p> <a>Remove</a> the <a>context object</a> from <a>context object</a> 's
2907+ <li><p> <a for=/ >Remove</a> the <a>context object</a> from <a>context object</a> 's
26872908 <a for=tree>parent</a> .
26882909</ol>
26892910
@@ -3842,8 +4063,8 @@ steps for each <a>descendant</a> <a>exclusive <code>Text</code> node</a> <var>no
38424063<ol>
38434064 <li> Let <var> length</var> be <var> node</var> 's <a for=Node>length</a> .
38444065
3845- <li> If <var> length</var> is zero, then <a>remove</a> <var> node</var> and continue with the next
3846- <a>exclusive <code>Text</code> node</a> , if any.
4066+ <li> If <var> length</var> is zero, then <a for=/ >remove</a> <var> node</var> and continue with the
4067+ next <a>exclusive <code>Text</code> node</a> , if any.
38474068
38484069 <li> Let <var> data</var> be the concatenation of the <a for=CharacterData>data</a> of
38494070 <var> node</var> 's <a>contiguous exclusive <code>Text</code> nodes</a> (excluding itself), in
@@ -3881,8 +4102,8 @@ steps for each <a>descendant</a> <a>exclusive <code>Text</code> node</a> <var>no
38814102 <li><p> Set <var> currentNode</var> to its <a for=tree>next sibling</a> .
38824103 </ol>
38834104
3884- <li> <a>Remove</a> <var> node</var> 's <a>contiguous exclusive <code>Text</code> nodes</a> (excluding
3885- itself), in <a>tree order</a> .
4105+ <li> <a for=/ >Remove</a> <var> node</var> 's <a>contiguous exclusive <code>Text</code> nodes</a>
4106+ (excluding itself), in <a>tree order</a> .
38864107</ol>
38874108
38884109<p class="note"> {{Node/normalize()}} does not need to run any
@@ -4987,8 +5208,8 @@ these steps:
49875208<ol>
49885209 <li><p> Let <var> oldDocument</var> be <var> node</var> 's <a for=Node>node document</a> .
49895210
4990- <li><p> If <var> node</var> 's <a for=tree>parent</a> is not null, <a>remove</a> <var> node</var> from its
4991- <a for=tree>parent</a> .
5211+ <li><p> If <var> node</var> 's <a for=tree>parent</a> is not null, <a for=/ >remove</a> <var> node</var>
5212+ from its <a for=tree>parent</a> .
49925213
49935214 <li>
49945215 <p> If <var> document</var> is not <var> oldDocument</var> , then:
@@ -7159,7 +7380,7 @@ might itself be modified as part of the mutation to the
71597380<a>node tree</a> when e.g. part of the content
71607381it represents is mutated.
71617382
7162- <p class="note no-backref"> See the <a>insert</a> and <a>remove</a> algorithms, the
7383+ <p class="note no-backref"> See the <a>insert</a> and <a for=/ >remove</a> algorithms, the
71637384{{Node/normalize()}} method, and the <a>replace data</a> and <a lt="split a Text node">split</a>
71647385algorithms for the hairy details.
71657386
@@ -7228,7 +7449,7 @@ the <a>boundary point</a>'s
72287449<a>length</a> , inclusive. Algorithms that
72297450modify a <a>tree</a> (in particular the
72307451<a>insert</a> ,
7231- <a>remove</a> ,
7452+ <a for=/ >remove</a> ,
72327453<a>replace data</a> , and
72337454<a lt="split a Text node">split</a> algorithms) also modify
72347455<a>ranges</a> associated with that
@@ -7816,7 +8037,7 @@ run these steps:
78168037
78178038 <li> For each <var> node</var> in <var> nodes to remove</var> ,
78188039 in <a>tree order</a> ,
7819- <a>remove</a> <var> node</var> from
8040+ <a for=/ >remove</a> <var> node</var> from
78208041 its <a for=tree>parent</a> .
78218042
78228043 <li> If <var> original end node</var> is a {{Text}} ,
@@ -8384,7 +8605,7 @@ the result of <a lt="clone the contents of a range">cloning the contents</a> of
83848605 <!-- Because we're about to remove node from its parent. -->
83858606
83868607 <li> If <var> node</var> 's <a for=tree>parent</a> is not
8387- null, <a>remove</a> <var> node</var> from its
8608+ null, <a for=/ >remove</a> <var> node</var> from its
83888609 <a for=tree>parent</a> .
83898610
83908611 <!-- Browsers disagree on how to handle the case where the range is
@@ -9811,6 +10032,7 @@ Mounir Lamouri,
981110032Michael™ Smith,
981210033Mike Champion,
981310034Mike Taylor,
10035+ Mike West,
981410036Ojan Vafai,
981510037Oliver Nightingale,
981610038Olli Pettay,
0 commit comments