Issue #2158 - Part 2: Handle and expose preload link destination to DOM

This also defines known preload destinations and ensures it is reflected in JS.
This commit is contained in:
FranklinDM 2023-03-11 16:42:18 +08:00 • committed by roytam1
commit 24189770aa
11 changed files with 98 additions and 5 deletions

View file

@ -26,6 +26,47 @@
namespace mozilla {
namespace dom {
enum Destination : uint8_t
{
DESTINATION_INVALID,
DESTINATION_AUDIO,
DESTINATION_AUDIOWORKLET,
DESTINATION_DOCUMENT,
DESTINATION_EMBED,
DESTINATION_FONT,
DESTINATION_FRAME,
DESTINATION_IFRAME,
DESTINATION_IMAGE,
DESTINATION_JSON,
DESTINATION_MANIFEST,
DESTINATION_OBJECT,
DESTINATION_REPORT,
DESTINATION_SCRIPT,
DESTINATION_SERVICEWORKER,
DESTINATION_SHAREDWORKER,
DESTINATION_STYLE,
DESTINATION_TRACK,
DESTINATION_VIDEO,
DESTINATION_WEBIDENTITY,
DESTINATION_WORKER,
DESTINATION_XSLT,
DESTINATION_FETCH
};
static const nsAttrValue::EnumTable kDestinationAttributeTable[] = {
{ "", DESTINATION_INVALID },
{ "audio", DESTINATION_AUDIO },
{ "font", DESTINATION_FONT },
{ "image", DESTINATION_IMAGE },
{ "script", DESTINATION_SCRIPT },
{ "style", DESTINATION_STYLE },
{ "track", DESTINATION_TRACK },
{ "video", DESTINATION_VIDEO },
{ "fetch", DESTINATION_FETCH },
{ "json", DESTINATION_JSON },
{ nullptr, 0 }
};
Link::Link(Element *aElement)
: mElement(aElement)
, mHistory(services::GetHistoryService())
@ -635,6 +676,17 @@ Link::SetHrefAttribute(nsIURI *aURI)
NS_ConvertUTF8toUTF16(href), true);
}
/* static */ void
Link::ParseDestinationValue(const nsAString& aValue,
nsAttrValue& aResult)
{
// Invalid values are treated as an empty string.
aResult.ParseEnumValue(aValue,
kDestinationAttributeTable,
false,
&kDestinationAttributeTable[0]);
}
size_t
Link::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{

View file

@ -119,6 +119,8 @@ public:
void TryDNSPrefetchPreconnectOrPrefetch();
void CancelPrefetch();
static void ParseDestinationValue(const nsAString& aValue, nsAttrValue& aResult);
protected:
virtual ~Link();

View file

@ -471,6 +471,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
nsAutoString media;
nsAutoString anchor;
nsAutoString crossOrigin;
nsAutoString destination;
crossOrigin.SetIsVoid(true);
@ -653,6 +654,11 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
crossOrigin = value;
crossOrigin.StripWhitespace();
}
} else if (attr.LowerCaseEqualsLiteral("as")) {
if (destination.IsEmpty()) {
destination = value;
destination.StripWhitespace();
}
}
}
}
@ -666,7 +672,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
rv = ProcessLink(anchor, href, rel,
// prefer RFC 5987 variant over non-I18zed version
titleStar.IsEmpty() ? title : titleStar,
type, media, crossOrigin);
type, media, crossOrigin, destination);
}
href.Truncate();
@ -676,6 +682,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
media.Truncate();
anchor.Truncate();
crossOrigin.SetIsVoid(true);
destination.Truncate();
seenParameters = false;
}
@ -688,7 +695,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
rv = ProcessLink(anchor, href, rel,
// prefer RFC 5987 variant over non-I18zed version
titleStar.IsEmpty() ? title : titleStar,
type, media, crossOrigin);
type, media, crossOrigin, destination);
}
return rv;
@ -699,7 +706,8 @@ nsresult
nsContentSink::ProcessLink(const nsSubstring& aAnchor, const nsSubstring& aHref,
const nsSubstring& aRel, const nsSubstring& aTitle,
const nsSubstring& aType, const nsSubstring& aMedia,
const nsSubstring& aCrossOrigin)
const nsSubstring& aCrossOrigin,
const nsSubstring& aDestination)
{
uint32_t linkTypes =
nsStyleLinkElement::ParseLinkTypes(aRel, mDocument->NodePrincipal());

View file

@ -153,7 +153,8 @@ protected:
nsresult ProcessLink(const nsSubstring& aAnchor,
const nsSubstring& aHref, const nsSubstring& aRel,
const nsSubstring& aTitle, const nsSubstring& aType,
const nsSubstring& aMedia, const nsSubstring& aCrossOrigin);
const nsSubstring& aMedia, const nsSubstring& aCrossOrigin,
const nsSubstring& aDestination);
virtual nsresult ProcessStyleLink(nsIContent* aElement,
const nsSubstring& aHref,

View file

@ -110,6 +110,7 @@ GK_ATOM(archive, "archive")
GK_ATOM(area, "area")
GK_ATOM(arrow, "arrow")
GK_ATOM(article, "article")
GK_ATOM(as, "as")
GK_ATOM(ascending, "ascending")
GK_ATOM(aside, "aside")
GK_ATOM(aspectRatio, "aspect-ratio")

View file

@ -174,6 +174,8 @@ static uint32_t ToLinkMask(const nsAString& aLink, nsIPrincipal* aPrincipal)
return nsStyleLinkElement::eHTMLIMPORT;
else if (aLink.EqualsLiteral("preconnect"))
return nsStyleLinkElement::ePRECONNECT;
else if (aLink.EqualsLiteral("preload"))
return nsStyleLinkElement::ePRELOAD;
else
return 0;
}

View file

@ -64,7 +64,8 @@ public:
eNEXT = 0x00000008,
eALTERNATE = 0x00000010,
eHTMLIMPORT = 0x00000020,
ePRECONNECT = 0x00000040
ePRECONNECT = 0x00000040,
ePRELOAD = 0x00000080
};
// The return value is a bitwise or of 0 or more RelValues.

View file

@ -151,6 +151,7 @@ nsIAtom** const kAttributesHTML[] = {
&nsGkAtoms::accesskey,
&nsGkAtoms::action,
&nsGkAtoms::alt,
&nsGkAtoms::as,
&nsGkAtoms::autocomplete,
&nsGkAtoms::autofocus,
&nsGkAtoms::autoplay,

View file

@ -242,6 +242,11 @@ HTMLLinkElement::ParseAttribute(int32_t aNamespaceID,
return true;
}
if (aAttribute == nsGkAtoms::as) {
ParseDestinationValue(aValue, aResult);
return true;
}
if (aAttribute == nsGkAtoms::sizes) {
aResult.ParseAtomArray(aValue);
return true;
@ -374,6 +379,8 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
aName == nsGkAtoms::title ||
aName == nsGkAtoms::media ||
aName == nsGkAtoms::type ||
aName == nsGkAtoms::as ||
aName == nsGkAtoms::crossorigin ||
(LINK_DISABLED && aName == nsGkAtoms::disabled))) {
bool dropSheet = false;
if (aName == nsGkAtoms::rel) {
@ -471,6 +478,7 @@ static const DOMTokenListSupportedToken sSupportedRelValues[] = {
"preconnect",
"icon",
"search",
"preload",
nullptr
};
@ -602,6 +610,12 @@ HTMLLinkElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
return HTMLLinkElementBinding::Wrap(aCx, this, aGivenProto);
}
void
HTMLLinkElement::GetAs(nsAString& aResult)
{
GetEnumAttr(nsGkAtoms::as, EmptyCString().get(), aResult);
}
already_AddRefed<nsIDocument>
HTMLLinkElement::GetImport()
{

View file

@ -127,6 +127,11 @@ public:
{
SetHTMLAttr(nsGkAtoms::hreflang, aHreflang, aRv);
}
void GetAs(nsAString& aResult);
void SetAs(const nsAString& aAs, ErrorResult& aRv)
{
SetAttr(nsGkAtoms::as, aAs, aRv);
}
nsDOMTokenList* Sizes()
{
return GetTokenList(nsGkAtoms::sizes);

View file

@ -59,3 +59,9 @@ partial interface HTMLLinkElement {
[CEReactions, SetterThrows]
attribute DOMString integrity;
};
//https://w3c.github.io/preload/
partial interface HTMLLinkElement {
[SetterThrows, Pure]
attribute DOMString as;
};