Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

Commit f9406a4

Browse files
committed
fix(shadowdom): fixes bug with nested content tags.
IntermediateContentTags were not properly accounting for nodes that pass through them.
1 parent 011d65f commit f9406a4

File tree

3 files changed

+44
-4
lines changed

3 files changed

+44
-4
lines changed

lib/core_dom/content_tag.dart

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ abstract class _ContentStrategy {
44
void attach();
55
void detach();
66
void insert(Iterable<dom.Node> nodes);
7+
Iterable<dom.Node> get nodes;
78
}
89

910
/**
@@ -14,6 +15,7 @@ class _ShadowDomContent implements _ContentStrategy {
1415
void attach(){}
1516
void detach(){}
1617
void insert(Iterable<dom.Node> nodes){}
18+
Iterable<dom.Node> get nodes => null;
1719
}
1820

1921
/**
@@ -35,6 +37,7 @@ class _RenderedTranscludingContent implements _ContentStrategy {
3537
dom.ScriptElement _endScript;
3638

3739
Iterable<dom.Node> _currNodes;
40+
Iterable<dom.Node> get nodes => _currNodes;
3841

3942
_RenderedTranscludingContent(this._content, this._sourceLightDom);
4043

@@ -50,7 +53,7 @@ class _RenderedTranscludingContent implements _ContentStrategy {
5053

5154
void insert(Iterable<dom.Node> nodes){
5255
final p = _endScript.parent;
53-
if (p != null && ! _equalToCurrNodes(nodes)) {
56+
if (p != null && !_equalToCurrNodes(nodes)) {
5457
_removeNodesBetweenScriptTags();
5558
_currNodes = nodes.toList();
5659
p.insertAllBefore(nodes, _endScript);
@@ -95,19 +98,22 @@ class _IntermediateTranscludingContent implements _ContentStrategy {
9598
final SourceLightDom _sourceLightDom;
9699
final DestinationLightDom _destinationLightDom;
97100
final Content _content;
101+
Iterable<dom.Node> _currNodes;
102+
Iterable<dom.Node> get nodes => _currNodes;
98103

99104
_IntermediateTranscludingContent(this._content, this._sourceLightDom, this._destinationLightDom);
100105

101106
void attach(){
102107
_sourceLightDom.redistribute();
108+
_destinationLightDom.addContentTag(_content);
103109
}
104110

105111
void detach(){
106112
_sourceLightDom.redistribute();
107113
}
108114

109115
void insert(Iterable<dom.Node> nodes){
110-
_content.element.nodes = nodes;
116+
_currNodes = nodes.toList();
111117
_destinationLightDom.redistribute();
112118
}
113119
}
@@ -127,6 +133,7 @@ class Content implements AttachAware, DetachAware {
127133
view.addContent(this);
128134
}
129135

136+
Iterable<dom.Node> get nodes => strategy._currNodes;
130137
void attach() => strategy.attach();
131138
void detach() => strategy.detach();
132139
void insert(Iterable<dom.Node> nodes) => strategy.insert(nodes);

lib/core_dom/light_dom.dart

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ abstract class SourceLightDom {
77
abstract class DestinationLightDom {
88
void redistribute();
99
void addViewPort(ViewPort viewPort);
10+
void addContentTag(Content content);
1011
bool hasRoot(dom.Element element);
1112
}
1213

@@ -15,6 +16,7 @@ class LightDom implements SourceLightDom, DestinationLightDom {
1516

1617
final List<dom.Node> _lightDomRootNodes = [];
1718
final Map<dom.Node, ViewPort> _ports = {};
19+
final Map<dom.Node, Content> _contentTags = {};
1820

1921
final Scope _scope;
2022

@@ -45,6 +47,10 @@ class LightDom implements SourceLightDom, DestinationLightDom {
4547
redistribute();
4648
}
4749

50+
void addContentTag(Content content) {
51+
_contentTags[content.element] = content;
52+
}
53+
4854
//TODO: vsavkin Add dirty flag after implementing view-scoped dom writes.
4955
void redistribute() {
5056
_scope.rootScope.domWrite(() {
@@ -82,7 +88,9 @@ class LightDom implements SourceLightDom, DestinationLightDom {
8288
if (_ports.containsKey(root)) {
8389
list.addAll(_ports[root].nodes);
8490
} else if (root is dom.ContentElement) {
85-
list.addAll(root.nodes);
91+
if (!_contentTags.containsKey(root))
92+
throw new Exception('Unmatched content tag encountered during redistibution.');
93+
list.addAll(_contentTags[root].nodes);
8694
} else {
8795
list.add(root);
8896
}
@@ -105,4 +113,4 @@ void redistributeNodes(Iterable<Content> contents, List<dom.Node> nodes) {
105113
nodes.removeWhere(matchSelector);
106114
}
107115
}
108-
}
116+
}

test/core_dom/compiler_spec.dart

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,8 @@ void main() {
312312
..bind(OuterComponent)
313313
..bind(InnerComponent)
314314
..bind(InnerInnerComponent)
315+
..bind(SimpleOuterComponent)
316+
..bind(SimpleInnerComponent)
315317
..bind(OuterWithDivComponent)
316318
..bind(OneTimeDecorator)
317319
..bind(OnceInside)
@@ -615,6 +617,13 @@ void main() {
615617
expect(element).toHaveText('OUTTER:INNER(OUTTER)');
616618
}));
617619

620+
it('should create simple nested components', async((VmTurnZone zone) {
621+
var element = _.compile(r'<div><simple-outer>TEXT</simple-outer></div>');
622+
microLeap();
623+
_.rootScope.apply();
624+
expect(element).toHaveText('OUTER(INNER(TEXT))');
625+
}));
626+
618627
it('should create a component that can access parent scope', async((VmTurnZone zone) {
619628
_.rootScope.context['fromParent'] = "should not be used";
620629
_.rootScope.context['val'] = "poof";
@@ -1744,6 +1753,22 @@ class InnerComponent implements ScopeAware {
17441753
InnerComponent();
17451754
}
17461755

1756+
@Component(
1757+
selector: 'simple-inner',
1758+
template: 'INNER(<content></content>)'
1759+
)
1760+
class SimpleInnerComponent implements ScopeAware {
1761+
Scope scope;
1762+
}
1763+
1764+
@Component(
1765+
selector: 'simple-outer',
1766+
template: 'OUTER(<simple-inner><content></content></simple-inner>)'
1767+
)
1768+
class SimpleOuterComponent implements ScopeAware {
1769+
Scope scope;
1770+
}
1771+
17471772
@Component(
17481773
selector: 'innerinner',
17491774
template: 'INNERINNER(<content select=".left"></content>,<content select=".right"></content>)'

0 commit comments

Comments
 (0)