4.11 Scripting — HTML5 (original) (raw)

W3C

A vocabulary and associated APIs for HTML and XHTML

W3C Candidate Recommendation 31 July 2014

← 4.10 FormsTable of contents4.12 Common idioms without dedicated elements →

    1. 4.11 Scripting
      1. 4.11.1 The script element
        1. 4.11.1.1 Scripting languages
        2. 4.11.1.2 Restrictions for contents of script elements
        3. 4.11.1.3 Inline documentation for external scripts
        4. 4.11.1.4 Interaction of script elements and XSLT
      2. 4.11.2 The noscript element
      3. 4.11.3 The template element
        1. 4.11.3.1 Interaction of template elements with XSLT and XPath
      4. 4.11.4 The canvas element
        1. 4.11.4.1 Color spaces and color correction
        2. 4.11.4.2 Serializing bitmaps to a file
        3. 4.11.4.3 Security with canvas elements

4.11 Scripting

Scripts allow authors to add interactivity to their documents.

Authors are encouraged to use declarative alternatives to scripting where possible, as declarative mechanisms are often more maintainable, and many users disable scripting.

Authors are also encouraged to make their applications degrade gracefully in the absence of scripting support.

4.11.1 The script element

Categories:

Metadata content.

Flow content.

Phrasing content.

Script-supporting element.

Contexts in which this element can be used:

Where metadata content is expected.

Where phrasing content is expected.

Where script-supporting elements are expected.

Content model:

If there is no [src](#attr-script-src) attribute, depends on the value of the [type](#attr-script-type) attribute, but must matchscript content restrictions.

If there is a [src](#attr-script-src) attribute, the element must be either empty or contain onlyscript documentation that also matches script content restrictions.

Content attributes:

Global attributes

[src](#attr-script-src)

[type](#attr-script-type)

[charset](#attr-script-charset)

[async](#attr-script-async)

[defer](#attr-script-defer)

[crossorigin](#attr-script-crossorigin)

DOM interface:

interface HTMLScriptElement : HTMLElement { attribute DOMString src; attribute DOMString type; attribute DOMString charset; attribute boolean async; attribute boolean defer; attribute DOMString crossOrigin; attribute DOMString text; };

The [script](#the-script-element) element allows authors to include dynamic script and data blocks in their documents. The element does not represent content for the user.

When used to include dynamic scripts, the scripts may either be embedded inline or may be imported from an external file using the [src](#attr-script-src) attribute. If the language is not that described by "text/javascript", then the [type](#attr-script-type) attribute must be present, as described below. Whatever language is used, the contents of the [script](#the-script-element) element must conform with the requirements of that language's specification.

When used to include data blocks (as opposed to scripts), the data must be embedded inline, the format of the data must be given using the [type](#attr-script-type) attribute, the [src](#attr-script-src) attribute must not be specified, and the contents of the [script](#the-script-element) element must conform to the requirements defined for the format used.

The type attribute gives the language of the script or format of the data. If the attribute is present, its value must be a valid MIME type. The charset parameter must not be specified. The default, which is used if the attribute is absent, is "text/javascript".

The src attribute, if specified, gives the address of the external script resource to use. The value of the attribute must be a valid non-empty URL potentially surrounded by spaces identifying a script resource of the type given by the [type](#attr-script-type) attribute, if the attribute is present, or of the type "text/javascript", if the attribute is absent. A resource is a script resource of a given type if that type identifies a scripting language and the resource conforms with the requirements of that language's specification.

The charset attribute gives the character encoding of the external script resource. The attribute must not be specified if the [src](#attr-script-src) attribute is not present. If the attribute is set, its value must be an ASCII case-insensitive match for one of the labels of an encoding, and must specify the same encoding as the charset parameter of the Content-Type metadata of the external file, if any. [ENCODING]

The async and defer attributes are boolean attributes that indicate how the script should be executed. The [defer](#attr-script-defer) and [async](#attr-script-async) attributes must not be specified if the [src](#attr-script-src) attribute is not present.

There are three possible modes that can be selected using these attributes. If the [async](#attr-script-async) attribute is present, then the script will be executed asynchronously, as soon as it is available. If the [async](#attr-script-async) attribute is not present but the [defer](#attr-script-defer) attribute is present, then the script is executed when the page has finished parsing. If neither attribute is present, then the script is fetched and executed immediately, before the user agent continues parsing the page.

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](#the-script-element) start and end tags in HTML, in foreign content, and in XML, the rules for the [document.write()](webappapis.html#dom-document-write) method, the handling of scripting, etc.

The [defer](#attr-script-defer) attribute may be specified even if the [async](#attr-script-async) attribute is specified, to cause legacy Web browsers that only support [defer](#attr-script-defer) (and not [async](#attr-script-async)) to fall back to the [defer](#attr-script-defer) behavior instead of the synchronous blocking behavior that is the default.

The crossorigin attribute is aCORS settings attribute. It controls, for scripts that are obtained from other origins, whether error information will be exposed.

Changing the [src](#attr-script-src), [type](#attr-script-type), [charset](#attr-script-charset), [async](#attr-script-async), [defer](#attr-script-defer), and [crossorigin](#attr-script-crossorigin) attributes dynamically has no direct effect; these attribute are only used at specific times described below.

A [script](#the-script-element) element has several associated pieces of state.

The first is a flag indicating whether or not the script block has been "already started". Initially, [script](#the-script-element) elements must have this flag unset (script blocks, when created, are not "already started"). The cloning steps for [script](#the-script-element) elements must set the "already started" flag on the copy if it is set on the element being cloned.

The second is a flag indicating whether the element was "parser-inserted". Initially, [script](#the-script-element) elements must have this flag unset. It is set by the HTML parser and the XML parser on [script](#the-script-element) elements they insert and affects the processing of those elements.

The third is a flag indicating whether the element will "force-async". Initially,[script](#the-script-element) elements must have this flag set. It is unset by the HTML parser and the XML parser on [script](#the-script-element) elements they insert. In addition, whenever a [script](#the-script-element) element whose "force-async" flag is set has a [async](#attr-script-async) content attribute added, the element's"force-async" flag must be unset.

The fourth is a flag indicating whether or not the script block is "ready to be parser-executed". Initially, [script](#the-script-element) elements must have this flag unset (script blocks, when created, are not "ready to be parser-executed"). This flag is used only for elements that are also "parser-inserted", to let the parser know when to execute the script.

The last few pieces of state are the script block's type, the script block's character encoding, and the script block's fallback character encoding. They are determined when the script is prepared, based on the attributes on the element at that time, and the [Document](dom.html#document) of the [script](#the-script-element) element.

When a [script](#the-script-element) element that is not marked as being "parser-inserted" experiences one of the events listed in the following list, the user agent must synchronouslyprepare the [script](#the-script-element) element:

To prepare a script, the user agent must act as follows:

  1. If the [script](#the-script-element) 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](#the-script-element) 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 [async](#attr-script-async) attribute, then set the element's"force-async" flag to true.
    This is done so that if a parser-inserted [script](#the-script-element) 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 asynchronously even if the [async](#attr-script-async) attribute isn't set.
  4. If the element has no [src](#attr-script-src) attribute, and its child nodes, if any, consist only of comment nodes and empty [Text](infrastructure.html#text-0) nodes, then the user agent must abort these steps at this point. The script is not executed.
  5. If the element is not in a Document, then the user agent must abort these steps at this point. The script is not executed.
  6. If either:
    • the [script](#the-script-element) element has a [type](#attr-script-type) attribute and its value is the empty string, or
    • the [script](#the-script-element) element has no [type](#attr-script-type) attribute but it has a [language](obsolete.html#attr-script-language) attribute and that attribute's value is the empty string, or
    • the [script](#the-script-element) element has neither a [type](#attr-script-type) attribute nor a [language](obsolete.html#attr-script-language) attribute, then
      ...let the script block's type for this [script](#the-script-element) element be "text/javascript".
      Otherwise, if the [script](#the-script-element) element has a [type](#attr-script-type) attribute, let the script block's type for this[script](#the-script-element) element be the value of that attribute with any leading or trailing sequences of space characters removed.
      Otherwise, the element has a non-empty [language](obsolete.html#attr-script-language) attribute; let the script block's type for this [script](#the-script-element) element be the concatenation of the string "text/" followed by the value of the [language](obsolete.html#attr-script-language) attribute.
      The [language](obsolete.html#attr-script-language) attribute is never conforming, and is always ignored if there is a [type](#attr-script-type) attribute present.
  7. If the user agent does not support the scripting language given by the script block's type for this [script](#the-script-element) element, then the user agent must abort these steps at this point. The script is not executed.
  8. If was-parser-inserted is true, then flag the element as"parser-inserted" again, and set the element's "force-async" flag to false.
  9. The user agent must set the element's "already started" flag.
    The state of the element at this moment is later used to determine the script source.
  10. If the element is flagged as "parser-inserted", but the element's[Document](dom.html#document) is not the [Document](dom.html#document) of the parser that created the element, then abort these steps.
  11. If scripting is disabled for the [script](#the-script-element) element, then the user agent must 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](infrastructure.html#xmlhttprequest)'s responseXML documents, scripts in DOMParser-created documents, scripts in documents created byXSLTProcessor's transformToDocument feature, and scripts that are first inserted by a script into a [Document](dom.html#document) that was created using the[createDocument()](infrastructure.html#dom-domimplementation-createdocument) API. [XHR] [DOMPARSING] [DOM]
  12. If the [script](#the-script-element) element has an [event](obsolete.html#attr-script-event) attribute and a [for](obsolete.html#attr-script-for) attribute, then run these substeps:
  13. Let for be the value of the [for](obsolete.html#attr-script-for) attribute.
  14. Let event be the value of the [event](obsolete.html#attr-script-event) attribute.
  15. Strip leading and trailing whitespace from event andfor.
  16. 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.
  17. 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.
  18. If the [script](#the-script-element) element has a [charset](#attr-script-charset) attribute, then let the script block's character encoding for this[script](#the-script-element) element be the result of getting an encoding from the value of the [charset](#attr-script-charset) attribute.
    Otherwise, let the script block's fallback character encoding for this[script](#the-script-element) element be the same as the encoding of the document itself.
    Only one of these two pieces of state is set.
  19. If the element has a [src](#attr-script-src) content attribute, run these substeps:
  20. Let src be the value of the element's [src](#attr-script-src) attribute.
  21. If src is the empty string, queue a task to fire a simple event named error at the element, and abort these steps.
  22. Resolve src relative to the element.
  23. If the previous step failed, queue a task to fire a simple event named error at the element, and abort these steps.
  24. Do a potentially CORS-enabled fetch of the resultingabsolute URL, with the mode being the current state of the element's [crossorigin](#attr-script-crossorigin) content attribute, the origin being the origin of the [script](#the-script-element) element's[Document](dom.html#document), and the default origin behaviour set to taint.
    The resource obtained in this fashion can be either CORS-same-origin orCORS-cross-origin. This only affects how error reporting happens.
    For performance reasons, user agents may start fetching the script (as defined above) as soon as the [src](#attr-script-src) attribute is set, instead, in the hope that the element will be inserted into the document (and that the [crossorigin](#attr-script-crossorigin) attribute won't change value in the meantime). Either way, once the element is inserted into the document, the load must have started as described in this step. If the UA performs such prefetching, but the element is never inserted in the document, or the [src](#attr-script-src) attribute is dynamically changed, or the [crossorigin](#attr-script-crossorigin) attribute is dynamically changed, then the user agent will not execute the script so obtained, and the fetching process will have been effectively wasted.
  25. Then, the first of the following options that describes the situation must be followed:
    If the element has a [src](#attr-script-src) attribute, and the element has a [defer](#attr-script-defer) attribute, and the element has been flagged as "parser-inserted", and the element does not have an [async](#attr-script-async) attribute
    The element must be added to the end of the list of scripts that will execute when the document has finished parsing associated with the [Document](dom.html#document) of the parser that created the element.
    The task that the networking task source places on the task queue once the fetching algorithm has completed must set the element's "ready to be parser-executed" flag. The parser will handle executing the script.
    If the element has a [src](#attr-script-src) attribute, and the element has been flagged as"parser-inserted", and the element does not have an [async](#attr-script-async) attribute
    The element is the pending parsing-blocking script of the[Document](dom.html#document) of the parser that created the element. (There can only be one such script per [Document](dom.html#document) at a time.)
    The task that the networking task source places on the task queue once the fetching algorithm has completed must set the element's "ready to be parser-executed" flag. The parser will handle executing the script.
    If the element does not have a [src](#attr-script-src) attribute, and the element has been flagged as"parser-inserted", and either the parser that created the [script](#the-script-element) is an XML parser or it's an HTML parser whose script nesting level is not greater than one, and the [Document](dom.html#document) of the HTML parser or XML parser that created the [script](#the-script-element) element has a style sheet that is blocking scripts
    The element is the pending parsing-blocking script of the[Document](dom.html#document) of the parser that created the element. (There can only be one such script per [Document](dom.html#document) at a time.)
    Set the element's "ready to be parser-executed" flag. The parser will handle executing the script.
    If the element has a [src](#attr-script-src) attribute, does not have an [async](#attr-script-async) attribute, and does not have the"force-async" flag set
    The element must be added to the end of the list of scripts that will execute in order as soon as possible associated with the [Document](dom.html#document) of the [script](#the-script-element) element at the time the prepare a script algorithm started.
    The task that the networking task source places on the task queue once the fetching algorithm has completed must run the following steps:
  26. If the element is not now the first element in the list of scripts that will execute in order as soon as possible to which it was added above, then mark the element as ready but abort these steps without executing the script yet.
  27. Execution: Execute the script block corresponding to the first script element in this list of scripts that will execute in order as soon as possible.
  28. Remove the first element from this list of scripts that will execute in order as soon as possible.
  29. If this list of scripts that will execute in order as soon as possible is still not empty and the first entry has already been marked as ready, then jump back to the step labeled execution.
    If the element has a [src](#attr-script-src) attribute
    The element must be added to the set of scripts that will execute as soon as possible of the [Document](dom.html#document) of the [script](#the-script-element) element at the time theprepare a script algorithm started.
    The task that the networking task source places on the task queue once the fetching algorithm has completed must execute the script block and then remove the element from theset of scripts that will execute as soon as possible.
    Otherwise
    The user agent must immediately execute the script block, even if other scripts are already executing.

Fetching an external script must delay the load event of the element's document until the task that is queued by the networking task source once the resource has been fetched (defined above) has been run.

The pending parsing-blocking script of a [Document](dom.html#document) is used by the[Document](dom.html#document)'s parser(s).

If a [script](#the-script-element) element that blocks a parser gets moved to another[Document](dom.html#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](dom.html#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[Document](dom.html#document) is not the [Document](dom.html#document) of the parser that created the element, then abort these steps.
  2. Jump to the appropriate set of steps from the list below:
    If the load resulted in an error (for example a DNS error, or an HTTP 404 error)
    Executing the script block must just consist of firing a simple event named error at the element.
    If the load was successful
    Executing the script block must consist of running the following steps. For the purposes of these steps, the script is considered to be from an external file if, while theprepare a script algorithm above was running for this script, the[script](#the-script-element) element had a [src](#attr-script-src) attribute specified.
    1. Initialize the script block's source as follows:
      If the script is from an external file and the script block's type is a text-based language
      The contents of that file, interpreted as a Unicode string, are the script source.
      To obtain the Unicode string, the user agent run the following steps:
      1. If the resource's Content Type metadata, if any, specifies a character encoding, and the user agent supports that encoding, then let character encoding be that encoding, and jump to the bottom step in this series of steps.
      2. If the algorithm above set the script block's character encoding, then let character encoding be that encoding, and jump to the bottom step in this series of steps.
      3. Let character encoding be the script block's fallback character encoding.
      4. If the specification for the script block's type gives specific rules for decoding files in that format to Unicode, follow them, using character encoding as the character encoding specified by higher-level protocols, if necessary.
        Otherwise, decode the file to Unicode, using character encoding as the fallback encoding.
        The decode algorithm overrides character encoding if the file contains a BOM.
        If the script is from an external file and the script block's type is an XML-based language
        The external file is the script source. When it is later executed, it must be interpreted in a manner consistent with the specification defining the language given bythe script block's type.
        If the script is inline and the script block's type is a text-based language
        The value of the [text](#dom-script-text) IDL attribute at the time the element's "already started" flag was last set is the script source.
        If the script is inline and the script block's type is an XML-based language
        The child nodes of the [script](#the-script-element) element at the time the element's"already started" flag was last set are the script source.
    2. Fire a simple event named beforescriptexecute that bubbles and is cancelable at the [script](#the-script-element) element.
      If the event is canceled, then abort these steps.
    3. If the script is from an external file, then increment theignore-destructive-writes counter of the [script](#the-script-element) element's[Document](dom.html#document). Let neutralized doc be that[Document](dom.html#document).
    4. Create a script, using the script block's source, theURL from which the script was obtained, the script block's type as the scripting language, and the script settings object of the [script](#the-script-element) element's[Document](dom.html#document)'s [Window](browsers.html#window) object.
      If the script came from a resource that was fetched in the steps above, and the resource was CORS-cross-origin, then pass the muted errors flag to the create a script algorithm as well.
      This is where the script is compiled and actually executed.
    5. Decrement the ignore-destructive-writes counter of neutralized doc, if it was incremented in the earlier step.
    6. Fire a simple event named afterscriptexecute that bubbles (but is not cancelable) at the [script](#the-script-element) element.
    7. If the script is from an external file, fire a simple event named load at the [script](#the-script-element) element.
      Otherwise, the script is internal; queue a task to fire a simple event named load at the [script](#the-script-element) element.

The IDL attributes src, type, charset, defer, each must reflect the respective content attributes of the same name.

The crossOrigin IDL attribute mustreflect the [crossorigin](#attr-script-crossorigin) content attribute, limited to only known values.

The async IDL attribute controls whether the element will execute asynchronously or not. If the element's "force-async" flag is set, then, on getting, the [async](#dom-script-async) IDL attribute must return true, and on setting, the "force-async" 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"force-async" flag is not set, the IDL attribute must reflect the [async](#attr-script-async) content attribute.

script . [text](#dom-script-text) [ = value ]

Returns the contents of the element, ignoring child nodes that aren't [Text](infrastructure.html#text-0) nodes.

Can be set, to replace the element's children with the given value.

The IDL attribute text must return a concatenation of the contents of all the [Text](infrastructure.html#text-0) nodes that are children of the[script](#the-script-element) element (ignoring any other nodes such as comments or elements), in tree order. On setting, it must act the same way as the [textContent](infrastructure.html#textcontent) IDL attribute.

When inserted using the [document.write()](webappapis.html#dom-document-write) method, [script](#the-script-element) elements execute (typically synchronously), but when inserted using[innerHTML](infrastructure.html#dom-innerhtml) and [outerHTML](infrastructure.html#dom-outerhtml) attributes, they do not execute at all.

In this example, two [script](#the-script-element) elements are used. One embeds an external script, and the other includes some data.

The data in this case might be used by the script to generate the map of a video game. The data doesn't have to be used that way, though; maybe the map data is actually embedded in other parts of the page's markup, and the data block here is just used by the site's search engine to help users who are looking for particular features in their game maps.

The following sample shows how a script element can be used to define a function that is then used by other parts of the document. It also shows how a [script](#the-script-element) element can be used to invoke script while the document is being parsed, in this case to initialize the form's output.

Work out the price of your car

Base cost: £52000.

Select additional options:

Total: £

4.11.1.1 Scripting languages

A user agent is said to support the scripting language if each component of the script block's type is an ASCII case-insensitive match for the corresponding component in the MIME type string of a scripting language that the user agent implements.

The following lists the MIME type strings that user agents must recognize, and the languages to which they refer:

"application/ecmascript"

"application/javascript"

"application/x-ecmascript"

"application/x-javascript"

"text/ecmascript"

"text/javascript"

"text/javascript1.0"

"text/javascript1.1"

"text/javascript1.2"

"text/javascript1.3"

"text/javascript1.4"

"text/javascript1.5"

"text/jscript"

"text/livescript"

"text/x-ecmascript"

"text/x-javascript"

JavaScript. [ECMA262]

User agents may support other MIME types for other languages, but must not support other MIME types for the languages in the list above. User agents are not required to support the languages listed above.

The following MIME types (with or without parameters) must not be interpreted as scripting languages:

These 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.

4.11.1.2 Restrictions for contents of script elements

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](#the-script-element) blocks in HTML is a strange and exotic practice that acts unintuitively in the face of these sequences.

The [textContent](infrastructure.html#textcontent) of a [script](#the-script-element) element must match the script 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 = "" 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 ; "tab" (U+0009) tag-end =/ %x000A ; "LF" (U+000A) tag-end =/ %x000C ; "FF" (U+000C) tag-end =/ %x0020 ; U+0020 SPACE tag-end =/ %x002F ; "/" (U+002F) tag-end =/ %x003E ; ">" (U+003E)

When a [script](#the-script-element) element contains script documentation, there are further restrictions on the contents of the element, as described in the section below.

The following script illustrates this issue. Suppose you have a script that contains a string, as in:

var example = 'Consider this string: <!--

The bigger problem, though, and the reason why it would violate those restrictions, is that actually the script would get parsed weirdly: the script block above is not terminated. That is, what looks like a "</script>" end tag in this snippet is actually still part of the [script](#the-script-element) block. The script doesn't execute (since it's not terminated); if it somehow were to execute, as it might if the markup looked as follows, it would fail because the script (highlighted here) is not valid JavaScript:

What is going on here is that for legacy reasons, "<!--" and "<script" strings in [script](#the-script-element) 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:

It is possible for these sequences to naturally occur in script expressions, as in the following examples:

if (x