mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 08:24:39 +00:00
[html] Better code for Element / _ChildrenElementList method
Two tricks let us compile this more efficiently: e.children.addAll(cs); Normally, get$children is inlined, returning a _ChildrenElementList wrapper, generating: new W._ChildrenElementList(e, e.children).addAll$1(0, cs); The two tricks: 1. Split _ChildElementList.addAll into an 'unwrap' that then calls the logic in '_addAll' 2. Add information about the properties of e.children that allow it to be removed. With these tricks, dart2js can optimize the code to this version that avoids allocating a wrapper or accessing the 'children' property: W._ChildrenElementList__addAll(e, cs); Change-Id: Ifdf533ac4f9790f09f87302e67304b5696097266 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/153904 Reviewed-by: Srujan Gaddam <srujzs@google.com> Commit-Queue: Stephen Adams <sra@google.com>
This commit is contained in:
parent
fdf4e364bf
commit
f997d62a6d
|
@ -11722,6 +11722,10 @@ class _ChildrenElementList extends ListBase<Element>
|
|||
Iterator<Element> get iterator => toList().iterator;
|
||||
|
||||
void addAll(Iterable<Element> iterable) {
|
||||
_addAll(_element, iterable);
|
||||
}
|
||||
|
||||
static void _addAll(Element _element, Iterable<Element> iterable) {
|
||||
if (iterable is _ChildNodeListLazy) {
|
||||
iterable = new List.from(iterable);
|
||||
}
|
||||
|
@ -11775,6 +11779,10 @@ class _ChildrenElementList extends ListBase<Element>
|
|||
}
|
||||
|
||||
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<Element>
|
|||
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<Element> get children => new _ChildrenElementList._wrap(this);
|
||||
|
||||
List<Node> 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<Element> 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<Node> get _children native;
|
||||
|
||||
@JSName('firstElementChild')
|
||||
Element? get _firstElementChild native;
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -46,6 +46,10 @@ class _ChildrenElementList extends ListBase<Element>
|
|||
Iterator<Element> get iterator => toList().iterator;
|
||||
|
||||
void addAll(Iterable<Element> iterable) {
|
||||
_addAll(_element, iterable);
|
||||
}
|
||||
|
||||
static void _addAll(Element _element, Iterable<Element> iterable) {
|
||||
if (iterable is _ChildNodeListLazy) {
|
||||
iterable = new List.from(iterable);
|
||||
}
|
||||
|
@ -99,6 +103,10 @@ class _ChildrenElementList extends ListBase<Element>
|
|||
}
|
||||
|
||||
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<Element>
|
|||
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<Element> get children => new _ChildrenElementList._wrap(this);
|
||||
|
||||
List<Node> 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<Element> value) {
|
||||
// Copy list first since we don't want liveness during iteration.
|
||||
var copy = value.toList();
|
||||
|
|
Loading…
Reference in a new issue