Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(170)

Side by Side Diff: pkg/third_party/html5lib/lib/dom.dart

Issue 224733003: Fix how document fragments are added on NodeList operations (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/third_party/html5lib/pubspec.yaml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /// A simple tree API that results from parsing html. Intended to be compatible 1 /// A simple tree API that results from parsing html. Intended to be compatible
2 /// with dart:html, but right now it resembles the classic JS DOM. 2 /// with dart:html, but right now it resembles the classic JS DOM.
3 library dom; 3 library dom;
4 4
5 import 'dart:collection'; 5 import 'dart:collection';
6 import 'package:source_maps/span.dart' show FileSpan; 6 import 'package:source_maps/span.dart' show FileSpan;
7 7
8 import 'src/constants.dart'; 8 import 'src/constants.dart';
9 import 'src/list_proxy.dart'; 9 import 'src/list_proxy.dart';
10 import 'src/token.dart'; 10 import 'src/token.dart';
(...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 644
645 Node _setParent(Node node) { 645 Node _setParent(Node node) {
646 // Note: we need to remove the node from its previous parent node, if any, 646 // Note: we need to remove the node from its previous parent node, if any,
647 // before updating its parent pointer to point at our parent. 647 // before updating its parent pointer to point at our parent.
648 node.remove(); 648 node.remove();
649 node.parent = _parent; 649 node.parent = _parent;
650 return node; 650 return node;
651 } 651 }
652 652
653 void add(Node value) { 653 void add(Node value) {
654 super.add(_setParent(value)); 654 if (value is DocumentFragment) {
655 addAll(value.nodes);
656 } else {
657 super.add(_setParent(value));
658 }
655 } 659 }
656 660
657 void addLast(Node value) => add(value); 661 void addLast(Node value) => add(value);
658 662
659 void addAll(Iterable<Node> collection) { 663 void addAll(Iterable<Node> collection) {
660 // Note: we need to be careful if collection is another NodeList. 664 // Note: we need to be careful if collection is another NodeList.
661 // In particular: 665 // In particular:
662 // 1. we need to copy the items before updating their parent pointers, 666 // 1. we need to copy the items before updating their parent pointers,
667 // _flattenDocFragments does a copy internally.
663 // 2. we should update parent pointers in reverse order. That way they 668 // 2. we should update parent pointers in reverse order. That way they
664 // are removed from the original NodeList (if any) from the end, which 669 // are removed from the original NodeList (if any) from the end, which
665 // is faster. 670 // is faster.
666 var list = (collection is NodeList || collection is! List) 671 var list = _flattenDocFragments(collection);
667 ? collection.toList() : collection as List;
668 for (var node in list.reversed) _setParent(node); 672 for (var node in list.reversed) _setParent(node);
669 super.addAll(list); 673 super.addAll(list);
670 } 674 }
671 675
672 void insert(int index, Node value) { 676 void insert(int index, Node value) {
673 super.insert(index, _setParent(value)); 677 if (value is DocumentFragment) {
678 insertAll(index, value.nodes);
679 } else {
680 super.insert(index, _setParent(value));
681 }
674 } 682 }
675 683
676 Node removeLast() => super.removeLast()..parent = null; 684 Node removeLast() => super.removeLast()..parent = null;
677 685
678 Node removeAt(int i) => super.removeAt(i)..parent = null; 686 Node removeAt(int i) => super.removeAt(i)..parent = null;
679 687
680 void clear() { 688 void clear() {
681 for (var node in this) node.parent = null; 689 for (var node in this) node.parent = null;
682 super.clear(); 690 super.clear();
683 } 691 }
684 692
685 void operator []=(int index, Node value) { 693 void operator []=(int index, Node value) {
686 this[index].parent = null; 694 if (value is DocumentFragment) {
687 super[index] = _setParent(value); 695 removeAt(index);
696 insertAll(index, value.nodes);
697 } else {
698 this[index].parent = null;
699 super[index] = _setParent(value);
700 }
688 } 701 }
689 702
690 // TODO(jmesserly): These aren't implemented in DOM _NodeListImpl, see 703 // TODO(jmesserly): These aren't implemented in DOM _NodeListImpl, see
691 // http://code.google.com/p/dart/issues/detail?id=5371 704 // http://code.google.com/p/dart/issues/detail?id=5371
692 void setRange(int start, int rangeLength, List<Node> from, 705 void setRange(int start, int rangeLength, List<Node> from,
693 [int startFrom = 0]) { 706 [int startFrom = 0]) {
694 if (from is NodeList) { 707 if (from is NodeList) {
695 // Note: this is presumed to make a copy 708 // Note: this is presumed to make a copy
696 from = from.sublist(startFrom, startFrom + rangeLength); 709 from = from.sublist(startFrom, startFrom + rangeLength);
697 } 710 }
698 // Note: see comment in [addAll]. We need to be careful about the order of 711 // Note: see comment in [addAll]. We need to be careful about the order of
699 // operations if [from] is also a NodeList. 712 // operations if [from] is also a NodeList.
700 for (int i = rangeLength - 1; i >= 0; i--) { 713 for (int i = rangeLength - 1; i >= 0; i--) {
701 this[start + i].parent = null; 714 this[start + i] = from[startFrom + i];
702 super[start + i] = _setParent(from[startFrom + i]);
703 } 715 }
704 } 716 }
705 717
706 void replaceRange(int start, int end, Iterable<Node> newContents) { 718 void replaceRange(int start, int end, Iterable<Node> newContents) {
707 removeRange(start, end); 719 removeRange(start, end);
708 insertAll(start, newContents); 720 insertAll(start, newContents);
709 } 721 }
710 722
711 void removeRange(int start, int rangeLength) { 723 void removeRange(int start, int rangeLength) {
712 for (int i = start; i < rangeLength; i++) this[i].parent = null; 724 for (int i = start; i < rangeLength; i++) this[i].parent = null;
713 super.removeRange(start, rangeLength); 725 super.removeRange(start, rangeLength);
714 } 726 }
715 727
716 void removeWhere(bool test(Element e)) { 728 void removeWhere(bool test(Element e)) {
717 for (var node in where(test)) { 729 for (var node in where(test)) {
718 node.parent = null; 730 node.parent = null;
719 } 731 }
720 super.removeWhere(test); 732 super.removeWhere(test);
721 } 733 }
722 734
723 void retainWhere(bool test(Element e)) { 735 void retainWhere(bool test(Element e)) {
724 for (var node in where((n) => !test(n))) { 736 for (var node in where((n) => !test(n))) {
725 node.parent = null; 737 node.parent = null;
726 } 738 }
727 super.retainWhere(test); 739 super.retainWhere(test);
728 } 740 }
729 741
730 void insertAll(int index, List<Node> nodes) { 742 void insertAll(int index, Iterable<Node> collection) {
731 for (var node in nodes) _setParent(node); 743 // Note: we need to be careful how we copy nodes. See note in addAll.
732 super.insertAll(index, nodes); 744 var list = _flattenDocFragments(collection);
745 for (var node in list.reversed) _setParent(node);
746 super.insertAll(index, list);
747 }
748
749 _flattenDocFragments(Iterable<Node> collection) {
750 // Note: this function serves two purposes:
751 // * it flattens document fragments
752 // * it creates a copy of [collections] when `collection is NodeList`.
753 var result = [];
754 for (var node in collection) {
755 if (node is DocumentFragment) {
756 result.addAll(node.nodes);
757 } else {
758 result.add(node);
759 }
760 }
761 return result;
733 } 762 }
734 } 763 }
735 764
736 765
737 /// An indexable collection of a node's descendants in the document tree, 766 /// An indexable collection of a node's descendants in the document tree,
738 /// filtered so that only elements are in the collection. 767 /// filtered so that only elements are in the collection.
739 // TODO(jmesserly): this was copied from dart:html 768 // TODO(jmesserly): this was copied from dart:html
740 // TODO(jmesserly): "implements List<Element>" is a workaround for analyzer bug. 769 // TODO(jmesserly): "implements List<Element>" is a workaround for analyzer bug.
741 class FilteredElementList extends IterableBase<Element> with ListMixin<Element> 770 class FilteredElementList extends IterableBase<Element> with ListMixin<Element>
742 implements List<Element> { 771 implements List<Element> {
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
927 956
928 class _ConcatTextVisitor extends TreeVisitor { 957 class _ConcatTextVisitor extends TreeVisitor {
929 final _str = new StringBuffer(); 958 final _str = new StringBuffer();
930 959
931 String toString() => _str.toString(); 960 String toString() => _str.toString();
932 961
933 visitText(Text node) { 962 visitText(Text node) {
934 _str.write(node.data); 963 _str.write(node.data);
935 } 964 }
936 } 965 }
OLDNEW
« no previous file with comments | « no previous file | pkg/third_party/html5lib/pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698