Nullable document/head/body
diff --git a/lib/dom.dart b/lib/dom.dart
index 8e0ea0b..cb4d63a 100644
--- a/lib/dom.dart
+++ b/lib/dom.dart
@@ -317,9 +317,9 @@
int get nodeType => Node.DOCUMENT_NODE;
// TODO(jmesserly): optmize this if needed
- Element get documentElement => querySelector('html')!;
- Element get head => documentElement.querySelector('head')!;
- Element get body => documentElement.querySelector('body')!;
+ Element? get documentElement => querySelector('html');
+ Element? get head => documentElement?.querySelector('head');
+ Element? get body => documentElement?.querySelector('body');
/// Returns a fragment of HTML or XML that represents the element and its
/// contents.
diff --git a/test/dom_test.dart b/test/dom_test.dart
index f9a5cac..82db4f4 100644
--- a/test/dom_test.dart
+++ b/test/dom_test.dart
@@ -24,7 +24,7 @@
'<div id=Foo>');
test('getElementById', () {
- final foo = doc.body.nodes[0];
+ final foo = doc.body!.nodes[0];
final fooVar = foo.nodes[2];
expect((foo as Element).id, 'foo');
expect((fooVar as Element).id, 'Foo');
@@ -33,7 +33,7 @@
});
test('getElementsByClassName', () {
- final foo = doc.body.nodes[0];
+ final foo = doc.body!.nodes[0];
final barBaz = foo.nodes[0];
final quxBaz = foo.nodes[1];
expect((barBaz as Element).className, ' bar baz');
@@ -45,7 +45,7 @@
});
test('getElementsByTagName', () {
- final foo = doc.body.nodes[0];
+ final foo = doc.body!.nodes[0];
final barBaz = foo.nodes[0];
final quxBaz = foo.nodes[1];
final fooVar = foo.nodes[2];
@@ -56,135 +56,135 @@
group('fragments are flattened', () {
test('add', () {
final doc = parse('<body>');
- doc.body.nodes.add(parseFragment('<x-foo>'));
- expect((doc.body.nodes[0] as Element).localName, 'x-foo');
- doc.body.nodes.add(parseFragment('<x-bar>'));
- expect((doc.body.nodes[1] as Element).localName, 'x-bar');
+ doc.body!.nodes.add(parseFragment('<x-foo>'));
+ expect((doc.body!.nodes[0] as Element).localName, 'x-foo');
+ doc.body!.nodes.add(parseFragment('<x-bar>'));
+ expect((doc.body!.nodes[1] as Element).localName, 'x-bar');
});
test('addLast', () {
final doc = parse('<body>');
- doc.body.nodes.addLast(parseFragment('<x-foo>'));
- expect((doc.body.nodes[0] as Element).localName, 'x-foo');
- doc.body.nodes.addLast(parseFragment('<x-bar>'));
- expect((doc.body.nodes[1] as Element).localName, 'x-bar');
+ doc.body!.nodes.addLast(parseFragment('<x-foo>'));
+ expect((doc.body!.nodes[0] as Element).localName, 'x-foo');
+ doc.body!.nodes.addLast(parseFragment('<x-bar>'));
+ expect((doc.body!.nodes[1] as Element).localName, 'x-bar');
});
test('addAll', () {
final doc = parse('<body><x-a></x-a>');
- doc.body.nodes.addAll([parseFragment('<x-b></x-b><x-c></x-c>')]);
- expect((doc.body.nodes[0] as Element).localName, 'x-a');
- expect((doc.body.nodes[1] as Element).localName, 'x-b');
- expect((doc.body.nodes[2] as Element).localName, 'x-c');
+ doc.body!.nodes.addAll([parseFragment('<x-b></x-b><x-c></x-c>')]);
+ expect((doc.body!.nodes[0] as Element).localName, 'x-a');
+ expect((doc.body!.nodes[1] as Element).localName, 'x-b');
+ expect((doc.body!.nodes[2] as Element).localName, 'x-c');
});
test('insert', () {
var doc = parse('<body><x-a></x-a>');
- doc.body.nodes.insert(0, parseFragment('<x-b></x-b><x-c></x-c>'));
- expect((doc.body.nodes[0] as Element).localName, 'x-b');
- expect((doc.body.nodes[1] as Element).localName, 'x-c');
- expect((doc.body.nodes[2] as Element).localName, 'x-a');
+ doc.body!.nodes.insert(0, parseFragment('<x-b></x-b><x-c></x-c>'));
+ expect((doc.body!.nodes[0] as Element).localName, 'x-b');
+ expect((doc.body!.nodes[1] as Element).localName, 'x-c');
+ expect((doc.body!.nodes[2] as Element).localName, 'x-a');
doc = parse('<body><x-a></x-a>');
- doc.body.nodes.insert(1, parseFragment('<x-b></x-b><x-c></x-c>'));
- expect((doc.body.nodes[0] as Element).localName, 'x-a');
- expect((doc.body.nodes[1] as Element).localName, 'x-b');
- expect((doc.body.nodes[2] as Element).localName, 'x-c');
+ doc.body!.nodes.insert(1, parseFragment('<x-b></x-b><x-c></x-c>'));
+ expect((doc.body!.nodes[0] as Element).localName, 'x-a');
+ expect((doc.body!.nodes[1] as Element).localName, 'x-b');
+ expect((doc.body!.nodes[2] as Element).localName, 'x-c');
doc = parse('<body><x-a></x-a>');
- doc.body.nodes.insert(0, parseFragment('<x-b></x-b>'));
- doc.body.nodes.insert(1, parseFragment('<x-c></x-c>'));
- expect((doc.body.nodes[0] as Element).localName, 'x-b');
- expect((doc.body.nodes[1] as Element).localName, 'x-c');
- expect((doc.body.nodes[2] as Element).localName, 'x-a');
+ doc.body!.nodes.insert(0, parseFragment('<x-b></x-b>'));
+ doc.body!.nodes.insert(1, parseFragment('<x-c></x-c>'));
+ expect((doc.body!.nodes[0] as Element).localName, 'x-b');
+ expect((doc.body!.nodes[1] as Element).localName, 'x-c');
+ expect((doc.body!.nodes[2] as Element).localName, 'x-a');
});
test('insertAll', () {
var doc = parse('<body><x-a></x-a>');
- doc.body.nodes.insertAll(0, [parseFragment('<x-b></x-b><x-c></x-c>')]);
- expect((doc.body.nodes[0] as Element).localName, 'x-b');
- expect((doc.body.nodes[1] as Element).localName, 'x-c');
- expect((doc.body.nodes[2] as Element).localName, 'x-a');
- expect(doc.body.nodes.length, 3);
+ doc.body!.nodes.insertAll(0, [parseFragment('<x-b></x-b><x-c></x-c>')]);
+ expect((doc.body!.nodes[0] as Element).localName, 'x-b');
+ expect((doc.body!.nodes[1] as Element).localName, 'x-c');
+ expect((doc.body!.nodes[2] as Element).localName, 'x-a');
+ expect(doc.body!.nodes.length, 3);
doc = parse('<body><x-a></x-a>');
- doc.body.nodes.insertAll(1, [parseFragment('<x-b></x-b><x-c></x-c>')]);
- expect((doc.body.nodes[0] as Element).localName, 'x-a');
- expect((doc.body.nodes[1] as Element).localName, 'x-b');
- expect((doc.body.nodes[2] as Element).localName, 'x-c');
+ doc.body!.nodes.insertAll(1, [parseFragment('<x-b></x-b><x-c></x-c>')]);
+ expect((doc.body!.nodes[0] as Element).localName, 'x-a');
+ expect((doc.body!.nodes[1] as Element).localName, 'x-b');
+ expect((doc.body!.nodes[2] as Element).localName, 'x-c');
doc = parse('<body><x-a></x-a>');
- doc.body.nodes.insertAll(0, [parseFragment('<x-b></x-b>')]);
- doc.body.nodes.insertAll(1, [parseFragment('<x-c></x-c>')]);
- expect((doc.body.nodes[0] as Element).localName, 'x-b');
- expect((doc.body.nodes[1] as Element).localName, 'x-c');
- expect((doc.body.nodes[2] as Element).localName, 'x-a');
+ doc.body!.nodes.insertAll(0, [parseFragment('<x-b></x-b>')]);
+ doc.body!.nodes.insertAll(1, [parseFragment('<x-c></x-c>')]);
+ expect((doc.body!.nodes[0] as Element).localName, 'x-b');
+ expect((doc.body!.nodes[1] as Element).localName, 'x-c');
+ expect((doc.body!.nodes[2] as Element).localName, 'x-a');
});
test('operator []=', () {
var doc = parse('<body><x-a></x-a>');
- doc.body.nodes[0] = parseFragment('<x-b></x-b><x-c></x-c>');
- expect((doc.body.nodes[0] as Element).localName, 'x-b');
- expect((doc.body.nodes[1] as Element).localName, 'x-c');
- expect(doc.body.nodes.length, 2);
+ doc.body!.nodes[0] = parseFragment('<x-b></x-b><x-c></x-c>');
+ expect((doc.body!.nodes[0] as Element).localName, 'x-b');
+ expect((doc.body!.nodes[1] as Element).localName, 'x-c');
+ expect(doc.body!.nodes.length, 2);
doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>');
- doc.body.nodes[1] = parseFragment('<y-b></y-b><y-c></y-c>');
- expect((doc.body.nodes[0] as Element).localName, 'x-a');
- expect((doc.body.nodes[1] as Element).localName, 'y-b');
- expect((doc.body.nodes[2] as Element).localName, 'y-c');
- expect((doc.body.nodes[3] as Element).localName, 'x-c');
- expect(doc.body.nodes.length, 4);
+ doc.body!.nodes[1] = parseFragment('<y-b></y-b><y-c></y-c>');
+ expect((doc.body!.nodes[0] as Element).localName, 'x-a');
+ expect((doc.body!.nodes[1] as Element).localName, 'y-b');
+ expect((doc.body!.nodes[2] as Element).localName, 'y-c');
+ expect((doc.body!.nodes[3] as Element).localName, 'x-c');
+ expect(doc.body!.nodes.length, 4);
});
test('setRange', () {
var fragment = parseFragment('<y-b></y-b><y-c></y-c>');
var doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>');
- doc.body.nodes.setRange(1, 2, fragment.nodes, 0);
- expect((doc.body.nodes[0] as Element).localName, 'x-a');
- expect((doc.body.nodes[1] as Element).localName, 'y-b');
- expect((doc.body.nodes[2] as Element).localName, 'y-c');
- expect(doc.body.nodes.length, 3);
+ doc.body!.nodes.setRange(1, 2, fragment.nodes, 0);
+ expect((doc.body!.nodes[0] as Element).localName, 'x-a');
+ expect((doc.body!.nodes[1] as Element).localName, 'y-b');
+ expect((doc.body!.nodes[2] as Element).localName, 'y-c');
+ expect(doc.body!.nodes.length, 3);
fragment = parseFragment('<y-b></y-b><y-c></y-c>');
doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>');
- doc.body.nodes.setRange(1, 1, [fragment], 0);
- expect((doc.body.nodes[0] as Element).localName, 'x-a');
- expect((doc.body.nodes[1] as Element).localName, 'y-b');
- expect((doc.body.nodes[2] as Element).localName, 'y-c');
- expect((doc.body.nodes[3] as Element).localName, 'x-c');
- expect(doc.body.nodes.length, 4);
+ doc.body!.nodes.setRange(1, 1, [fragment], 0);
+ expect((doc.body!.nodes[0] as Element).localName, 'x-a');
+ expect((doc.body!.nodes[1] as Element).localName, 'y-b');
+ expect((doc.body!.nodes[2] as Element).localName, 'y-c');
+ expect((doc.body!.nodes[3] as Element).localName, 'x-c');
+ expect(doc.body!.nodes.length, 4);
});
test('replaceRange', () {
var fragment = parseFragment('<y-b></y-b><y-c></y-c>');
var doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>');
- doc.body.nodes.replaceRange(1, 2, fragment.nodes);
- expect((doc.body.nodes[0] as Element).localName, 'x-a');
- expect((doc.body.nodes[1] as Element).localName, 'y-b');
- expect((doc.body.nodes[2] as Element).localName, 'y-c');
- expect((doc.body.nodes[3] as Element).localName, 'x-c');
- expect(doc.body.nodes.length, 4);
+ doc.body!.nodes.replaceRange(1, 2, fragment.nodes);
+ expect((doc.body!.nodes[0] as Element).localName, 'x-a');
+ expect((doc.body!.nodes[1] as Element).localName, 'y-b');
+ expect((doc.body!.nodes[2] as Element).localName, 'y-c');
+ expect((doc.body!.nodes[3] as Element).localName, 'x-c');
+ expect(doc.body!.nodes.length, 4);
fragment = parseFragment('<y-b></y-b><y-c></y-c>');
doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>');
- doc.body.nodes.replaceRange(1, 2, [fragment]);
- expect((doc.body.nodes[0] as Element).localName, 'x-a');
- expect((doc.body.nodes[1] as Element).localName, 'y-b');
- expect((doc.body.nodes[2] as Element).localName, 'y-c');
- expect((doc.body.nodes[3] as Element).localName, 'x-c');
- expect(doc.body.nodes.length, 4);
+ doc.body!.nodes.replaceRange(1, 2, [fragment]);
+ expect((doc.body!.nodes[0] as Element).localName, 'x-a');
+ expect((doc.body!.nodes[1] as Element).localName, 'y-b');
+ expect((doc.body!.nodes[2] as Element).localName, 'y-c');
+ expect((doc.body!.nodes[3] as Element).localName, 'x-c');
+ expect(doc.body!.nodes.length, 4);
});
test('replaceWith', () {
final fragment = parseFragment('<y-b></y-b><y-c></y-c>');
final doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>');
- doc.body.nodes[1].replaceWith(fragment);
- expect((doc.body.nodes[0] as Element).localName, 'x-a');
- expect((doc.body.nodes[1] as Element).localName, 'y-b');
- expect((doc.body.nodes[2] as Element).localName, 'y-c');
- expect((doc.body.nodes[3] as Element).localName, 'x-c');
- expect(doc.body.nodes.length, 4);
+ doc.body!.nodes[1].replaceWith(fragment);
+ expect((doc.body!.nodes[0] as Element).localName, 'x-a');
+ expect((doc.body!.nodes[1] as Element).localName, 'y-b');
+ expect((doc.body!.nodes[2] as Element).localName, 'y-c');
+ expect((doc.body!.nodes[3] as Element).localName, 'x-c');
+ expect(doc.body!.nodes.length, 4);
});
});
}
diff --git a/test/parser_feature_test.dart b/test/parser_feature_test.dart
index 7825a23..64068d0 100644
--- a/test/parser_feature_test.dart
+++ b/test/parser_feature_test.dart
@@ -20,7 +20,7 @@
test('line counter', () {
// http://groups.google.com/group/html5lib-discuss/browse_frm/thread/f4f00e4a2f26d5c0
final doc = parse('<pre>\nx\n>\n</pre>');
- expect(doc.body.innerHtml, '<pre>x\n>\n</pre>');
+ expect(doc.body!.innerHtml, '<pre>x\n>\n</pre>');
});
test('namespace html elements on', () {
@@ -43,7 +43,7 @@
</html>
''', generateSpans: true, sourceUrl: 'ParseError');
final doc = parser.parse();
- expect(doc.body.outerHtml, '<body>\n \n \n\n</body>');
+ expect(doc.body!.outerHtml, '<body>\n \n \n\n</body>');
expect(parser.errors.length, 1);
final error = parser.errors[0];
expect(error.errorCode, 'unexpected-doctype');
@@ -73,7 +73,7 @@
</html>
''');
final doc = parser.parse();
- expect(doc.body.outerHtml, '<body>\n \n \n\n</body>');
+ expect(doc.body!.outerHtml, '<body>\n \n \n\n</body>');
expect(parser.errors.length, 1);
final error = parser.errors[0];
expect(error.errorCode, 'unexpected-doctype');
@@ -86,7 +86,7 @@
final textContent = '\n hello {{name}}';
final html = '<body><div>$textContent</div>';
final doc = parse(html, generateSpans: true);
- final text = doc.body.nodes[0].nodes[0] as Text;
+ final text = doc.body!.nodes[0].nodes[0] as Text;
expect(text, const TypeMatcher<Text>());
expect(text.data, textContent);
expect(text.sourceSpan!.start.offset, html.indexOf(textContent));
@@ -150,26 +150,26 @@
test('void element innerHTML', () {
var doc = parse('<div></div>');
- expect(doc.body.innerHtml, '<div></div>');
+ expect(doc.body!.innerHtml, '<div></div>');
doc = parse('<body><script></script></body>');
- expect(doc.body.innerHtml, '<script></script>');
+ expect(doc.body!.innerHtml, '<script></script>');
doc = parse('<br>');
- expect(doc.body.innerHtml, '<br>');
+ expect(doc.body!.innerHtml, '<br>');
doc = parse('<br><foo><bar>');
- expect(doc.body.innerHtml, '<br><foo><bar></bar></foo>');
+ expect(doc.body!.innerHtml, '<br><foo><bar></bar></foo>');
});
test('empty document has html, body, and head', () {
final doc = parse('');
final html = '<html><head></head><body></body></html>';
expect(doc.outerHtml, html);
- expect(doc.documentElement.outerHtml, html);
- expect(doc.head.outerHtml, '<head></head>');
- expect(doc.body.outerHtml, '<body></body>');
+ expect(doc.documentElement!.outerHtml, html);
+ expect(doc.head!.outerHtml, '<head></head>');
+ expect(doc.body!.outerHtml, '<body></body>');
});
test('strange table case', () {
- final doc = parse('<table><tbody><foo>').body;
+ final doc = parse('<table><tbody><foo>').body!;
expect(doc.innerHtml, '<foo></foo><table><tbody></tbody></table>');
});
@@ -177,7 +177,7 @@
test('attribute order', () {
// Note: the spec only requires a stable order.
// However, we preserve the input order via LinkedHashMap
- final body = parse('<foo d=1 a=2 c=3 b=4>').body;
+ final body = parse('<foo d=1 a=2 c=3 b=4>').body!;
expect(body.innerHtml, '<foo d="1" a="2" c="3" b="4"></foo>');
expect(body.querySelector('foo')!.attributes.remove('a'), '2');
expect(body.innerHtml, '<foo d="1" c="3" b="4"></foo>');
@@ -249,7 +249,7 @@
test('error printing without spans', () {
final parser = HtmlParser('foo');
final doc = parser.parse();
- expect(doc.body.innerHtml, 'foo');
+ expect(doc.body!.innerHtml, 'foo');
expect(parser.errors.length, 1);
expect(parser.errors[0].errorCode, 'expected-doctype-but-got-chars');
expect(parser.errors[0].message,
diff --git a/test/selectors/level1_baseline_test.dart b/test/selectors/level1_baseline_test.dart
index cba4c21..5e85c8f 100644
--- a/test/selectors/level1_baseline_test.dart
+++ b/test/selectors/level1_baseline_test.dart
@@ -116,7 +116,7 @@
group('out of scope', () {
setUp(() {
- doc.body.append(outOfScope); // Append before in-document Element tests.
+ doc.body!.append(outOfScope); // Append before in-document Element tests.
// None of these elements should match
});
tearDown(outOfScope.remove);