script element
interface HTMLScriptElement : HTMLElement {
attribute DOMString src;
attribute DOMString type;
attribute DOMString charset;
attribute boolean async;
attribute boolean defer;
attribute DOMString? crossOrigin;
attribute DOMString text;
attribute DOMString nonce;
};
type attribute allows customization of the
type of script represented:
* Omitting the attribute, or setting it to a JavaScript MIME type, means that the script
is a classic script, to be interpreted according to the JavaScript
Script top-level production. Classic scripts are affected by the
<{script/charset}>, <{script/async}>, and <{script/defer}> attributes. Authors should omit
the attribute, instead of redundantly giving a JavaScript MIME type.
* Setting the attribute to an ASCII case-insensitive match for the string
"module" means that the script is a module script, to be interpreted
according to the JavaScript Module top-level production. Module scripts are
not affected by the <{script/charset}> and <{script/defer}> attributes.
* Setting the attribute to any other value means that the script is a
data block, which is not processed. None of the
<{script}> attributes (except <{script/type}> itself) have any effect on data blocks.
Authors must use a valid MIME type that is not a JavaScript MIME type to denote
data blocks.
The requirement that data blocks must be denoted using a valid MIME type is in
place to avoid potential future collisions. If this specification ever adds additional types
of [=concept/script=], they will be triggered by setting the <{script/type}> attribute to
something which is not a MIME type, like how the "module" value denotes
module scripts. By using a valid MIME type now, you ensure that your data block
will not ever be reinterpreted as a different script type, even in future user agents.
src attribute,
which if specified gives the [=url/URL=] of the external script resource to use.
If <{script/src}> is specified, it must be a
valid non-empty URL potentially surrounded by spaces. The contents of inline
<{script}> elements, or the external script resource, must conform with the requirements
of the JavaScript specification's Script or Module productions,
for classic scripts and module scripts respectively. [[ECMA-262]]
When used to include data blocks, the data must be embedded inline, the format of the data
must be given using the <{script/type}> attribute, and the contents of the <{script}> element
must conform to the requirements defined for the format used. The <{script/src}>,
<{script/charset}>, <{script/async}>, <{script/defer}>, <{script/crossorigin}>, and
<{script/integrity}> attributes must not be specified.
The async and
defer attributes are boolean attributes
that indicate how a script should be loaded and executed.
They have no effect, and must not be used, on <{script}> elements that do not have a
<{script/src}> attribute specified. Classic scripts may specify either or both of
<{script/defer}> and <{script/async}>; module scripts may specify <{script/async}>.
There are several possible modes that can be selected using these attributes, and depending
on the script's <{script/type}>.
If a <{script/defer}> attribute is present, then a classic script will be fetched
in parallel to parsing, and only evaluated when parsing is complete. The attribute has
no effect on module scripts or data blocks.
If the <{script/async}> attribute is present, then a classic or module script will be fetched
in parallel to parsing. A module script will be evaluated as soon as it is available,
(potentially before parsing completes), as will a classic script unless a <{script/defer}>
attribute is present.
If neither attribute is present, the script is fetched and evaluated immediately, blocking
parsing until these are both complete.
The exact processing details for these attributes are, for mostly historical reasons, somewhat non-trivial, involving a number of aspects of HTML. The implementation requirements are therefore by necessity scattered throughout the specification. The algorithms below (in this section) describe the core of this processing, but these algorithms reference and are referenced by the parsing rules for <{script}> [=start tag|start=] and [=end tag|end=] tags in HTML, in foreign content, and in XML, the rules for the {{Document/write()|document.write()}} method, the handling of scripting, etc.
The <{script/defer}> attribute may be specified even if the <{script/async}> attribute is specified, to cause legacy Web browsers that only support <{script/defer}> (and not <{script/async}>) to fall back to the <{script/defer}> behavior instead of the blocking behavior that is the default. Thecrossorigin attribute is a
CORS settings attribute. For classic scripts, it controls whether error information
will be exposed, when the script is obtained from other origins. For
module scripts, it controls the credentials mode used for cross-origin requests.
Unlike classic scripts, module scripts require the use of the CORS protocol for cross-origin fetching.
Changing the <{script/src}>, <{script/type}>, <{script/charset}>, <{script/async}>, <{script/defer}>, <{script/crossorigin}>, and <{script/integrity}> attributes dynamically has no direct effect; these attributes are only used at specific times described below. The IDL attributessrc,
type,
defer, and
integrity, must each reflect the
respective content attributes of the same name.
The crossOrigin IDL attribute must
reflect the <{script/crossorigin}> content attribute, limited to only known values.
The async IDL attribute controls
whether the element will execute in parallel or not. If the element's "[=non-blocking=]"
flag is set, then, on getting, the {{HTMLScriptElement/async}} IDL attribute must return true,
and on setting, the "[=non-blocking=]" flag must first be unset, and then the content attribute
must be removed if the IDL attribute's new value is false, and must be set to the empty string
if the IDL attribute's new value is true. If the element's "[=non-blocking=]" flag is
not set, the IDL attribute must reflect the <{script/async}> content attribute.
text must return the
child text content of the <{script}> element. On setting, it must act the same way as the
{{Node/textContent}} IDL attribute.
When inserted using the {{Document/write()|document.write()}} method, <{script}> elements
execute (typically blocking further script execution or HTML parsing), but when inserted using
innerHTML and outerHTML attributes, they do not execute at all.
classic" or
"module". It is determined when the script is prepared, based on the
<{script/type}> attribute of the element at that time. Initially, <{script}> elements must have
this flag unset.
The sixth is a flag indicating whether or not the script is from an external file. It
is determined when the script is prepared, based on the <{script/src}> attribute of the
element at that time.
Finally, a <{script}> element has the script's script, which is a
<{script}> resulting from preparing the element. This is set asynchronously after the
classic script or module tree is fetched. Once it is set, either to a <{script}> in the
case of success or to null in the case of failure, the fetching algorithms will note that
the script is ready, which can trigger other actions. The user agent must
delay the load event of the element's node document until
the script is ready.
When a <{script}> element that is not marked as being "[=parser-inserted=]" experiences one of
the events listed in the following list, the user agent must immediately prepare
the <{script}> element:
* The <{script}> element gets inserted into a document, at the time the
node is inserted according to the DOM, after any other <{script}> elements inserted at the
same time that are earlier in the Document in tree order.
* The <{script}> element is in a Document and a node or document fragment is
inserted into the <{script}> element, after any <{script}> elements inserted at
that time.
* The <{script}> element is in a Document and has a src
attribute set where previously the element had no such attribute.
To prepare a script, the user agent must act
as follows:
1. If the <{script}> element is marked as having "[=already started=]", then the user agent
must abort these steps at this point. The script is not executed.
2. If the element has its "[=parser-inserted=]" flag set, then set
was-parser-inserted to true and unset the element's "[=parser-inserted=]" flag.
Otherwise, set was-parser-inserted to false.
This is done so that if parser-inserted <{script}> elements fail to run when the parser tries to run them, e.g., because they are empty or specify an unsupported scripting language, another script can later mutate them and cause them to run again.
3. If was-parser-inserted is true and the element does not have an <{script/async}> attribute, then set the element's "[=non-blocking=]" flag to true.This is done so that if a parser-inserted <{script}> element fails to run when the parser tries to run it, but it is later executed after a script dynamically updates it, it will execute in a non-blocking fashion even if the <{script/async}> attribute isn't set.
4. If the element has no <{script/src}> attribute, and its child nodes, if any, consist only of comment nodes and empty {{Text}} nodes, then abort these steps at this point. The script is not executed. 5. If the element is not in aDocument, then the user agent must abort these
steps at this point. The script is not executed.
6. If either:
* the <{script}> element has a <{script/type}> attribute and its value is the empty string, or
* the <{script}> element has no <{script/type}> attribute but it has a <{script/language}>
attribute and that attribute's value is the empty string, or
* the <{script}> element has neither a <{script/type}> attribute nor a <{script/language}>
attribute, then
...let the script block's type string for this <{script}> element be
"`text/javascript`".
Otherwise, if the <{script}> element has a <{script/type}> attribute, let
the script block's type string for this <{script}> element be the value of that
attribute after stripping leading and trailing white space.
Otherwise, the element has a non-empty <{script/language}> attribute; let
the script block's type string for this <{script}> element be the
concatenation of the string "text/" followed by the value of the
<{script/language}> attribute.
The <{script/language}> attribute is never conforming, and is always ignored if there is a <{script/type}> attribute present.
Determine the script's type as follows: * If the script block's type string is an ASCII case-insensitive match for any JavaScript MIME type, the script's type is "classic".
* If the script block's type string is an ASCII case-insensitive match for
the string "module", the script's type is "module".
* If neither of the above conditions are true, then abort these steps at this point.
No script is executed.
7. If was-parser-inserted is true, then flag the element as "[=parser-inserted=]"
again, and set the element's "[=non-blocking=]" flag to false.
8. The user agent must set the element's "[=already started=]" flag.
9. If the element is flagged as "[=parser-inserted=]", but the element's node document
is not the {{Document}} of the parser that created the element, then abort these steps.
10. If scripting is disabled for the <{script}> element, then abort these steps at this
point. The script is not executed.
The definition of scripting is disabled means that, amongst others,
the following scripts will not execute: scripts in {{XMLHttpRequest}}'s
{{XMLHttpRequest/responseXML}} documents, scripts in {{DOMParser}}-created documents,
scripts in documents created by XSLTProcessor's
transformToDocument feature, and scripts that are first inserted by a
script into a {{Document}} that was created using the
{{DOMImplementation/createDocument()}} API. [[!XHR]] [[!DOM-PARSING]] [[XSLTP]] [[!DOM]]
Blocked" when executed upon the <{script}> element,
"script", and the <{script}> element's child text content, then
abort these steps. The script is not executed. [[CSP3]]
12. If the <{script}> element has an <{script/event}> attribute and a <{script/for}> attribute,
and the script's type is "classic", then run these substeps:
1. Let for be the value of the <{script/for}> attribute.
2. Let event be the value of the <{script/event}> attribute.
3. Strip leading and trailing white space from event and for.
4. If for is not an ASCII case-insensitive match for the string
"window", then the user agent must abort these steps at this point.
The script is not executed.
5. If event is not an ASCII case-insensitive match for either the string
"onload" or the string "`onload()`", then the user agent must abort these
steps at this point. The script is not executed.
13. If the <{script}> element has a <{script/charset}> attribute, then let encoding be
the result of getting an encoding from the value of the <{script/charset}> attribute.
If the <{script}> element does not have a <{script/charset}> attribute, or if
getting an encoding failed, let encoding be the same as
the encoding of the document itself.
If the script's type is "module", this encoding will be ignored.
parser-inserted" if the <{script}> element
has been flagged as "[=parser-inserted=]", and "`not parser-inserted`" otherwise.
18. Let options be a set of script fetch options whose
cryptographic nonce metadata is cryptographic nonce, integrity metadata
is integrity metadata, parser metadata is parser metadata,
credentials mode is module script credentials mode, and referrer policy
is the empty string.
19. Let settings be the element's node document's {{Window}} object's
environment settings object.
20. If the element has a <{script/src}> content attribute, run these substeps:
1. Let src be the value of the element's <{script/src}> attribute.
2. If src is the empty string, queue a task to fire a simple event
named error at the element, and abort these steps.
3. Set the element's from an external file flag.
4. Parse src relative to the element's node document.
5. If the previous step failed, queue a task to fire a simple event named
error at the element, and abort these steps.
Otherwise, let url be the resulting URL record.
6. Switch on the script's type:
"module"script", and options.
"module"| the script's type | <{script/src}> present? | <{script/defer}> present? | <{script/async}> present? | other conditions |
|---|---|---|---|---|
| `"classic"` | yes | yes | no | element flagged as "[=parser-inserted=]" |
"module"
| yes or no | n/a | no | element flagged as "[=parser-inserted=]" |
| the script's type | <{script/src}> present? | <{script/defer}> present? | <{script/async}> present? | other conditions |
|---|---|---|---|---|
| `"classic"` | yes | no | no | element flagged as "[=parser-inserted=]" |
| the script's type | <{script/src}> present? | <{script/defer}> present? | <{script/async}> present? | other conditions |
|---|---|---|---|---|
| `"classic"` | yes | yes or no | no | "[=non-blocking=]" flag not set on element |
"module"
| yes or no | n/a | no | "[=non-blocking=]" flag not set on element |
| the script's type | <{script/src}> present? | <{script/defer}> present? | <{script/async}> present? | other conditions |
|---|---|---|---|---|
| `"classic"` | yes | yes or no | yes or no | n/a |
"module"
| yes or no | n/a | yes or no | n/a |
| the script's type | <{script/src}> present? | <{script/defer}> present? | <{script/async}> present? | other conditions |
|---|---|---|---|---|
"classic" or "module"
| no | yes or no | yes or no | All of the following: * element flagged as "[=parser-inserted=]" * an XML parser or an HTML parser whose script nesting level is not greater than one created the <{script}> * the {{Document}} of the XML parser or HTML parser that created the <{script}> has a style sheet that is blocking scripts |
If a <{script}> element that blocks a parser gets moved to another {{Document}} before it would normally have stopped blocking that parser, it nonetheless continues blocking that parser until the condition that causes it to be blocking the parser no longer applies (e.g., if the script is a pending parsing-blocking script because there was a style sheet that is blocking scripts when it was parsed, but then the script is moved to another {{Document}} before the style sheet loads, the script still blocks the parser until the style sheets are all loaded, at which time the script executes and the parser is unblocked).
When the user agent is required to execute a script block, it must run the following steps: 1. If the element is flagged as "[=parser-inserted=]", but the element's node document is not the {{Document}} of the parser that created the element, then abort these steps. 2. If the script's script is null, fire a simple event namederror
at the element, and abort these steps.
3. If the script is from an external file, or the script's type is
"module", then increment the ignore-destructive-writes counter of the
<{script}> element's node document. Let neutralized doc be that
{{Document}}.
4. Let old script element be the value to which the <{script}> element's
node document's {{Document/currentScript}} object was most recently set.
5. Switch on the script's type:
This does not use the in a document check, as the <{script}> element could have been removed from the document prior to execution, and in that scenario {{Document/currentScript}} still needs to point to it.
2. Run the classic script given by the script's script."module"classic" and the script is
from an external file, fire a simple event named load
at the <{script}> element.
Otherwise queue a task to fire a simple event named load at the
<{script}> element.
application/ecmascriptapplication/javascriptapplication/x-ecmascriptapplication/x-javascripttext/ecmascripttext/javascripttext/javascript1.0text/javascript1.1text/javascript1.2text/javascript1.3text/javascript1.4text/javascript1.5text/jscripttext/livescripttext/x-ecmascripttext/x-javascriptThese types are explicitly listed here because they are poorly-defined types that are nonetheless likely to be used as formats for data blocks, and it would be problematic if they were suddenly to be interpreted as script by a user agent.
When examining types to determine if they represent supported languages, user agents must not ignore MIME parameters. Types are to be compared including all parameters.
For example, types that include the charset parameter will not be
recognized as referencing any of the scripting languages listed above.
The easiest and safest way to avoid the rather strange restrictions described in this section is to always escape "`<!--`" as "`<\!--`", "`<script`" as "`<\script`", and "`</script`" as "`<\/script`" when these sequences appear in literals in scripts (e.g., in strings, regular expressions, or comments), and to avoid writing code that uses such constructs in expressions. Doing so avoids the pitfalls that the restrictions in this section are prone to triggering: namely, that, for historical reasons, parsing of <{script}> blocks in HTML is a strange and exotic practice that acts counter intuitively in the face of these sequences.
The {{Node/textContent}} of a <{script}> element must match thescript production in
the following ABNF, the character set for which is Unicode. [[!ABNF]]
script = outer *( comment-open inner comment-close outer )
outer = < any string that doesn't contain a substring that matches not-in-outer >
not-in-outer = comment-open
inner = < any string that doesn't contain a substring that matches not-in-inner >
not-in-inner = comment-close / script-open
comment-open = "<!--"
comment-close = "-->"
script-open = "<" s c r i p t tag-end
s = %x0053 ; U+0053 LATIN CAPITAL LETTER S
s =/ %x0073 ; U+0073 LATIN SMALL LETTER S
c = %x0043 ; U+0043 LATIN CAPITAL LETTER C
c =/ %x0063 ; U+0063 LATIN SMALL LETTER C
r = %x0052 ; U+0052 LATIN CAPITAL LETTER R
r =/ %x0072 ; U+0072 LATIN SMALL LETTER R
i = %x0049 ; U+0049 LATIN CAPITAL LETTER I
i =/ %x0069 ; U+0069 LATIN SMALL LETTER I
p = %x0050 ; U+0050 LATIN CAPITAL LETTER P
p =/ %x0070 ; U+0070 LATIN SMALL LETTER P
t = %x0054 ; U+0054 LATIN CAPITAL LETTER T
t =/ %x0074 ; U+0074 LATIN SMALL LETTER T
tag-end = %x0009 ; U+0009 CHARACTER TABULATION (tab)
tag-end =/ %x000A ; U+000A LINE FEED (LF)
tag-end =/ %x000C ; U+000C FORM FEED (FF)
tag-end =/ %x0020 ; U+0020 SPACE
tag-end =/ %x002F ; U+002F SOLIDUS (/)
tag-end =/ %x003E ; U+003E GREATER-THAN SIGN (>)
When a <{script}> element contains script documentation, there are further restrictions on
the contents of the element, as described in the section below.
<!--" and
"<script" strings in <{script}> elements in HTML need to be balanced in
order for the parser to consider closing the block.
By escaping the problematic strings as mentioned at the top of this section, the problem is
avoided entirely:
No details provided.
slot element, or a custom element doesn't
define replacement content for a slot, the fallback content of that slot in the
<{template}> will be used.
<user-card>
<h2 slot="user-name">Violet Ann</h2>
<div>
<p>Enjoys:</p>
<ul>
<li>Reading</li>
<li>Sketching</li>
<li>Cycling</li>
</ul>
</div>
<-- notice no defined user-email -->
</user-card>
After the browser runs the necessary JavaScript to define the custom element, the content
defined within the custom element user-card will be inserted into the appropriate
<{slot}> elements defined within the <{template}>.
With some CSS styling the example could be rendered like this:
nameassignedNodes()assignedNodes({ flatten: true})assignedElements()assignedElements({ flatten: true})assignedNodes({ flatten: true}).assignedNodes(), when invoked on an element
element, and given options options, must run the
following algorithm:
flatten member of options is false,
return the element's assigned nodes.assignedElements(), when invoked on an element
element, and given options options, must run the
following algorithm:
flatten member of options is false,
set result to the element's assigned nodes.