SVGScriptElement.cpp (7985B)
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/. */ 6 7 #include "mozilla/dom/SVGScriptElement.h" 8 9 #include "mozilla/dom/Document.h" 10 #include "mozilla/dom/FetchPriority.h" 11 #include "mozilla/dom/SVGScriptElementBinding.h" 12 #include "nsContentUtils.h" 13 #include "nsGkAtoms.h" 14 #include "nsIScriptError.h" 15 #include "nsNetUtil.h" 16 17 NS_IMPL_NS_NEW_SVG_ELEMENT_CHECK_PARSER(Script) 18 19 using JS::loader::ScriptKind; 20 21 namespace mozilla::dom { 22 23 JSObject* SVGScriptElement::WrapNode(JSContext* aCx, 24 JS::Handle<JSObject*> aGivenProto) { 25 return SVGScriptElement_Binding::Wrap(aCx, this, aGivenProto); 26 } 27 28 SVGElement::StringInfo SVGScriptElement::sStringInfo[2] = { 29 {nsGkAtoms::href, kNameSpaceID_None, false}, 30 {nsGkAtoms::href, kNameSpaceID_XLink, false}}; 31 32 //---------------------------------------------------------------------- 33 // nsISupports methods 34 35 NS_IMPL_ISUPPORTS_INHERITED(SVGScriptElement, SVGScriptElementBase, 36 nsIScriptLoaderObserver, nsIScriptElement, 37 nsIMutationObserver) 38 39 //---------------------------------------------------------------------- 40 // Implementation 41 42 SVGScriptElement::SVGScriptElement( 43 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, 44 FromParser aFromParser) 45 : SVGScriptElementBase(std::move(aNodeInfo)), ScriptElement(aFromParser) { 46 AddMutationObserver(this); 47 } 48 49 //---------------------------------------------------------------------- 50 // nsINode methods 51 52 nsresult SVGScriptElement::Clone(dom::NodeInfo* aNodeInfo, 53 nsINode** aResult) const { 54 *aResult = nullptr; 55 56 SVGScriptElement* it = new (aNodeInfo->NodeInfoManager()) 57 SVGScriptElement(do_AddRef(aNodeInfo), NOT_FROM_PARSER); 58 59 nsCOMPtr<nsINode> kungFuDeathGrip = it; 60 nsresult rv1 = it->Init(); 61 nsresult rv2 = const_cast<SVGScriptElement*>(this)->CopyInnerTo(it); 62 NS_ENSURE_SUCCESS(rv1, rv1); 63 NS_ENSURE_SUCCESS(rv2, rv2); 64 65 // The clone should be marked evaluated if we are. 66 it->mAlreadyStarted = mAlreadyStarted; 67 it->mLineNumber = mLineNumber; 68 it->mMalformed = mMalformed; 69 70 kungFuDeathGrip.swap(*aResult); 71 72 return NS_OK; 73 } 74 75 //---------------------------------------------------------------------- 76 void SVGScriptElement::GetType(nsAString& aType) { 77 GetAttr(nsGkAtoms::type, aType); 78 } 79 80 void SVGScriptElement::SetType(const nsAString& aType, ErrorResult& rv) { 81 rv = SetAttr(kNameSpaceID_None, nsGkAtoms::type, aType, true); 82 } 83 84 void SVGScriptElement::GetCrossOrigin(nsAString& aCrossOrigin) { 85 // Null for both missing and invalid defaults is ok, since we 86 // always parse to an enum value, so we don't need an invalid 87 // default, and we _want_ the missing default to be null. 88 GetEnumAttr(nsGkAtoms::crossorigin, nullptr, aCrossOrigin); 89 } 90 91 void SVGScriptElement::SetCrossOrigin(const nsAString& aCrossOrigin, 92 ErrorResult& aError) { 93 SetOrRemoveNullableStringAttr(nsGkAtoms::crossorigin, aCrossOrigin, aError); 94 } 95 96 already_AddRefed<DOMSVGAnimatedString> SVGScriptElement::Href() { 97 return mStringAttributes[HREF].IsExplicitlySet() || 98 !mStringAttributes[XLINK_HREF].IsExplicitlySet() 99 ? mStringAttributes[HREF].ToDOMAnimatedString(this) 100 : mStringAttributes[XLINK_HREF].ToDOMAnimatedString(this); 101 } 102 103 //---------------------------------------------------------------------- 104 // nsIScriptElement methods 105 106 void SVGScriptElement::GetScriptText(nsAString& text) const { 107 nsContentUtils::GetNodeTextContent(this, false, text); 108 } 109 110 void SVGScriptElement::GetScriptCharset(nsAString& charset) { 111 charset.Truncate(); 112 } 113 114 void SVGScriptElement::FreezeExecutionAttrs(const Document* aOwnerDoc) { 115 if (mFrozen) { 116 return; 117 } 118 119 // Determine whether this is a(n) classic/module/importmap script. 120 DetermineKindFromType(aOwnerDoc); 121 122 if (mStringAttributes[HREF].IsExplicitlySet() || 123 mStringAttributes[XLINK_HREF].IsExplicitlySet()) { 124 // variation of this code in nsHTMLScriptElement - check if changes 125 // need to be transferred when modifying 126 bool isHref = false; 127 nsAutoString src; 128 if (mStringAttributes[HREF].IsExplicitlySet()) { 129 mStringAttributes[HREF].GetAnimValue(src, this); 130 isHref = true; 131 } else { 132 mStringAttributes[XLINK_HREF].GetAnimValue(src, this); 133 } 134 135 SourceLocation loc{OwnerDoc()->GetDocumentURI(), GetScriptLineNumber(), 136 GetScriptColumnNumber().oneOriginValue()}; 137 // Empty src should be treated as invalid URL. 138 if (!src.IsEmpty()) { 139 NS_NewURI(getter_AddRefs(mUri), src, nullptr, GetBaseURI()); 140 141 if (!mUri) { 142 AutoTArray<nsString, 2> params = { 143 isHref ? u"href"_ns : u"xlink:href"_ns, src}; 144 145 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "SVG"_ns, 146 OwnerDoc(), 147 nsContentUtils::eDOM_PROPERTIES, 148 "ScriptSourceInvalidUri", params, loc); 149 } 150 } else { 151 AutoTArray<nsString, 1> params = {isHref ? u"href"_ns : u"xlink:href"_ns}; 152 153 nsContentUtils::ReportToConsole( 154 nsIScriptError::warningFlag, "SVG"_ns, OwnerDoc(), 155 nsContentUtils::eDOM_PROPERTIES, "ScriptSourceEmpty", params, loc); 156 } 157 158 // At this point mUri will be null for invalid URLs. 159 mExternal = true; 160 } 161 162 bool async = (mExternal || mKind == ScriptKind::eModule) && Async(); 163 bool defer = mExternal && Defer(); 164 165 mDefer = !async && defer; 166 mAsync = async; 167 168 mFrozen = true; 169 } 170 171 //---------------------------------------------------------------------- 172 // ScriptElement methods 173 bool SVGScriptElement::HasExternalScriptContent() { 174 return mFrozen ? mExternal 175 : (mStringAttributes[HREF].IsExplicitlySet() || 176 mStringAttributes[XLINK_HREF].IsExplicitlySet()); 177 } 178 179 //---------------------------------------------------------------------- 180 // SVGElement methods 181 182 SVGElement::StringAttributesInfo SVGScriptElement::GetStringInfo() { 183 return StringAttributesInfo(mStringAttributes, sStringInfo, 184 std::size(sStringInfo)); 185 } 186 187 //---------------------------------------------------------------------- 188 // nsIContent methods 189 190 nsresult SVGScriptElement::BindToTree(BindContext& aContext, nsINode& aParent) { 191 nsresult rv = SVGScriptElementBase::BindToTree(aContext, aParent); 192 NS_ENSURE_SUCCESS(rv, rv); 193 194 if (IsInComposedDoc()) { 195 MaybeProcessScript(nullptr /* aParser */); 196 } 197 198 return NS_OK; 199 } 200 201 bool SVGScriptElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, 202 const nsAString& aValue, 203 nsIPrincipal* aMaybeScriptedPrincipal, 204 nsAttrValue& aResult) { 205 if (aNamespaceID == kNameSpaceID_None) { 206 if (aAttribute == nsGkAtoms::crossorigin) { 207 ParseCORSValue(aValue, aResult); 208 return true; 209 } 210 if (aAttribute == nsGkAtoms::fetchpriority) { 211 ParseFetchPriority(aValue, aResult); 212 return true; 213 } 214 } 215 216 return SVGScriptElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue, 217 aMaybeScriptedPrincipal, aResult); 218 } 219 220 CORSMode SVGScriptElement::GetCORSMode() const { 221 return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin)); 222 } 223 224 void SVGScriptElement::GetFetchPriority(nsAString& aFetchPriority) const { 225 GetEnumAttr(nsGkAtoms::fetchpriority, kFetchPriorityAttributeValueAuto, 226 aFetchPriority); 227 } 228 229 FetchPriority SVGScriptElement::GetFetchPriority() const { 230 return Element::GetFetchPriority(); 231 } 232 233 } // namespace mozilla::dom