Skip to content

Commit da4e899

Browse files
committed
Remove quadratic behavior from clone a node
Strictly speaking this should be an editorial change, but as it's fairly significant not marking it as such. This improves integration with HTML as well. As part of this change we move the shadow tree behavior under creating the element clone as that is a more logical fit. Unfortunately subtree has to be passed everywhere as HTML needs it for its template element logic. That's also why clone a node's children is exported. Corresponding HTML PR: SOON. Fixes #1219. Closes #1220.
1 parent 10dbae4 commit da4e899

File tree

1 file changed

+86
-61
lines changed

1 file changed

+86
-61
lines changed

dom.bs

Lines changed: 86 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -4097,7 +4097,7 @@ interface Node : EventTarget {
40974097
[CEReactions] attribute DOMString? textContent;
40984098
[CEReactions] undefined normalize();
40994099

4100-
[CEReactions, NewObject] Node cloneNode(optional boolean deep = false);
4100+
[CEReactions, NewObject] Node cloneNode(optional boolean subtree = false);
41014101
boolean isEqualNode(Node? otherNode);
41024102
boolean isSameNode(Node? otherNode); // legacy alias of ===
41034103

@@ -4521,9 +4521,9 @@ each <a for=tree>descendant</a> <a>exclusive <code>Text</code> node</a> <var>nod
45214521
<hr>
45224522

45234523
<dl class=domintro>
4524-
<dt><code><var>node</var> . <a method for=Node lt=cloneNode()>cloneNode([<var>deep</var> = false])</a></code>
4524+
<dt><code><var>node</var> . <a method for=Node lt=cloneNode()>cloneNode([<var>subtree</var> = false])</a></code>
45254525
<dd>Returns a copy of <var>node</var>. If
4526-
<var>deep</var> is true, the copy also includes the
4526+
<var>subtree</var> is true, the copy also includes the
45274527
<var>node</var>'s <a for=tree>descendants</a>.
45284528

45294529
<dt><code><var>node</var> . {{Node/isEqualNode(otherNode)}}</code>
@@ -4533,33 +4533,82 @@ each <a for=tree>descendant</a> <a>exclusive <code>Text</code> node</a> <var>nod
45334533

45344534
<div class=impl>
45354535

4536+
<div algorithm>
45364537
<a lt="Other applicable specifications">Specifications</a> may define
45374538
<dfn export id=concept-node-clone-ext>cloning steps</dfn> for all or some <a for=/>nodes</a>. The
4538-
algorithm is passed <var>copy</var>, <var>node</var>, <var>document</var>, and an optional
4539-
<i>clone children flag</i>, as indicated in the <a lt="clone a node">clone</a> algorithm.
4539+
algorithm is passed <var ignore>node</var>, <var ignore>copy</var>, and <var ignore>subtree</var> as
4540+
indicated in the <a>clone a node</a> algorithm.
45404541

4541-
<p class=note>HTML defines <a>cloning steps</a> for <{script}> and <{input}>
4542-
elements. SVG ought to do the same for its <{script}> elements, but does not call this out
4543-
at the moment.
4542+
<p class=note>HTML defines <a>cloning steps</a> for several elements, such as <{input}>, <{script}>,
4543+
and <{template}>. SVG ought to do the same for its <{script}> elements, but does not.
4544+
</div>
45444545

4545-
<p>To <dfn export id=concept-node-clone lt="clone a node" local-lt="clone">clone</dfn> a
4546-
<var>node</var>, with an optional <var>document</var> and <i>clone children flag</i>, run these
4547-
steps:
4548-
<!-- This algorithm is used by dom-Node-cloneNode, dom-Document-importNode,
4549-
dom-Range-extractContents, dom-Range-cloneContents -->
4546+
<div algorithm="clone a node">
4547+
<p>To <dfn export id=concept-node-clone>clone a node</dfn> given a <a for=/>node</a> <var>node</var>
4548+
and an optional <a for=/>document</a> <dfn export for="clone a node"><var>document</var></dfn>
4549+
(default <var>node</var>'s <a for=Node>node document</a>), boolean
4550+
<dfn export for="clone a node"><var>subtree</var></dfn> (default false), and
4551+
<a for=/>node</a>-or-null <dfn export for="clone a node"><var>parent</var></dfn> (default null):
45504552

45514553
<ol>
4552-
<li><p>If <var>document</var> is not given, then set <var>document</var> to <var>node</var>'s
4553-
<a for=Node>node document</a>.
4554+
<li><p><a for=/>Assert</a>: <var>node</var> is not a <a for=/>document</a> or <var>node</var> is
4555+
<var>document</var>.
45544556

4555-
<li><a for=/>Assert</a>: <var>node</var> is not a <a for=/>document</a> or <var>node</var> is
4557+
<li><p>Let <var>copy</var> be the result of <a>cloning a single node</a> given <var>node</var> and
45564558
<var>document</var>.
45574559

4560+
<li><p>If <var>parent</var> is non-null, then <a for=/>append</a> <var>copy</var> to
4561+
<var>parent</var>.
4562+
4563+
<li><p>Run any <a>cloning steps</a> defined for <var>node</var> in
4564+
<a>other applicable specifications</a> and pass <var>node</var>, <var>copy</var>, and
4565+
<var>subtree</var> as parameters.
4566+
4567+
<li><p>If <var>subtree</var> is true, then for each <var>child</var> of <var>node</var>'s
4568+
<a for=tree>children</a>, in <a>tree order</a>: <a>clone a node</a> given <var>child</var> with
4569+
<a for="clone a node"><i>document</i></a> set to <var>document</var>,
4570+
<a for="clone a node"><i>subtree</i></a> set to <var>subtree</var>, and
4571+
<a for="clone a node"><i>parent</i></a> set to <var>copy</var>.
4572+
4573+
<li>
4574+
<p>If <var>node</var> is an <a for=/>element</a>, <a for=Element>shadow host</a>, and its
4575+
<a for=Element>shadow root</a>'s <a for=ShadowRoot>clonable</a> is true:
4576+
4577+
<ol>
4578+
<li><p><a for=/>Assert</a>: <var>copy</var> is not a <a for=Element>shadow host</a>.
4579+
4580+
<li><p><a>Attach a shadow root</a> with <var>copy</var>, <var>node</var>'s
4581+
<a for=Element>shadow root</a>'s <a for=ShadowRoot>mode</a>, true, <var>node</var>'s
4582+
<a for=Element>shadow root</a>'s <a for=ShadowRoot>serializable</a>, <var>node</var>'s
4583+
<a for=Element>shadow root</a>'s <a for=ShadowRoot>delegates focus</a>, and <var>node</var>'s
4584+
<a for=Element>shadow root</a>'s <a for=ShadowRoot>slot assignment</a>.
4585+
4586+
<li><p>Set <var>copy</var>'s <a for=Element>shadow root</a>'s <a for=ShadowRoot>declarative</a>
4587+
to <var>node</var>'s <a for=Element>shadow root</a>'s <a for=ShadowRoot>declarative</a>.
4588+
4589+
<li><p>For each <var>child</var> of <var>node</var>'s <a for=Element>shadow root</a>'s
4590+
<a for=tree>children</a>, in <a>tree order</a>: <a>clone a node</a> given <var>child</var> with
4591+
<a for="clone a node"><i>document</i></a> set to <var>document</var>,
4592+
<a for="clone a node"><i>subtree</i></a> set to <var>subtree</var>, and
4593+
<a for="clone a node"><i>parent</i></a> set to <var>copy</var>'s <a for=Element>shadow root</a>.
4594+
</ol>
4595+
4596+
<li><p>Return <var>copy</var>.
4597+
</ol>
4598+
</div>
4599+
4600+
<div algorithm>
4601+
<p>To <dfn>clone a single node</dfn> given a <a for=/>node</a> <var>node</var> and
4602+
<a for=/>document</a> <var>document</var>:
4603+
4604+
<ol>
4605+
<li><p>Let <var>copy</var> be null.
4606+
45584607
<li>
45594608
<p>If <var>node</var> is an <a for=/>element</a>:
45604609

45614610
<ol>
4562-
<li><p>Let <var>copy</var> be the result of <a>creating an element</a>, given
4611+
<li><p>Set <var>copy</var> to the result of <a>creating an element</a>, given
45634612
<var>document</var>, <var>node</var>'s <a for=Element>local name</a>, <var>node</var>'s
45644613
<a for=Element>namespace</a>, <var>node</var>'s <a for=Element>namespace prefix</a>, and
45654614
<var>node</var>'s <a><code>is</code> value</a>.
@@ -4569,16 +4618,15 @@ dom-Range-extractContents, dom-Range-cloneContents -->
45694618
<a for=Element>attribute list</a>:
45704619

45714620
<ol>
4572-
<li><p>Let <var>copyAttribute</var> be a <a>clone</a> of <var>attribute</var>.
4621+
<li><p>Let <var>copyAttribute</var> be the result of <a>cloning a single node</a> given
4622+
<var>attribute</var> and <var>document</var>.
45734623

45744624
<li><p><a lt="append an attribute">Append</a> <var>copyAttribute</var> to <var>copy</var>.
45754625
</ol>
4576-
</li>
45774626
</ol>
4578-
</li>
45794627

45804628
<li>
4581-
<p>Otherwise, let <var>copy</var> be a <a for=/>node</a> that <a>implements</a> the same
4629+
<p>Otherwise, set <var>copy</var> to a <a for=/>node</a> that <a>implements</a> the same
45824630
interfaces as <var>node</var>, and fulfills these additional requirements, switching on the
45834631
interface <var>node</var> <a>implements</a>:
45844632

@@ -4608,54 +4656,28 @@ dom-Range-extractContents, dom-Range-cloneContents -->
46084656
<dd><p>Do nothing.
46094657
</dl>
46104658

4659+
<li><p><a for=/>Assert</a>: <var>copy</var> is a <a for=/>node</a>.
4660+
46114661
<li><p>If <var>node</var> is a <a for=/>document</a>, then set <var>document</var> to
46124662
<var>copy</var>.
46134663

46144664
<li><p>Set <var>copy</var>'s <a for=Node>node document</a> to <var>document</var>.
46154665

4616-
<li><p>Run any <a>cloning steps</a> defined for <var>node</var> in
4617-
<a>other applicable specifications</a> and pass <var>copy</var>, <var>node</var>,
4618-
<var>document</var>, and the <i>clone children flag</i> if set, as parameters.
4619-
4620-
<li><p>If the <i>clone children flag</i> is set, then for each <a for=tree>child</a>
4621-
<var>child</var> of <var>node</var>, in <a>tree order</a>: <a>append</a> the result of
4622-
<a lt="clone a node">cloning</a> <var>child</var> with <var>document</var> and the
4623-
<i>clone children flag</i> set, to <var>copy</var>.
4624-
4625-
<li>
4626-
<p>If <var>node</var> is a <a for=Element>shadow host</a> whose <a for=/>shadow root</a>'s
4627-
<a for=ShadowRoot>clonable</a> is true:
4628-
4629-
<ol>
4630-
<li><p>Assert: <var>copy</var> is not a <a for=Element>shadow host</a>.
4631-
4632-
<li><p>Run <a>attach a shadow root</a> with <var>copy</var>, <var>node</var>'s
4633-
<a for=Element>shadow root</a>'s <a for=ShadowRoot>mode</a>, true, <var>node</var>'s
4634-
<a for=Element>shadow root</a>'s <a for=ShadowRoot>serializable</a>, <var>node</var>'s
4635-
<a for=Element>shadow root</a>'s <a for=ShadowRoot>delegates focus</a>, and <var>node</var>'s
4636-
<a for=Element>shadow root</a>'s <a for=ShadowRoot>slot assignment</a>.
4637-
4638-
<li><p>Set <var>copy</var>'s <a for=Element>shadow root</a>'s <a for=ShadowRoot>declarative</a>
4639-
to <var>node</var>'s <a for=Element>shadow root</a>'s <a for=ShadowRoot>declarative</a>.
4640-
4641-
<li><p>For each <a for=tree>child</a> <var>child</var> of <var>node</var>'s
4642-
<a for=Element>shadow root</a>, in <a>tree order</a>: <a>append</a> the result of
4643-
<a lt="clone a node">cloning</a> <var>child</var> with <var>document</var> and the
4644-
<i>clone children flag</i> set, to <var>copy</var>'s <a for=Element>shadow root</a>.
4645-
</ol>
4646-
46474666
<li><p>Return <var>copy</var>.
46484667
</ol>
4668+
</div>
46494669

4650-
<p>The <dfn method for=Node><code>cloneNode(<var>deep</var>)</code></dfn> method steps are:
4670+
<div algorithm>
4671+
<p>The <dfn method for=Node><code>cloneNode(<var>subtree</var>)</code></dfn> method steps are:
46514672

46524673
<ol>
46534674
<li><p>If <a>this</a> is a <a for=/>shadow root</a>, then <a>throw</a> a
46544675
"{{NotSupportedError!!exception}}" {{DOMException}}.
46554676

4656-
<li><p>Return a <a lt="clone a node">clone</a> of <a>this</a>, with the
4657-
<i>clone children flag</i> set if <var>deep</var> is true.
4677+
<li><p>Return the result of <a>cloning a node</a> given <a>this</a> with
4678+
<a for="clone a node"><i>subtree</i></a> set to <var>subtree</var>.
46584679
</ol>
4680+
</div>
46594681

46604682
<p>A <a for=/>node</a> <var>A</var> <dfn export for=Node id=concept-node-equals>equals</dfn> a
46614683
<a for=/>node</a> <var>B</var> if all of the following conditions are true:
@@ -5127,7 +5149,7 @@ interface Document : Node {
51275149
[NewObject] Comment createComment(DOMString data);
51285150
[NewObject] ProcessingInstruction createProcessingInstruction(DOMString target, DOMString data);
51295151

5130-
[CEReactions, NewObject] Node importNode(Node node, optional boolean deep = false);
5152+
[CEReactions, NewObject] Node importNode(Node node, optional boolean subtree = false);
51315153
[CEReactions] Node adoptNode(Node node);
51325154

51335155
[NewObject] Attr createAttribute(DOMString localName);
@@ -5554,9 +5576,9 @@ method steps are:
55545576
<hr>
55555577

55565578
<dl class=domintro>
5557-
<dt><var>clone</var> = <var>document</var> . <a method for=Document lt=importNode()>importNode(<var>node</var> [, <var>deep</var> = false])</a>
5579+
<dt><var>clone</var> = <var>document</var> . <a method for=Document lt=importNode()>importNode(<var>node</var> [, <var>subtree</var> = false])</a>
55585580
<dd>
5559-
<p>Returns a copy of <var>node</var>. If <var>deep</var> is true, the copy also includes the
5581+
<p>Returns a copy of <var>node</var>. If <var>subtree</var> is true, the copy also includes the
55605582
<var>node</var>'s <a for=tree>descendants</a>.
55615583

55625584
<p>If <var>node</var> is a <a for=/>document</a> or a <a for=/>shadow root</a>, throws a
@@ -5573,16 +5595,19 @@ method steps are:
55735595
"{{HierarchyRequestError!!exception}}" {{DOMException}}.
55745596
</dl>
55755597

5576-
<p>The <dfn method for=Document><code>importNode(<var>node</var>, <var>deep</var>)</code></dfn>
5598+
<div algorithm>
5599+
<p>The <dfn method for=Document><code>importNode(<var>node</var>, <var>subtree</var>)</code></dfn>
55775600
method steps are:
55785601

55795602
<ol>
55805603
<li><p>If <var>node</var> is a <a for=/>document</a> or <a for=/>shadow root</a>, then <a>throw</a>
55815604
a "{{NotSupportedError!!exception}}" {{DOMException}}.
55825605

5583-
<li><p>Return a <a lt="clone a node">clone</a> of <var>node</var>, with <a>this</a> and the
5584-
<i>clone children flag</i> set if <var>deep</var> is true.
5606+
<li><p>Return the result of <a>cloning a node</a> given <var>node</var> with
5607+
<a for="clone a node"><i>document</i></a> set to <a>this</a> and
5608+
<a for="clone a node"><i>subtree</i></a> set to <var>subtree</var>.
55855609
</ol>
5610+
</div>
55865611

55875612
<p><a lt="Other applicable specifications">Specifications</a> may define
55885613
<dfn export id=concept-node-adopt-ext>adopting steps</dfn> for all or some <a for=/>nodes</a>. The

0 commit comments

Comments
 (0)