{"id":30983,"date":"2006-06-05T10:00:00","date_gmt":"2006-06-05T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2006\/06\/05\/why-cant-you-say-script-in-a-script-block\/"},"modified":"2006-06-05T10:00:00","modified_gmt":"2006-06-05T10:00:00","slug":"why-cant-you-say-script-in-a-script-block","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20060605-00\/?p=30983","title":{"rendered":"Why can&#039;t you say &#060;\/script&#062; in a script block?"},"content":{"rendered":"<p>\nBecause it ends the script block, of course.\nDuh, what&#8217;s so hard about that?\n<\/p>\n<p>\nBecause if you have script that generates script, you&#8217;ll find\nyourself caught out if you&#8217;re not careful.  For example, you can&#8217;t say\n<\/p>\n<pre>\ndocument.write(\"&lt;SCRIPT&gt;blahblah&lt;\/SCRIPT&gt;\");\n<\/pre>\n<p>\nin a script block because the HTML parser will see the\n<code>&lt;\/SCRIPT&gt;<\/code>\nand conclude that your script block is over.\nIn other words, the script block extends as far as the\nhighlighted section below:\n<\/p>\n<pre>\n&lt;SCRIPT&gt;\n<font COLOR=\"blue\">document.write(\"&lt;SCRIPT&gt;blahblah<\/font>&lt;\/SCRIPT&gt;\");\n&lt;\/SCRIPT&gt;<font COLOR=\"red\">&lt;!-- mismatched tag --&gt;<\/font>\n<\/pre>\n<p>\nThe parser doesn&#8217;t understand &#8220;quoted strings&#8221; or &#8220;comments&#8221; or\nanything like that.\nIt just looks for the nine characters\n&#8220;&lt;&#8220;,\n&#8220;\/&#8221;,\n&#8220;S&#8221;,\n&#8220;C&#8221;,\n&#8220;R&#8221;,\n&#8220;I&#8221;,\n&#8220;P&#8221;,\n&#8220;T&#8221;, and\n&#8220;&gt;&#8221;.\nWhen it sees them, it decides that the script block is over and\nreturns to HTML parsing.\n<\/p>\n<p>\nWhy doesn&#8217;t the parser understand quoted string?\n<\/p>\n<p>\nWell, in order to parse quoted strings, you have to be able to\nparse comments:\n<\/p>\n<pre>\n&lt;SCRIPT&gt;\n\/* unmatched quotation mark \" ignored since it's in a comment *\/\n&lt;\/SCRIPT&gt;&lt;!-- you might expect this to end the script block --&gt;\n<\/pre>\n<p>\nBut every language has a different comment syntax.\nJScript uses <code>\/* ... *\/<\/code> and <code>\/\/<\/code>,\nVisual Basic uses <code>'<\/code>,\nperl uses <code>#<\/code>, and so on.\nAnd even if you got comments figured out, you also would\nneed to know how to parse quoted strings.\nPerl, for example, has a very large vocabulary for expressing\nquoted strings,\nfrom the simple <code>\"...\"<\/code> and <code>'...'<\/code>\nto the idiosyncratic <code>qq:...:<\/code>.\nAnd I lied about the JScript comment and quotation syntax;\nit&#8217;s actually more complicated than I suggested:\n<\/p>\n<pre>\n\/\"\/\/\"&lt;\/SCRIPT&gt;is this inside or outside quotes?\n<\/pre>\n<p>\nThat first quotation mark is itself quoted and does not count as\na &#8220;beginning of quoted string&#8221; marker.\nAnd the <code>\/\/<\/code> sequence is not a comment marker.\nThe first slash in the <code>\/\/<\/code> sequence ends the\nregular expression, and the second is a division operator.\n<\/p>\n<p>\nIt would be unreasonable to expect the HTML parser to be able to\nunderstand every language both present and future.\n(At least not until clairvoyance has been perfected.)\n<\/p>\n<pre>\n&lt;SCRIPT&gt;\n'is this a quoted string?'&lt;\/SCRIPT&gt;\nIs this inside or outside the script block?\n'&lt;SCRIPT&gt;' is this a new script block\nor the continuation of the previous one?\n&lt;\/SCRIPT&gt;\n<\/pre>\n<p>\nOne &#8220;solution&#8221; would be to require all languages to conform\nto one of a fixed number of quotation and comment syntaxes.\nNevermind that not even JScript conforms to the basic\nsyntax, as we saw above, thanks to the complicated\nquotation rules implied by regular expression shorthand.\nAnd do you really want all HTML parsers to understand perl?\n<\/p>\n<p>\nAnother &#8220;solution&#8221; would be to have the language processor\ndo the parsing and tell the HTML parser where the\n<code>&lt;\/SCRIPT&gt;<\/code> tag is.\nThis has its own problems, however.\nFirst, it means that the HTML parser would still have to\nload the language parser even for <code>DEFER<\/code>\nscript blocks, which sort of defeats one of the\npurposes of <code>DEFER<\/code>.\nEven worse, it means that a web page that used a language\nthat the system didn&#8217;t support would become unparseable:\n<\/p>\n<pre>\n&lt;SCRIPT LANG=\"unknown-language\"&gt;\n<a HREF=\"http:\/\/www.lipsum.com\/\">Lorem ipsum<\/a> dolor sit amet,\n...\n<\/pre>\n<p>\nIf a language parser were required to locate the end of the\nscript block, it would be impossible to parse past this point.\n<\/p>\n<p>\nSo how do you work around this aspect of HTML parsing?\nYou have to find an alternate way of expressing the\nstring you want.\nTypically, this is done by breaking in up into two strings\nthat you then reassemble:\n<\/p>\n<pre>\ndocument.write(\"&lt;SCRIPT&gt;blahblah&lt;\/SCRI\"+\"PT&gt;\");\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Because it ends the script block, of course. Duh, what&#8217;s so hard about that? Because if you have script that generates script, you&#8217;ll find yourself caught out if you&#8217;re not careful. For example, you can&#8217;t say document.write(&#8220;&lt;SCRIPT&gt;blahblah&lt;\/SCRIPT&gt;&#8221;); in a script block because the HTML parser will see the &lt;\/SCRIPT&gt; and conclude that your script block [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-30983","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Because it ends the script block, of course. Duh, what&#8217;s so hard about that? Because if you have script that generates script, you&#8217;ll find yourself caught out if you&#8217;re not careful. For example, you can&#8217;t say document.write(&#8220;&lt;SCRIPT&gt;blahblah&lt;\/SCRIPT&gt;&#8221;); in a script block because the HTML parser will see the &lt;\/SCRIPT&gt; and conclude that your script block [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/30983","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=30983"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/30983\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=30983"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=30983"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=30983"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}