Skip to content

Commit

Permalink
Bug 1839954 - support async defer and module scripts r=emilio
Browse files Browse the repository at this point in the history
https://www.w3.org/2012/01/05-svg-irc#T21-07-03 says that async and defer should be supported as does the specification https://www.w3.org/TR/SVG2/interact.html#ScriptElement

w3c/svgwg#918 tracks getting the SVGScriptElement webidl updated.

Differential Revision: https://phabricator.services.mozilla.com/D181936

UltraBlame original commit: 21669d226d640b0b8d4b44449e512e0942b113a1
  • Loading branch information
marco-c committed Jul 16, 2023
1 parent 04c2866 commit 13c353e
Show file tree
Hide file tree
Showing 15 changed files with 156 additions and 37 deletions.
4 changes: 2 additions & 2 deletions dom/base/Document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18114,12 +18114,12 @@ void Document::RecordNavigationTiming(ReadyState aReadyState) {
}
}

bool Document::ModuleScriptsEnabled() {
bool Document::ModuleScriptsEnabled() const {
return nsContentUtils::IsChromeDoc(this) ||
StaticPrefs::dom_moduleScripts_enabled();
}

bool Document::ImportMapsEnabled() {
bool Document::ImportMapsEnabled() const {
return nsContentUtils::IsChromeDoc(this) ||
StaticPrefs::dom_importMaps_enabled();
}
Expand Down
4 changes: 2 additions & 2 deletions dom/base/Document.h
Original file line number Diff line number Diff line change
Expand Up @@ -4029,9 +4029,9 @@ class Document : public nsINode,

mozilla::dom::FeaturePolicy* FeaturePolicy() const;

bool ModuleScriptsEnabled();
bool ModuleScriptsEnabled() const;

bool ImportMapsEnabled();
bool ImportMapsEnabled() const;



Expand Down
24 changes: 2 additions & 22 deletions dom/html/HTMLScriptElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,33 +150,13 @@ void HTMLScriptElement::GetScriptCharset(nsAString& charset) {
GetCharset(charset);
}

void HTMLScriptElement::FreezeExecutionAttrs(Document* aOwnerDoc) {
void HTMLScriptElement::FreezeExecutionAttrs(const Document* aOwnerDoc) {
if (mFrozen) {
return;
}

MOZ_ASSERT((mKind != ScriptKind::eModule) &&
(mKind != ScriptKind::eImportMap) && !mAsync && !mDefer &&
!mExternal);


nsAutoString type;
GetScriptType(type);
if (!type.IsEmpty()) {
if (aOwnerDoc->ModuleScriptsEnabled() &&
type.LowerCaseEqualsASCII("module")) {
mKind = ScriptKind::eModule;
}





if (aOwnerDoc->ImportMapsEnabled() &&
type.LowerCaseEqualsASCII("importmap")) {
mKind = ScriptKind::eImportMap;
}
}
DetermineKindFromType(aOwnerDoc);



Expand Down
2 changes: 1 addition & 1 deletion dom/html/HTMLScriptElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class HTMLScriptElement final : public nsGenericHTMLElement,

virtual void GetScriptText(nsAString& text) const override;
virtual void GetScriptCharset(nsAString& charset) override;
virtual void FreezeExecutionAttrs(Document* aOwnerDoc) override;
virtual void FreezeExecutionAttrs(const Document* aOwnerDoc) override;
virtual CORSMode GetCORSMode() const override;
virtual mozilla::dom::ReferrerPolicy GetReferrerPolicy() override;

Expand Down
29 changes: 29 additions & 0 deletions dom/script/nsIScriptElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@

#include "nsIScriptElement.h"

#include "mozilla/dom/Document.h"
#include "mozilla/dom/ReferrerPolicyBinding.h"
#include "nsIParser.h"
#include "nsIWeakReference.h"

using JS::loader::ScriptKind;

void nsIScriptElement::SetCreatorParser(nsIParser* aParser) {
mCreatorParser = do_GetWeakReference(aParser);
}
Expand Down Expand Up @@ -51,3 +54,29 @@ already_AddRefed<nsIParser> nsIScriptElement::GetCreatorParser() {
mozilla::dom::ReferrerPolicy nsIScriptElement::GetReferrerPolicy() {
return mozilla::dom::ReferrerPolicy::_empty;
}

void nsIScriptElement::DetermineKindFromType(
const mozilla::dom::Document* aOwnerDoc) {
MOZ_ASSERT((mKind != ScriptKind::eModule) &&
(mKind != ScriptKind::eImportMap) && !mAsync && !mDefer &&
!mExternal);

nsAutoString type;
GetScriptType(type);

if (!type.IsEmpty()) {
if (aOwnerDoc->ModuleScriptsEnabled() &&
type.LowerCaseEqualsASCII("module")) {
mKind = ScriptKind::eModule;
}





if (aOwnerDoc->ImportMapsEnabled() &&
type.LowerCaseEqualsASCII("importmap")) {
mKind = ScriptKind::eImportMap;
}
}
}
7 changes: 6 additions & 1 deletion dom/script/nsIScriptElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class nsIScriptElement : public nsIScriptLoaderObserver {



virtual void FreezeExecutionAttrs(mozilla::dom::Document*) = 0;
virtual void FreezeExecutionAttrs(const mozilla::dom::Document*) = 0;



Expand Down Expand Up @@ -279,6 +279,11 @@ class nsIScriptElement : public nsIScriptLoaderObserver {



void DetermineKindFromType(const mozilla::dom::Document* aOwnerDoc);




uint32_t mLineNumber;


Expand Down
13 changes: 12 additions & 1 deletion dom/svg/SVGScriptElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

NS_IMPL_NS_NEW_SVG_ELEMENT_CHECK_PARSER(Script)

using JS::loader::ScriptKind;

namespace mozilla::dom {

JSObject* SVGScriptElement::WrapNode(JSContext* aCx,
Expand Down Expand Up @@ -106,11 +108,14 @@ void SVGScriptElement::GetScriptCharset(nsAString& charset) {
charset.Truncate();
}

void SVGScriptElement::FreezeExecutionAttrs(Document* aOwnerDoc) {
void SVGScriptElement::FreezeExecutionAttrs(const Document* aOwnerDoc) {
if (mFrozen) {
return;
}


DetermineKindFromType(aOwnerDoc);

if (mStringAttributes[HREF].IsExplicitlySet() ||
mStringAttributes[XLINK_HREF].IsExplicitlySet()) {

Expand Down Expand Up @@ -150,6 +155,12 @@ void SVGScriptElement::FreezeExecutionAttrs(Document* aOwnerDoc) {
mExternal = true;
}

bool async = (mExternal || mKind == ScriptKind::eModule) && Async();
bool defer = mExternal && Defer();

mDefer = !async && defer;
mAsync = async;

mFrozen = true;
}

Expand Down
9 changes: 8 additions & 1 deletion dom/svg/SVGScriptElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class SVGScriptElement final : public SVGScriptElementBase,

void GetScriptText(nsAString& text) const override;
void GetScriptCharset(nsAString& charset) override;
void FreezeExecutionAttrs(Document* aOwnerDoc) override;
void FreezeExecutionAttrs(const Document* aOwnerDoc) override;
CORSMode GetCORSMode() const override;


Expand All @@ -59,6 +59,13 @@ class SVGScriptElement final : public SVGScriptElementBase,

void GetType(nsAString& aType);
void SetType(const nsAString& aType, ErrorResult& rv);
bool Async() { return mForceAsync || GetBoolAttr(nsGkAtoms::async); }
void SetAsync(bool aValue) {
mForceAsync = false;
SetBoolAttr(nsGkAtoms::async, aValue);
}
bool Defer() { return GetBoolAttr(nsGkAtoms::defer); }
void SetDefer(bool aDefer) { SetBoolAttr(nsGkAtoms::defer, aDefer); }
void GetCrossOrigin(nsAString& aCrossOrigin);
void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& aError);
already_AddRefed<DOMSVGAnimatedString> Href();
Expand Down
5 changes: 3 additions & 2 deletions dom/webidl/SVGScriptElement.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
interface SVGScriptElement : SVGElement {
[SetterThrows]
attribute DOMString type;

// CORS attribute
// See https://github.com/w3c/svgwg/issues/918
attribute boolean async;
attribute boolean defer;
[SetterThrows]
attribute DOMString? crossOrigin;
};
Expand Down

This file was deleted.

29 changes: 29 additions & 0 deletions testing/web-platform/tests/svg/interact/scripted/async-01.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions testing/web-platform/tests/svg/interact/scripted/defer-01.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions testing/web-platform/tests/svg/interact/scripted/defer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
t.step(() => {
assert_equals(script_run_status, "deferred", "script run status");
});
t.done();
13 changes: 13 additions & 0 deletions testing/web-platform/tests/svg/interact/scripted/log.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import time

def main(request, response):
response.headers.append(b"Content-Type", b"text/javascript")
try:
script_id = int(request.GET.first(b"id"))
delay = int(request.GET.first(b"sec"))
except:
response.set_error(400, u"Invalid parameter")

time.sleep(int(delay))

return u"log('%s')" % script_id
20 changes: 20 additions & 0 deletions testing/web-platform/tests/svg/interact/scripted/module-01.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 13c353e

Please sign in to comment.