-2

OK this is purely out of curiosity: I was expecting the following markup to be valid inside an HTML document:

<script>
  var test = "<script>why?
</script>";
</script>

But no: this results in an "unterminated string constant" error, the first occurrence of </script> terminating the block, even though it's enclosed with quotes.

Can someone explain why this is happening (links to a specification appreciated :)?

Kas Elvirov
  • 7,394
  • 4
  • 40
  • 62
Gyum Fox
  • 3,287
  • 2
  • 41
  • 71

3 Answers3

4

The HTML parser doesn't know anything about JavaScript. It doesn't know that the first </script> is inside a string literal. All it sees is the first </script> and thinks this closes the block.

Here is a maybe more relateable example in JavaScript:

var foo = "He said: "Let's go!"";

The JavaScript parser doesn't know anything about the textual representation of human dialogs (e.g. that we usually put "speech" into quotation marks). All it sees is the second quotation mark and thinks that this terminates the string literal. But that is not what we intend so we have to help the parser by escaping the inner quotation marks.

Related: Why split the <script> tag when writing it with document.write()?

Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • 1
    How is the "related" not a duplicate? Or http://stackoverflow.com/q/23038617/215552? – Heretic Monkey Mar 16 '17 at 13:41
  • 1
    @MikeMcCaughan: I feel like the other question doesn't explain well why the script block is terminated at the first occurrence of ``. But if the answer to *this* question is simply *because it closes the script block*, then sure, it's a duplicate. – Felix Kling Mar 16 '17 at 13:45
4

You just need to escape the / character.

<script>
 var test = "<script>why?<\/script>";
</script>
Sulthan Allaudeen
  • 11,330
  • 12
  • 48
  • 63
maximedubois
  • 395
  • 1
  • 13
1

The HTML engine and the JavaScript engine are two different things. First, the HTML engine parses the document. It then passes along chunks of JavaScript code to the JavaScript engine. (And CSS code to the CSS engine, and so on.)

Since HTML doesn't know JavaScript syntax, it sees the closing tag as part of the overall content and merrily passes along the contents of the tags to the JavaScript engine:

<script>
    var test = "<script>why?
</script>

More specifically, if you follow the parsing rules starting here...

  1. The first <script> put us in "Script data state"
  2. We remained there until the first <, where we entered "Script data less-than sign state"
  3. We encountered an s, where we returned to "Script data state"
  4. Some characters later, we encounter another <, where we enter "Script data less-than sign state"
  5. We then encounter a /, where we enter "Script data end tag open state"
  6. etc.

You can keep following along in the spec, but essentially it describes the step-by-step details of how the HTML engine is parsing each character as HTML syntax, regardless of how we intuitively interpret those characters.

David
  • 208,112
  • 36
  • 198
  • 279
  • could you add the link to the W3C specification that James Thorpe posted in his comment to my question (this is simply to enhance the answer)? – Gyum Fox Mar 16 '17 at 14:19
  • @GyumFox: Good suggestion, I'm updated the answer. I'd never actually seen that part of the spec before, it was interesting to follow along. Thanks! – David Mar 16 '17 at 14:29