Commit 17481350 authored by Andrew Comminos's avatar Andrew Comminos Committed by Commit Bot

Only flush tokenized chunks to the HTML parser for valid script types.

Having a large amount of <script> tags on a page with an invalid type
for execution (e.g. text/html) triggers the same path for event loop
yielding as JavaScript tags, causing slowness due to parser yields and
unnecessarily aggressive chunking. Avoid performing this logic if the
ScriptLoader can't recognize the script type.

This reduces the amount of time it takes for DOMContentLoaded in the script
attachment for issue 873648 from 367ms to 208ms, similar to the div attachment's
209ms.

R=kouhei@chromium.org

Bug: 873648
Change-Id: I4c7ea76feb2034f5ff97fe08b481c790b9a35122
Reviewed-on: https://chromium-review.googlesource.com/1247230Reviewed-by: default avatarKouhei Ueno <kouhei@chromium.org>
Commit-Queue: Kouhei Ueno <kouhei@chromium.org>
Cr-Commit-Position: refs/heads/master@{#595719}
parent 4a56f1ee
......@@ -233,7 +233,7 @@ void BackgroundHTMLParser::PumpTokenizer() {
// Break chunks before a script tag is inserted and flag the chunk as
// starting a script so the main parser can decide if it should yield
// before processing the chunk.
if (simulated_token == HTMLTreeBuilderSimulator::kScriptStart) {
if (simulated_token == HTMLTreeBuilderSimulator::kValidScriptStart) {
EnqueueTokenizedChunk();
starting_script_ = true;
}
......
......@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/html/parser/html_tree_builder.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/mathml_names.h"
#include "third_party/blink/renderer/core/script/script_loader.h"
#include "third_party/blink/renderer/core/svg_names.h"
namespace blink {
......@@ -152,7 +153,23 @@ HTMLTreeBuilderSimulator::SimulatedToken HTMLTreeBuilderSimulator::Simulate(
tokenizer->SetState(HTMLTokenizer::kRCDATAState);
} else if (ThreadSafeMatch(tag_name, scriptTag)) {
tokenizer->SetState(HTMLTokenizer::kScriptDataState);
simulated_token = kScriptStart;
String type_attribute_value;
if (auto* item = token.GetAttributeItem(typeAttr)) {
type_attribute_value = item->Value();
}
String language_attribute_value;
if (auto* item = token.GetAttributeItem(languageAttr)) {
language_attribute_value = item->Value();
}
ScriptType script_type;
if (ScriptLoader::IsValidScriptTypeAndLanguage(
type_attribute_value, language_attribute_value,
ScriptLoader::kAllowLegacyTypeInTypeAttribute, script_type)) {
simulated_token = kValidScriptStart;
}
} else if (ThreadSafeMatch(tag_name, linkTag)) {
simulated_token = kLink;
} else if (!in_select_insertion_mode_) {
......
......@@ -44,7 +44,7 @@ class CORE_EXPORT HTMLTreeBuilderSimulator {
public:
enum SimulatedToken {
kScriptStart,
kValidScriptStart,
kScriptEnd,
kLink,
kStyleEnd,
......
......@@ -24,7 +24,7 @@ TEST(HTMLTreeBuilderSimulatorTest, SelfClosingSVGFollowedByScript) {
token.Clear();
EXPECT_TRUE(tokenizer->NextToken(input, token));
EXPECT_EQ(HTMLTreeBuilderSimulator::kScriptStart,
EXPECT_EQ(HTMLTreeBuilderSimulator::kValidScriptStart,
simulator.Simulate(CompactHTMLToken(&token, TextPosition()),
tokenizer.get()));
......@@ -50,7 +50,7 @@ TEST(HTMLTreeBuilderSimulatorTest, SelfClosingMathFollowedByScript) {
token.Clear();
EXPECT_TRUE(tokenizer->NextToken(input, token));
EXPECT_EQ(HTMLTreeBuilderSimulator::kScriptStart,
EXPECT_EQ(HTMLTreeBuilderSimulator::kValidScriptStart,
simulator.Simulate(CompactHTMLToken(&token, TextPosition()),
tokenizer.get()));
......@@ -63,4 +63,22 @@ TEST(HTMLTreeBuilderSimulatorTest, SelfClosingMathFollowedByScript) {
tokenizer.get()));
}
TEST(HTMLTreeBuilderSimulatorTest, DetectInvalidScriptType) {
HTMLParserOptions options;
HTMLTreeBuilderSimulator simulator(options);
std::unique_ptr<HTMLTokenizer> tokenizer = HTMLTokenizer::Create(options);
SegmentedString input("<script type=\"text/html\"></script>");
HTMLToken token;
EXPECT_TRUE(tokenizer->NextToken(input, token));
EXPECT_NE(HTMLTreeBuilderSimulator::kValidScriptStart,
simulator.Simulate(CompactHTMLToken(&token, TextPosition()),
tokenizer.get()));
token.Clear();
EXPECT_TRUE(tokenizer->NextToken(input, token));
EXPECT_EQ(HTMLTreeBuilderSimulator::kScriptEnd,
simulator.Simulate(CompactHTMLToken(&token, TextPosition()),
tokenizer.get()));
}
} // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment