nsIScriptElement.h (10279B)
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 #ifndef nsIScriptElement_h___ 8 #define nsIScriptElement_h___ 9 10 #include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin 11 #include "js/loader/ScriptKind.h" 12 #include "mozilla/AlreadyAddRefed.h" 13 #include "mozilla/Assertions.h" 14 #include "mozilla/CORSMode.h" 15 #include "mozilla/dom/FromParser.h" 16 #include "nsCOMPtr.h" 17 #include "nsID.h" 18 #include "nsIScriptLoaderObserver.h" 19 #include "nsIWeakReferenceUtils.h" 20 #include "nsStringFwd.h" 21 #include "nscore.h" 22 23 // XXX Avoid including this here by moving function bodies to the cpp file 24 #include "nsIPrincipal.h" 25 26 class nsIContent; 27 class nsIParser; 28 class nsIPrincipal; 29 class nsIURI; 30 31 namespace mozilla::dom { 32 class Document; 33 enum class FetchPriority : uint8_t; 34 enum class ReferrerPolicy : uint8_t; 35 } // namespace mozilla::dom 36 37 // Must be kept in sync with xpcom/rust/xpcom/src/interfaces/nonidl.rs 38 #define NS_ISCRIPTELEMENT_IID \ 39 {0xe60fca9b, 0x1b96, 0x4e4e, {0xa9, 0xb4, 0xdc, 0x98, 0x4f, 0x88, 0x3f, 0x9c}} 40 41 /** 42 * Internal interface implemented by script elements 43 */ 44 class nsIScriptElement : public nsIScriptLoaderObserver { 45 public: 46 NS_INLINE_DECL_STATIC_IID(NS_ISCRIPTELEMENT_IID) 47 48 explicit nsIScriptElement(mozilla::dom::FromParser aFromParser) 49 : mLineNumber(1), 50 mColumnNumber(1), 51 mAlreadyStarted(false), 52 mMalformed(false), 53 mDoneAddingChildren(aFromParser == mozilla::dom::NOT_FROM_PARSER || 54 aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT), 55 mForceAsync(aFromParser == mozilla::dom::NOT_FROM_PARSER || 56 aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT), 57 mFrozen(false), 58 mDefer(false), 59 mAsync(false), 60 mExternal(false), 61 mIsTrusted(true), 62 mKind(JS::loader::ScriptKind::eClassic), 63 mParserCreated(aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT 64 ? mozilla::dom::NOT_FROM_PARSER 65 : aFromParser), 66 // Fragment parser-created scripts (if executable) 67 // behave like script-created scripts. 68 mCreatorParser(nullptr) {} 69 70 /** 71 * Content type identifying the scripting language. Can be empty, in 72 * which case javascript will be assumed. 73 * Return false if type attribute is not found. 74 */ 75 virtual bool GetScriptType(nsAString& type) = 0; 76 77 /** 78 * Location of script source text. Can return null, in which case 79 * this is assumed to be an inline script element. 80 */ 81 nsIURI* GetScriptURI() { 82 MOZ_ASSERT(mFrozen, "Not ready for this call yet!"); 83 return mUri; 84 } 85 86 nsIPrincipal* GetScriptURITriggeringPrincipal() { 87 MOZ_ASSERT(mFrozen, "Not ready for this call yet!"); 88 return mSrcTriggeringPrincipal; 89 } 90 91 /** 92 * Script source text for inline script elements. 93 */ 94 virtual void GetScriptText(nsAString& text) const = 0; 95 96 virtual void GetScriptCharset(nsAString& charset) = 0; 97 98 /** 99 * Freezes the return values of the following methods so that subsequent 100 * modifications to the attributes don't change execution behavior: 101 * - GetScriptIsModule() 102 * - GetScriptIsImportMap() 103 * - GetScriptDeferred() 104 * - GetScriptAsync() 105 * - GetScriptURI() 106 * - GetScriptExternal() 107 */ 108 virtual void FreezeExecutionAttrs(const mozilla::dom::Document*) = 0; 109 110 /** 111 * Is the script a module script. 112 */ 113 bool GetScriptIsModule() { 114 MOZ_ASSERT(mFrozen, "Not ready for this call yet!"); 115 return mKind == JS::loader::ScriptKind::eModule; 116 } 117 118 /** 119 * Is the script an import map. 120 */ 121 bool GetScriptIsImportMap() { 122 MOZ_ASSERT(mFrozen, "Not ready for this call yet!"); 123 return mKind == JS::loader::ScriptKind::eImportMap; 124 } 125 126 /** 127 * Is the script deferred. 128 */ 129 bool GetScriptDeferred() { 130 MOZ_ASSERT(mFrozen, "Not ready for this call yet!"); 131 return mDefer; 132 } 133 134 /** 135 * Is the script async. 136 */ 137 bool GetScriptAsync() { 138 MOZ_ASSERT(mFrozen, "Not ready for this call yet!"); 139 return mAsync; 140 } 141 142 /** 143 * Is the script an external script? 144 */ 145 bool GetScriptExternal() { 146 MOZ_ASSERT(mFrozen, "Not ready for this call yet!"); 147 return mExternal; 148 } 149 150 /** 151 * Returns how the element was created. 152 */ 153 mozilla::dom::FromParser GetParserCreated() { return mParserCreated; } 154 155 void SetScriptLineNumber(uint32_t aLineNumber) { mLineNumber = aLineNumber; } 156 157 uint32_t GetScriptLineNumber() { return mLineNumber; } 158 159 void SetScriptColumnNumber(JS::ColumnNumberOneOrigin aColumnNumber) { 160 mColumnNumber = aColumnNumber; 161 } 162 163 JS::ColumnNumberOneOrigin GetScriptColumnNumber() { return mColumnNumber; } 164 165 void SetIsMalformed() { mMalformed = true; } 166 167 bool IsMalformed() { return mMalformed; } 168 169 void PreventExecution() { mAlreadyStarted = true; } 170 171 void LoseParserInsertedness() { 172 mUri = nullptr; 173 mCreatorParser = nullptr; 174 mParserCreated = mozilla::dom::NOT_FROM_PARSER; 175 mForceAsync = !GetAsyncState(); 176 177 // Reset state set by FreezeExecutionAttrs(). 178 mFrozen = false; 179 mExternal = false; 180 mAsync = false; 181 mDefer = false; 182 mKind = JS::loader::ScriptKind::eClassic; 183 } 184 185 void SetCreatorParser(nsIParser* aParser); 186 187 /** 188 * Unblocks the creator parser 189 */ 190 void UnblockParser(); 191 192 /** 193 * Attempts to resume parsing asynchronously 194 */ 195 void ContinueParserAsync(); 196 197 /** 198 * Informs the creator parser that the evaluation of this script is starting 199 */ 200 void BeginEvaluating(); 201 202 /** 203 * Informs the creator parser that the evaluation of this script is ending 204 */ 205 void EndEvaluating(); 206 207 /** 208 * Retrieves a pointer to the creator parser if this has one or null if not 209 */ 210 already_AddRefed<nsIParser> GetCreatorParser(); 211 212 /** 213 * This method is called when the parser finishes creating the script 214 * element's children, if any are present. 215 * 216 * @param aParser If non-null, a parser that can be blocked until the script 217 * becomes available. 218 * @return whether a non-null aParser would be blocked while this script is 219 * being loaded. 220 */ 221 bool AttemptToExecute(nsCOMPtr<nsIParser> aParser); 222 223 /** 224 * Get the CORS mode of the script element 225 */ 226 virtual mozilla::CORSMode GetCORSMode() const { 227 /* Default to no CORS */ 228 return mozilla::CORS_NONE; 229 } 230 231 /** 232 * Get the fetch priority 233 * (https://html.spec.whatwg.org/multipage/scripting.html#attr-script-fetchpriority) 234 * of the script element. 235 */ 236 virtual mozilla::dom::FetchPriority GetFetchPriority() const = 0; 237 238 /** 239 * Get referrer policy of the script element 240 */ 241 virtual mozilla::dom::ReferrerPolicy GetReferrerPolicy(); 242 243 /** 244 * Fire an error event 245 */ 246 virtual nsresult FireErrorEvent() = 0; 247 248 /** 249 * This must be called on scripts with mIsTrusted set to false in 250 * order retrieve the associated aSourceText (source text after 251 * application of the Trusted Types's default policy). 252 */ 253 virtual MOZ_CAN_RUN_SCRIPT nsresult 254 GetTrustedTypesCompliantInlineScriptText(nsString& aSourceText) = 0; 255 256 protected: 257 /** 258 * Processes the script if it's in the document-tree and links to or 259 * contains a script. Once it has been evaluated there is no way to make it 260 * reevaluate the script, you'll have to create a new element. This also means 261 * that when adding a src attribute to an element that already contains an 262 * inline script, the script referenced by the src attribute will not be 263 * loaded. 264 * 265 * In order to be able to use multiple childNodes, or to use the 266 * fallback mechanism of using both inline script and linked script you have 267 * to add all attributes and childNodes before adding the element to the 268 * document-tree. 269 * 270 * @return whether the parser will be blocked while this script is being 271 * loaded 272 */ 273 virtual bool MaybeProcessScript(nsCOMPtr<nsIParser> aParser) = 0; 274 275 /** 276 * Since we've removed the XPCOM interface to HTML elements, we need a way to 277 * retreive async state from script elements without bringing the type in. 278 */ 279 virtual bool GetAsyncState() = 0; 280 281 /** 282 * Allow implementing elements to avoid unnecessary QueryReferences. 283 */ 284 virtual nsIContent* GetAsContent() = 0; 285 286 /** 287 * Determine whether this is a(n) classic/module/importmap script. 288 */ 289 void DetermineKindFromType(const mozilla::dom::Document* aOwnerDoc); 290 291 bool IsClassicNonAsyncDefer(); 292 293 /** 294 * The start line number of the script. 295 */ 296 uint32_t mLineNumber; 297 298 /** 299 * The start column number of the script. 300 */ 301 JS::ColumnNumberOneOrigin mColumnNumber; 302 303 /** 304 * The "already started" flag per HTML5. 305 */ 306 bool mAlreadyStarted; 307 308 /** 309 * The script didn't have an end tag. 310 */ 311 bool mMalformed; 312 313 /** 314 * False if parser-inserted but the parser hasn't triggered running yet. 315 */ 316 bool mDoneAddingChildren; 317 318 /** 319 * If true, the .async property returns true instead of reflecting the 320 * content attribute. 321 */ 322 bool mForceAsync; 323 324 /** 325 * Whether src, defer and async are frozen. 326 */ 327 bool mFrozen; 328 329 /** 330 * The effective deferredness. 331 */ 332 bool mDefer; 333 334 /** 335 * The effective asyncness. 336 */ 337 bool mAsync; 338 339 /** 340 * The effective externalness. A script can be external with mUri being null 341 * if the src attribute contained an invalid URL string. 342 */ 343 bool mExternal; 344 345 /** 346 * Whether a script element is considered trustworthy for execution. 347 * https://github.com/w3c/trusted-types/pull/579 348 */ 349 bool mIsTrusted; 350 351 /** 352 * The effective script kind. 353 */ 354 JS::loader::ScriptKind mKind; 355 356 /** 357 * Whether this element was parser-created. 358 */ 359 mozilla::dom::FromParser mParserCreated; 360 361 /** 362 * The effective src (or null if no src). 363 */ 364 nsCOMPtr<nsIURI> mUri; 365 366 /** 367 * The triggering principal for the src URL. 368 */ 369 nsCOMPtr<nsIPrincipal> mSrcTriggeringPrincipal; 370 371 /** 372 * The creator parser of a non-defer, non-async parser-inserted script. 373 */ 374 nsWeakPtr mCreatorParser; 375 }; 376 377 #endif // nsIScriptElement_h___