summaryrefslogtreecommitdiffstats
path: root/parser/html/nsHtml5TreeBuilderCppSupplement.h
diff options
context:
space:
mode:
Diffstat (limited to 'parser/html/nsHtml5TreeBuilderCppSupplement.h')
-rw-r--r--parser/html/nsHtml5TreeBuilderCppSupplement.h148
1 files changed, 98 insertions, 50 deletions
diff --git a/parser/html/nsHtml5TreeBuilderCppSupplement.h b/parser/html/nsHtml5TreeBuilderCppSupplement.h
index ba9c217cb9..59df6937e2 100644
--- a/parser/html/nsHtml5TreeBuilderCppSupplement.h
+++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h
@@ -113,6 +113,19 @@ nsHtml5TreeBuilder::~nsHtml5TreeBuilder() {
mOpQueue.Clear();
}
+static void getTypeString(nsHtml5String& aType, nsAString& aTypeString) {
+ aType.ToString(aTypeString);
+
+ // Since `typeString` after trimming and lowercasing is only checked
+ // for "module" and " importmap", we don't need to remember
+ // pre-trimming emptiness here.
+
+ // ASCII whitespace https://infra.spec.whatwg.org/#ascii-whitespace:
+ // U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, or U+0020 SPACE.
+ static const char kASCIIWhitespace[] = "\t\n\f\r ";
+ aTypeString.Trim(kASCIIWhitespace);
+}
+
nsIContentHandle* nsHtml5TreeBuilder::createElement(
int32_t aNamespace, nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
nsIContentHandle* aIntendedParent, nsHtml5ContentCreatorFunction aCreator) {
@@ -202,9 +215,11 @@ nsIContentHandle* nsHtml5TreeBuilder::createElement(
nsHtml5AttributeName::ATTR_REFERRERPOLICY);
nsHtml5String sizes =
aAttributes->getValue(nsHtml5AttributeName::ATTR_SIZES);
+ nsHtml5String fetchPriority =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_FETCHPRIORITY);
mSpeculativeLoadQueue.AppendElement()->InitImage(
url, crossOrigin, /* aMedia = */ nullptr, referrerPolicy,
- srcset, sizes, false);
+ srcset, sizes, false, fetchPriority);
}
} else if (nsGkAtoms::source == aName) {
nsHtml5String srcset =
@@ -239,16 +254,7 @@ nsIContentHandle* nsHtml5TreeBuilder::createElement(
nsHtml5String type =
aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
nsAutoString typeString;
- type.ToString(typeString);
-
- // Since `typeString` after trimming and lowercasing is only checked
- // for "module" and " importmap", we don't need to remember
- // pre-trimming emptiness here.
-
- // ASCII whitespace https://infra.spec.whatwg.org/#ascii-whitespace:
- // U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, or U+0020 SPACE.
- static const char kASCIIWhitespace[] = "\t\n\f\r ";
- typeString.Trim(kASCIIWhitespace);
+ getTypeString(type, typeString);
bool isModule = typeString.LowerCaseEqualsASCII("module");
bool importmap = typeString.LowerCaseEqualsASCII("importmap");
@@ -431,7 +437,7 @@ nsIContentHandle* nsHtml5TreeBuilder::createElement(
nsHtml5AttributeName::ATTR_IMAGESIZES);
mSpeculativeLoadQueue.AppendElement()->InitImage(
url, crossOrigin, media, referrerPolicy, srcset, sizes,
- true);
+ true, fetchPriority);
} else if (as.LowerCaseEqualsASCII("font")) {
mSpeculativeLoadQueue.AppendElement()->InitFont(
url, crossOrigin, media, referrerPolicy, fetchPriority);
@@ -483,8 +489,14 @@ nsIContentHandle* nsHtml5TreeBuilder::createElement(
nsHtml5String url =
aAttributes->getValue(nsHtml5AttributeName::ATTR_POSTER);
if (url) {
+ // Fetch priority is not supported for video. Nullptr will map to
+ // the auto state
+ // (https://html.spec.whatwg.org/#fetch-priority-attribute).
+ auto fetchPriority = nullptr;
+
mSpeculativeLoadQueue.AppendElement()->InitImage(
- url, nullptr, nullptr, nullptr, nullptr, nullptr, false);
+ url, nullptr, nullptr, nullptr, nullptr, nullptr, false,
+ fetchPriority);
}
} else if (nsGkAtoms::style == aName) {
mImportScanner.Start();
@@ -539,8 +551,15 @@ nsIContentHandle* nsHtml5TreeBuilder::createElement(
url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF);
}
if (url) {
+ // Currently SVG's `<image>` element lacks support for
+ // `fetchpriority`, see bug 1847712. Hence passing nullptr which
+ // maps to the auto state
+ // (https://html.spec.whatwg.org/#fetch-priority-attribute).
+ auto fetchPriority = nullptr;
+
mSpeculativeLoadQueue.AppendElement()->InitImage(
- url, nullptr, nullptr, nullptr, nullptr, nullptr, false);
+ url, nullptr, nullptr, nullptr, nullptr, nullptr, false,
+ fetchPriority);
}
} else if (nsGkAtoms::script == aName) {
nsHtml5TreeOperation* treeOp =
@@ -556,36 +575,70 @@ nsIContentHandle* nsHtml5TreeBuilder::createElement(
tokenizer->getColumnNumber() + 1);
treeOp->Init(mozilla::AsVariant(operation));
+ nsHtml5String type =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
+ nsAutoString typeString;
+ getTypeString(type, typeString);
+
+ bool isModule = typeString.LowerCaseEqualsASCII("module");
+ bool importmap = typeString.LowerCaseEqualsASCII("importmap");
+ bool async = false;
+ bool defer = false;
+
+ if (importmap) {
+ // If we see an importmap, we don't want to later start speculative
+ // loads for modulepreloads, since such load might finish before
+ // the importmap is created. This also applies to module scripts so
+ // that any modulepreload integrity checks can be performed before
+ // the modules scripts are loaded.
+ // This state is not part of speculation rollback: If an importmap
+ // is seen speculatively and the speculation is rolled back, the
+ // importmap is still considered seen.
+ // TODO: Sync importmap seenness between the main thread and the
+ // parser thread.
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1848312
+ mHasSeenImportMap = true;
+ }
nsHtml5String url =
aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
if (!url) {
url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF);
}
if (url) {
- nsHtml5String type =
- aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
- nsHtml5String crossOrigin =
- aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
- nsHtml5String nonce =
- aAttributes->getValue(nsHtml5AttributeName::ATTR_NONCE);
- nsHtml5String integrity =
- aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
- nsHtml5String referrerPolicy = aAttributes->getValue(
- nsHtml5AttributeName::ATTR_REFERRERPOLICY);
+ async = aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC);
+ defer = aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER);
+ if ((isModule && !mHasSeenImportMap) || (!isModule && !importmap)) {
+ nsHtml5String type =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
+ nsHtml5String crossOrigin =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
+ nsHtml5String nonce =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_NONCE);
+ nsHtml5String integrity =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
+ nsHtml5String referrerPolicy = aAttributes->getValue(
+ nsHtml5AttributeName::ATTR_REFERRERPOLICY);
- // Bug 1847712: SVG's `<script>` element doesn't support
- // `fetchpriority` yet.
- // Use the empty string and rely on the
- // "invalid value default" state being used later.
- // Compared to using a non-empty string, this doesn't
- // require calling `Release()` for the string.
- nsHtml5String fetchPriority = nsHtml5String::EmptyString();
-
- mSpeculativeLoadQueue.AppendElement()->InitScript(
- url, nullptr, type, crossOrigin, /* aMedia = */ nullptr, nonce,
- fetchPriority, integrity, referrerPolicy,
- mode == nsHtml5TreeBuilder::IN_HEAD, false, false, false);
+ // Bug 1847712: SVG's `<script>` element doesn't support
+ // `fetchpriority` yet.
+ // Use the empty string and rely on the
+ // "invalid value default" state being used later.
+ // Compared to using a non-empty string, this doesn't
+ // require calling `Release()` for the string.
+ nsHtml5String fetchPriority = nsHtml5String::EmptyString();
+
+ mSpeculativeLoadQueue.AppendElement()->InitScript(
+ url, nullptr, type, crossOrigin, /* aMedia = */ nullptr,
+ nonce, fetchPriority, integrity, referrerPolicy,
+ mode == nsHtml5TreeBuilder::IN_HEAD, async, defer, false);
+ }
}
+ // `mCurrentHtmlScriptCannotDocumentWriteOrBlock` MUST be computed to
+ // match the ScriptLoader-perceived kind of the script regardless of
+ // enqueuing a speculative load. Either the attribute prevents a
+ // classic script execution or is ignored on a module script.
+ mCurrentHtmlScriptCannotDocumentWriteOrBlock =
+ isModule || importmap || async || defer;
} else if (nsGkAtoms::style == aName) {
mImportScanner.Start();
nsHtml5TreeOperation* treeOp =
@@ -638,16 +691,7 @@ nsIContentHandle* nsHtml5TreeBuilder::createElement(
nsHtml5String type =
aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
nsAutoString typeString;
- type.ToString(typeString);
-
- // Since `typeString` after trimming and lowercasing is only checked
- // for "module" and " importmap", we don't need to remember
- // pre-trimming emptiness here.
-
- // ASCII whitespace https://infra.spec.whatwg.org/#ascii-whitespace:
- // U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, or U+0020 SPACE.
- static const char kASCIIWhitespace[] = "\t\n\f\r ";
- typeString.Trim(kASCIIWhitespace);
+ getTypeString(type, typeString);
mCurrentHtmlScriptCannotDocumentWriteOrBlock =
typeString.LowerCaseEqualsASCII("module") ||
@@ -1224,8 +1268,9 @@ void nsHtml5TreeBuilder::elementPopped(int32_t aNamespace, nsAtom* aName,
return;
}
if (mCurrentHtmlScriptCannotDocumentWriteOrBlock) {
- NS_ASSERTION(aNamespace == kNameSpaceID_XHTML,
- "Only HTML scripts may be async/defer.");
+ NS_ASSERTION(
+ aNamespace == kNameSpaceID_XHTML || aNamespace == kNameSpaceID_SVG,
+ "Only HTML and SVG scripts may be async/defer.");
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
if (MOZ_UNLIKELY(!treeOp)) {
MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
@@ -1661,7 +1706,8 @@ void nsHtml5TreeBuilder::setDocumentFragmentForTemplate(
nsIContentHandle* nsHtml5TreeBuilder::getShadowRootFromHost(
nsIContentHandle* aHost, nsIContentHandle* aTemplateNode,
- nsHtml5String aShadowRootMode, bool aShadowRootDelegatesFocus) {
+ nsHtml5String aShadowRootMode, bool aShadowRootIsClonable,
+ bool aShadowRootDelegatesFocus) {
mozilla::dom::ShadowRootMode mode;
if (aShadowRootMode.LowerCaseEqualsASCII("open")) {
mode = mozilla::dom::ShadowRootMode::Open;
@@ -1673,7 +1719,8 @@ nsIContentHandle* nsHtml5TreeBuilder::getShadowRootFromHost(
if (mBuilder) {
nsIContent* root = nsContentUtils::AttachDeclarativeShadowRoot(
- static_cast<nsIContent*>(aHost), mode, aShadowRootDelegatesFocus);
+ static_cast<nsIContent*>(aHost), mode, aShadowRootIsClonable,
+ aShadowRootDelegatesFocus);
if (!root) {
nsContentUtils::LogSimpleConsoleError(
u"Failed to attach Declarative Shadow DOM."_ns, "DOM"_ns,
@@ -1690,6 +1737,7 @@ nsIContentHandle* nsHtml5TreeBuilder::getShadowRootFromHost(
}
nsIContentHandle* fragHandle = AllocateContentHandle();
opGetShadowRootFromHost operation(aHost, fragHandle, aTemplateNode, mode,
+ aShadowRootIsClonable,
aShadowRootDelegatesFocus);
treeOp->Init(mozilla::AsVariant(operation));
return fragHandle;