srctree

Robin Linden parent a2baeec0 baec2a1e
html2: Implement the InFrameset state

inlinesplit
html2/parser_states.cpp added: 180, removed: 9, total 171
@@ -447,8 +447,7 @@ std::optional<InsertionMode> AfterHead::process(IActions &a, html2::Token const
 
if (start->tag_name == "frameset") {
a.insert_element_for(*start);
// TODO(robinlinden): Switch to InFrameset.
return {};
return InFrameset{};
}
 
static constexpr auto kInHeadElements = std::to_array<std::string_view>({
@@ -528,4 +527,67 @@ std::optional<InsertionMode> Text::process(IActions &a, html2::Token const &toke
return {};
}
 
std::optional<InsertionMode> InFrameset::process(IActions &a, html2::Token const &token) {
if (is_boring_whitespace(token)) {
a.insert_character(std::get<html2::CharacterToken>(token));
return {};
}
 
if (std::holds_alternative<html2::CommentToken>(token)) {
// TODO(robinlinden): Insert.
return {};
}
 
if (std::holds_alternative<html2::DoctypeToken>(token)) {
// Parse error.
return {};
}
 
if (auto const *start = std::get_if<html2::StartTagToken>(&token); start != nullptr) {
if (start->tag_name == "html") {
return InBody{}.process(a, token);
}
 
if (start->tag_name == "frameset") {
a.insert_element_for(*start);
return {};
}
 
if (start->tag_name == "frame") {
a.insert_element_for(*start);
a.pop_current_node();
// TODO(robinlinden): Acknowledge the token's self-closing flag, if it is set.
return {};
}
 
if (start->tag_name == "noframes") {
auto mode_override = current_insertion_mode_override(a, InFrameset{});
return InHead{}.process(mode_override, token);
}
}
 
if (auto const *end = std::get_if<html2::EndTagToken>(&token); end != nullptr && end->tag_name == "frameset") {
// TODO(robinlinden): Fragment-parsing.
a.pop_current_node();
if (a.current_node_name() != "frameset") {
return AfterFrameset{};
}
}
 
if (std::holds_alternative<html2::EndOfFileToken>(token)) {
if (a.current_node_name() != "html") {
// Parse error.
}
 
return {};
}
 
// Parse error.
return {};
}
 
std::optional<InsertionMode> AfterFrameset::process(IActions &, html2::Token const &) {
return {};
}
 
} // namespace html2
 
html2/parser_states.h added: 180, removed: 9, total 171
@@ -45,7 +45,7 @@ using InsertionMode = std::variant<Initial,
InHeadNoscript,
AfterHead,
InBody,
Text //
Text,
#if 0
InTable,
InTableText,
@@ -58,8 +58,10 @@ using InsertionMode = std::variant<Initial,
InSelectInTable,
InTemplate,
AfterBody,
#endif
InFrameset,
AfterFrameset,
AfterFrameset
#if 0
AfterAfterBody,
AfterAfterFrameset
#endif
@@ -76,8 +78,6 @@ struct InSelect {};
struct InSelectInTable {};
struct InTemplate {};
struct AfterBody {};
struct InFrameset {};
struct AfterFrameset {};
struct AfterAfterBody {};
struct AfterAfterFrameset {};
 
@@ -125,6 +125,17 @@ struct Text {
std::optional<InsertionMode> process(IActions &, html2::Token const &);
};
 
// https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inframeset
struct InFrameset {
std::optional<InsertionMode> process(IActions &, html2::Token const &);
};
 
// https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-afterframeset
// Incomplete.
struct AfterFrameset {
std::optional<InsertionMode> process(IActions &, html2::Token const &);
};
 
} // namespace html2
 
#endif
 
html2/parser_states_test.cpp added: 180, removed: 9, total 171
@@ -368,6 +368,103 @@ void after_head_tests() {
});
}
 
void in_frameset_tests() {
etest::test("InFrameset: boring whitespace", [] {
auto res = parse("<head></head><frameset> ", {});
dom::Element expected{
"html",
{},
{
dom::Element{"head"},
dom::Element{"frameset", {}, {dom::Text{" "}}},
},
};
expect_eq(res.document.html(), expected);
});
 
etest::test("InFrameset: comment", [] {
auto res = parse("<head></head><frameset><!-- comment -->", {});
dom::Element expected{
"html",
{},
{dom::Element{"head"}, dom::Element{"frameset"}},
};
expect_eq(res.document.html(), expected);
});
 
etest::test("InFrameset: doctype", [] {
auto res = parse("<head></head><frameset><!doctype html>", {});
dom::Element expected{
"html",
{},
{dom::Element{"head"}, dom::Element{"frameset"}},
};
expect_eq(res.document.html(), expected);
});
 
etest::test("InFrameset: <html>", [] {
auto res = parse("<head></head><frameset><html foo=bar>", {});
dom::Element expected{
"html",
{{"foo", "bar"}},
{dom::Element{"head"}, dom::Element{"frameset"}},
};
expect_eq(res.document.html(), expected);
});
 
etest::test("InFrameset: <frameset>", [] {
auto res = parse("<head></head><frameset><frameset>", {});
dom::Element expected{
"html",
{},
{
dom::Element{"head"},
dom::Element{"frameset", {}, {dom::Element{"frameset"}}},
},
};
expect_eq(res.document.html(), expected);
});
 
etest::test("InFrameset: <frame>", [] {
auto res = parse("<head></head><frameset><frame>", {});
dom::Element expected{
"html",
{},
{
dom::Element{"head"},
dom::Element{"frameset", {}, {dom::Element{"frame"}}},
},
};
expect_eq(res.document.html(), expected);
});
 
etest::test("InFrameset: <noframes>", [] {
auto res = parse("<head></head><frameset><noframes>", {});
dom::Element expected{
"html",
{},
{
dom::Element{"head"},
dom::Element{"frameset", {}, {dom::Element{"noframes"}}},
},
};
expect_eq(res.document.html(), expected);
});
 
etest::test("InFrameset: </frameset>", [] {
auto res = parse("<head></head><frameset></frameset>", {});
dom::Element expected{
"html",
{},
{
dom::Element{"head"},
dom::Element{"frameset"},
},
};
expect_eq(res.document.html(), expected);
});
}
 
} // namespace
 
int main() {
@@ -377,5 +474,6 @@ int main() {
in_head_tests();
in_head_noscript_tests();
after_head_tests();
in_frameset_tests();
return etest::run_all_tests();
}