diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart index a3bcc029cc3..4144280eb77 100644 --- a/sdk/lib/html/dart2js/html_dart2js.dart +++ b/sdk/lib/html/dart2js/html_dart2js.dart @@ -11722,6 +11722,10 @@ class _ChildrenElementList extends ListBase Iterator get iterator => toList().iterator; void addAll(Iterable iterable) { + _addAll(_element, iterable); + } + + static void _addAll(Element _element, Iterable iterable) { if (iterable is _ChildNodeListLazy) { iterable = new List.from(iterable); } @@ -11775,6 +11779,10 @@ class _ChildrenElementList extends ListBase } bool remove(Object? object) { + return _remove(_element, object); + } + + static bool _remove(Element _element, Object? object) { if (object is Element) { Element element = object; if (identical(element.parentNode, _element)) { @@ -11823,7 +11831,10 @@ class _ChildrenElementList extends ListBase return result; } - Element get first { + Element get first => _first(_element); + + @pragma('dart2js:noInline') + static Element _first(Element _element) { Element? result = _element._firstElementChild; if (result == null) throw new StateError("No elements"); return result; @@ -12965,6 +12976,16 @@ class Element extends Node */ List get children => new _ChildrenElementList._wrap(this); + List get _children => + // Element.children always returns the same list-like object which is a + // live view on the underlying DOM tree. So we can GVN it and remove it if + // unused. + JS( + 'returns:HtmlCollection;creates:HtmlCollection;' + 'depends:none;effects:none;gvn:true', + '#.children', + this); + set children(List value) { // Copy list first since we don't want liveness during iteration. var copy = value.toList(); @@ -14824,11 +14845,6 @@ class Element extends Node @JSName('childElementCount') int get _childElementCount native; - @JSName('children') - @Returns('HtmlCollection') - @Creates('HtmlCollection') - List get _children native; - @JSName('firstElementChild') Element? get _firstElementChild native; diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py index 623f5e9061a..014e8116258 100644 --- a/tools/dom/scripts/htmlrenamer.py +++ b/tools/dom/scripts/htmlrenamer.py @@ -387,7 +387,6 @@ private_html_members = monitored.Set( # Not prefixed but requires custom implementation for cross-browser compatibility. 'Document.visibilityState', 'Element.animate', - 'Element.children', 'Element.childElementCount', 'Element.firstElementChild', 'Element.getClientRects', @@ -791,6 +790,7 @@ removed_html_members = monitored.Set( 'DOMException.WRONG_DOCUMENT_ERR', 'Element.accessKey', 'Element.append', + 'Element.children', 'Element.dataset', 'Element.get:classList', 'Element.getAttributeNode', diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate index bdca7ed4d7b..b0d5ff880bd 100644 --- a/tools/dom/templates/html/impl/impl_Element.darttemplate +++ b/tools/dom/templates/html/impl/impl_Element.darttemplate @@ -46,6 +46,10 @@ class _ChildrenElementList extends ListBase Iterator get iterator => toList().iterator; void addAll(Iterable iterable) { + _addAll(_element, iterable); + } + + static void _addAll(Element _element, Iterable iterable) { if (iterable is _ChildNodeListLazy) { iterable = new List.from(iterable); } @@ -99,6 +103,10 @@ class _ChildrenElementList extends ListBase } bool remove(Object$NULLABLE object) { + return _remove(_element, object); + } + + static bool _remove(Element _element, Object$NULLABLE object) { if (object is Element) { Element element = object; if (identical(element.parentNode, _element)) { @@ -149,7 +157,10 @@ class _ChildrenElementList extends ListBase return result; } - Element get first { + Element get first => _first(_element); + + @pragma('dart2js:noInline') + static Element _first(Element _element) { Element$NULLABLE result = _element._firstElementChild; if (result == null) throw new StateError("No elements"); return result; @@ -667,6 +678,15 @@ $endif */ List get children => new _ChildrenElementList._wrap(this); + List get _children => + // Element.children always returns the same list-like object which is a + // live view on the underlying DOM tree. So we can GVN it and remove it if + // unused. + JS('returns:HtmlCollection;creates:HtmlCollection;' + 'depends:none;effects:none;gvn:true', + '#.children', + this); + set children(List value) { // Copy list first since we don't want liveness during iteration. var copy = value.toList();