@@ -13,7 +13,7 @@ No Editor: true
13
13
!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>)
14
14
!Translation (non-normative): <span title=Japanese><a href=https://triple-underscore.github.io/DOM4-ja.html lang=ja hreflang=ja rel=alternate>日本語</a></span>
15
15
Logo : 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.
17
17
Ignored Terms : EmptyString, Array, Document
18
18
Boilerplate : omit feedback-header, omit conformance
19
19
</pre>
@@ -562,7 +562,7 @@ algorithm below.
562
562
the operation that caused <var> event</var> to be <a>dispatched</a> that it needs to be canceled.
563
563
564
564
<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 ,
566
566
and false otherwise.
567
567
568
568
<dt><code><var> event</var> . {{Event/composed}} </code>
@@ -1445,6 +1445,228 @@ can only be used to influence an ongoing one.
1445
1445
1446
1446
1447
1447
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
+
1448
1670
<h2 id=nodes>Nodes</h2>
1449
1671
1450
1672
<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
1963
2185
1964
2186
<li> If <var> node</var> is a {{DocumentFragment}}
1965
2187
<a>node</a> ,
1966
- <a>remove</a> its
2188
+ <a for=/ >remove</a> its
1967
2189
<a>children</a> with the
1968
2190
<i> suppress observers flag</i> set.
1969
2191
@@ -2135,7 +2357,7 @@ within a <var>parent</var>, run these steps:
2135
2357
<ol>
2136
2358
<li><p> Set <var> removedNodes</var> to a list solely containing <var> child</var> .
2137
2359
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
2139
2361
<i> suppress observers flag</i> set.
2140
2362
</ol>
2141
2363
@@ -2176,7 +2398,7 @@ To <dfn export for=Node id=concept-node-replace-all>replace all</dfn> with a
2176
2398
<a>node</a> , and a list containing <var> node</var>
2177
2399
otherwise.
2178
2400
2179
- <li> <a>Remove</a> all
2401
+ <li> <a for=/ >Remove</a> all
2180
2402
<var> parent</var> 's <a>children</a> , in
2181
2403
<a>tree order</a> , with the
2182
2404
<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
2201
2423
<li> If <var> child</var> 's <a for=tree>parent</a> is not <var> parent</var> , then <a>throw</a> a
2202
2424
{{NotFoundError}} .
2203
2425
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> .
2206
2427
2207
2428
<li> Return <var> child</var> .
2208
2429
<!-- 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
2212
2433
<p> <a lt="Other applicable specifications">Specifications</a> may define
2213
2434
<dfn export id=concept-node-remove-ext>removing steps</dfn> for all or some <a>nodes</a> . The
2214
2435
algorithm 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.
2216
2437
2217
2438
<p> To <dfn export id=concept-node-remove>remove</dfn> a <var> node</var> from a <var> parent</var> ,
2218
2439
with an optional <i> suppress observers flag</i> , run these steps:
@@ -2683,7 +2904,7 @@ steps:
2683
2904
<ol>
2684
2905
<li><p> If <a>context object</a> 's <a for=tree>parent</a> is null, then return.
2685
2906
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
2687
2908
<a for=tree>parent</a> .
2688
2909
</ol>
2689
2910
@@ -3842,8 +4063,8 @@ steps for each <a>descendant</a> <a>exclusive <code>Text</code> node</a> <var>no
3842
4063
<ol>
3843
4064
<li> Let <var> length</var> be <var> node</var> 's <a for=Node>length</a> .
3844
4065
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.
3847
4068
3848
4069
<li> Let <var> data</var> be the concatenation of the <a for=CharacterData>data</a> of
3849
4070
<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
3881
4102
<li><p> Set <var> currentNode</var> to its <a for=tree>next sibling</a> .
3882
4103
</ol>
3883
4104
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> .
3886
4107
</ol>
3887
4108
3888
4109
<p class="note"> {{Node/normalize()}} does not need to run any
@@ -4987,8 +5208,8 @@ these steps:
4987
5208
<ol>
4988
5209
<li><p> Let <var> oldDocument</var> be <var> node</var> 's <a for=Node>node document</a> .
4989
5210
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> .
4992
5213
4993
5214
<li>
4994
5215
<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
7159
7380
<a>node tree</a> when e.g. part of the content
7160
7381
it represents is mutated.
7161
7382
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
7163
7384
{{Node/normalize()}} method, and the <a>replace data</a> and <a lt="split a Text node">split</a>
7164
7385
algorithms for the hairy details.
7165
7386
@@ -7228,7 +7449,7 @@ the <a>boundary point</a>'s
7228
7449
<a>length</a> , inclusive. Algorithms that
7229
7450
modify a <a>tree</a> (in particular the
7230
7451
<a>insert</a> ,
7231
- <a>remove</a> ,
7452
+ <a for=/ >remove</a> ,
7232
7453
<a>replace data</a> , and
7233
7454
<a lt="split a Text node">split</a> algorithms) also modify
7234
7455
<a>ranges</a> associated with that
@@ -7816,7 +8037,7 @@ run these steps:
7816
8037
7817
8038
<li> For each <var> node</var> in <var> nodes to remove</var> ,
7818
8039
in <a>tree order</a> ,
7819
- <a>remove</a> <var> node</var> from
8040
+ <a for=/ >remove</a> <var> node</var> from
7820
8041
its <a for=tree>parent</a> .
7821
8042
7822
8043
<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
8384
8605
<!-- Because we're about to remove node from its parent. -->
8385
8606
8386
8607
<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
8388
8609
<a for=tree>parent</a> .
8389
8610
8390
8611
<!-- Browsers disagree on how to handle the case where the range is
@@ -9811,6 +10032,7 @@ Mounir Lamouri,
9811
10032
Michael™ Smith,
9812
10033
Mike Champion,
9813
10034
Mike Taylor,
10035
+ Mike West,
9814
10036
Ojan Vafai,
9815
10037
Oliver Nightingale,
9816
10038
Olli Pettay,
0 commit comments