1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsAttrValue.h"
8 #include "nsAttrValueOrString.h"
9 #include "nsGenericHTMLElement.h"
10 #include "nsGkAtoms.h"
11 #include "nsStyleConsts.h"
12 #include "mozilla/dom/Document.h"
13 #include "nsNetUtil.h"
14 #include "nsContentUtils.h"
15 #include "nsUnicharUtils.h" // for nsCaseInsensitiveStringComparator()
16 #include "nsIScriptContext.h"
17 #include "nsIScriptGlobalObject.h"
18 #include "nsServiceManagerUtils.h"
21 #include "nsDOMJSUtils.h"
22 #include "nsIScriptError.h"
23 #include "nsISupportsImpl.h"
24 #include "nsDOMTokenList.h"
25 #include "mozilla/dom/FetchPriority.h"
26 #include "mozilla/dom/HTMLScriptElement.h"
27 #include "mozilla/dom/HTMLScriptElementBinding.h"
28 #include "mozilla/Assertions.h"
29 #include "mozilla/StaticPrefs_dom.h"
31 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Script
)
33 using JS::loader::ScriptKind
;
35 namespace mozilla::dom
{
37 JSObject
* HTMLScriptElement::WrapNode(JSContext
* aCx
,
38 JS::Handle
<JSObject
*> aGivenProto
) {
39 return HTMLScriptElement_Binding::Wrap(aCx
, this, aGivenProto
);
42 HTMLScriptElement::HTMLScriptElement(
43 already_AddRefed
<mozilla::dom::NodeInfo
>&& aNodeInfo
,
44 FromParser aFromParser
)
45 : nsGenericHTMLElement(std::move(aNodeInfo
)), ScriptElement(aFromParser
) {
46 AddMutationObserver(this);
49 HTMLScriptElement::~HTMLScriptElement() = default;
51 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLScriptElement
,
53 nsIScriptLoaderObserver
,
57 NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLScriptElement
, nsGenericHTMLElement
,
60 nsresult
HTMLScriptElement::BindToTree(BindContext
& aContext
,
62 nsresult rv
= nsGenericHTMLElement::BindToTree(aContext
, aParent
);
63 NS_ENSURE_SUCCESS(rv
, rv
);
65 if (IsInComposedDoc()) {
72 bool HTMLScriptElement::ParseAttribute(int32_t aNamespaceID
, nsAtom
* aAttribute
,
73 const nsAString
& aValue
,
74 nsIPrincipal
* aMaybeScriptedPrincipal
,
75 nsAttrValue
& aResult
) {
76 if (aNamespaceID
== kNameSpaceID_None
) {
77 if (aAttribute
== nsGkAtoms::crossorigin
) {
78 ParseCORSValue(aValue
, aResult
);
82 if (aAttribute
== nsGkAtoms::integrity
) {
83 aResult
.ParseStringOrAtom(aValue
);
87 if (aAttribute
== nsGkAtoms::fetchpriority
) {
88 ParseFetchPriority(aValue
, aResult
);
92 if (aAttribute
== nsGkAtoms::blocking
&&
93 StaticPrefs::dom_element_blocking_enabled()) {
94 aResult
.ParseAtomArray(aValue
);
99 return nsGenericHTMLElement::ParseAttribute(aNamespaceID
, aAttribute
, aValue
,
100 aMaybeScriptedPrincipal
, aResult
);
103 nsresult
HTMLScriptElement::Clone(dom::NodeInfo
* aNodeInfo
,
104 nsINode
** aResult
) const {
107 HTMLScriptElement
* it
= new (aNodeInfo
->NodeInfoManager())
108 HTMLScriptElement(do_AddRef(aNodeInfo
), NOT_FROM_PARSER
);
110 nsCOMPtr
<nsINode
> kungFuDeathGrip
= it
;
111 nsresult rv
= const_cast<HTMLScriptElement
*>(this)->CopyInnerTo(it
);
112 NS_ENSURE_SUCCESS(rv
, rv
);
114 // The clone should be marked evaluated if we are.
115 it
->mAlreadyStarted
= mAlreadyStarted
;
116 it
->mLineNumber
= mLineNumber
;
117 it
->mMalformed
= mMalformed
;
119 kungFuDeathGrip
.swap(*aResult
);
124 void HTMLScriptElement::AfterSetAttr(int32_t aNamespaceID
, nsAtom
* aName
,
125 const nsAttrValue
* aValue
,
126 const nsAttrValue
* aOldValue
,
127 nsIPrincipal
* aMaybeScriptedPrincipal
,
129 if (nsGkAtoms::async
== aName
&& kNameSpaceID_None
== aNamespaceID
) {
132 if (nsGkAtoms::src
== aName
&& kNameSpaceID_None
== aNamespaceID
) {
133 mSrcTriggeringPrincipal
= nsContentUtils::GetAttrTriggeringPrincipal(
134 this, aValue
? aValue
->GetStringValue() : EmptyString(),
135 aMaybeScriptedPrincipal
);
137 return nsGenericHTMLElement::AfterSetAttr(
138 aNamespaceID
, aName
, aValue
, aOldValue
, aMaybeScriptedPrincipal
, aNotify
);
141 void HTMLScriptElement::GetInnerHTML(nsAString
& aInnerHTML
,
142 OOMReporter
& aError
) {
143 if (!nsContentUtils::GetNodeTextContent(this, false, aInnerHTML
, fallible
)) {
148 void HTMLScriptElement::SetInnerHTML(const nsAString
& aInnerHTML
,
149 nsIPrincipal
* aScriptedPrincipal
,
150 ErrorResult
& aError
) {
151 aError
= nsContentUtils::SetNodeTextContent(this, aInnerHTML
, true);
154 void HTMLScriptElement::GetText(nsAString
& aValue
, ErrorResult
& aRv
) const {
155 if (!nsContentUtils::GetNodeTextContent(this, false, aValue
, fallible
)) {
156 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
160 void HTMLScriptElement::SetText(const nsAString
& aValue
, ErrorResult
& aRv
) {
161 aRv
= nsContentUtils::SetNodeTextContent(this, aValue
, true);
164 // variation of this code in SVGScriptElement - check if changes
165 // need to be transfered when modifying
167 void HTMLScriptElement::GetScriptText(nsAString
& text
) const {
168 GetText(text
, IgnoreErrors());
171 void HTMLScriptElement::GetScriptCharset(nsAString
& charset
) {
175 void HTMLScriptElement::FreezeExecutionAttrs(const Document
* aOwnerDoc
) {
180 // Determine whether this is a(n) classic/module/importmap script.
181 DetermineKindFromType(aOwnerDoc
);
183 // variation of this code in SVGScriptElement - check if changes
184 // need to be transfered when modifying. Note that we don't use GetSrc here
185 // because it will return the base URL when the attr value is "".
187 if (GetAttr(nsGkAtoms::src
, src
)) {
188 // Empty src should be treated as invalid URL.
189 if (!src
.IsEmpty()) {
190 nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(mUri
), src
,
191 OwnerDoc(), GetBaseURI());
194 AutoTArray
<nsString
, 2> params
= {u
"src"_ns
, src
};
196 nsContentUtils::ReportToConsole(
197 nsIScriptError::warningFlag
, "HTML"_ns
, OwnerDoc(),
198 nsContentUtils::eDOM_PROPERTIES
, "ScriptSourceInvalidUri", params
,
199 nullptr, u
""_ns
, GetScriptLineNumber(),
200 GetScriptColumnNumber().oneOriginValue());
203 AutoTArray
<nsString
, 1> params
= {u
"src"_ns
};
205 nsContentUtils::ReportToConsole(
206 nsIScriptError::warningFlag
, "HTML"_ns
, OwnerDoc(),
207 nsContentUtils::eDOM_PROPERTIES
, "ScriptSourceEmpty", params
, nullptr,
208 u
""_ns
, GetScriptLineNumber(),
209 GetScriptColumnNumber().oneOriginValue());
212 // At this point mUri will be null for invalid URLs.
216 bool async
= (mExternal
|| mKind
== ScriptKind::eModule
) && Async();
217 bool defer
= mExternal
&& Defer();
219 mDefer
= !async
&& defer
;
225 CORSMode
HTMLScriptElement::GetCORSMode() const {
226 return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin
));
229 FetchPriority
HTMLScriptElement::GetFetchPriority() const {
230 return nsGenericHTMLElement::GetFetchPriority();
233 mozilla::dom::ReferrerPolicy
HTMLScriptElement::GetReferrerPolicy() {
234 return GetReferrerPolicyAsEnum();
237 bool HTMLScriptElement::HasScriptContent() {
238 return (mFrozen
? mExternal
: HasAttr(nsGkAtoms::src
)) ||
239 nsContentUtils::HasNonEmptyTextContent(this);
242 // https://html.spec.whatwg.org/multipage/scripting.html#dom-script-supports
244 bool HTMLScriptElement::Supports(const GlobalObject
& aGlobal
,
245 const nsAString
& aType
) {
246 nsAutoString
type(aType
);
247 return aType
.EqualsLiteral("classic") || aType
.EqualsLiteral("module") ||
249 aType
.EqualsLiteral("importmap");
252 nsDOMTokenList
* HTMLScriptElement::Blocking() {
255 new nsDOMTokenList(this, nsGkAtoms::blocking
, sSupportedBlockingValues
);
260 bool HTMLScriptElement::IsPotentiallyRenderBlocking() {
261 return BlockingContainsRender();
263 // TODO: handle implicitly potentially render blocking
264 // https://html.spec.whatwg.org/#implicitly-potentially-render-blocking
265 // A script element el is implicitly potentially render-blocking if el's type
266 // is "classic", el is parser-inserted, and el does not have an async or defer
270 } // namespace mozilla::dom