10

I'm having an issue where I can only get my code to fire if I repeat it. See the below example. While the code is nearly identical if I take either of the two scripts out the code doesn't function with just one, yet if I run both the script fires fine, but only one instead of two. give it a go.

This works (but only one script fires):

<script type="text/javascript">
var url = window.location.href + "";
document.write('<script type="application/javascript" src="https://testdomain.com/mik21?add=2140535&mik21=' + url + '"/>');
</script>

<script type="text/javascript">
var url = window.location.href + "";
document.write('<script type="application/javascript" src="https://testdomain.com/mik?add=2140535&mik=' + url + '"/>');
</script>

This does not work:

<script type="text/javascript">
var url = window.location.href + "";
document.write('<script type="application/javascript" src="https://testdomain.com/mik21?add=2140535&mik21=' + url + '"/>');
</script>

Or this:

<script type="text/javascript">
var url = window.location.href + "";
document.write('<script type="application/javascript" src="https://testdomain.com/mik?add=2140535&mik=' + url + '"/>');
</script>

Does anyone have any ideas? this is definitely the weirdest thing I've seen in a while.

Thanks,

Salman A
  • 229,425
  • 77
  • 398
  • 489
Michael Wa
  • 111
  • 4

3 Answers3

11

The problem is that your script tag is broken. A <script> tag must be closed by </script>.
Now here is what happens:

Example 1

<script>
  document.write('<script src="test.js"/>');
</script>

Produces the following markup HTML:

<script>
  document.write('<script src="test.js"/>');
</script>
<script src="test.js">
  </body>
  </html>

In general, browsers do not execute a <script> block until they find the corresponding </script>. There is no explicit closing tag in the above example so the browser ignores the tag.

Example 2

<script>
  document.write('<script src="test.js"/>');
</script>
This HTML will be consumed
<script>
  document.write('<script src="test.js"/>');
</script>

Produces the following output:

<script>
  document.write('<script src="test.js"/>');
</script>
<script src="test.js">
  This HTML will be consumed
  <script>
  document.write('<script src="test.js"/>');
</script>

Notice that the dynamically written script tag is not closed. The browser will match this tag with the second </script> in the markup; everything in-between (incorrectly) becomes part of this tag.

Solution

When using document.write, make sure that you close <script> tags properly. But note that you cannot use </script> as-is inside JavaScript code since it signals end of script block. You can use the following trick:

<script>
  document.write('<script src="test.js"><\/script>');
</script>
Salman A
  • 229,425
  • 77
  • 398
  • 489
  • 2
    Note: If someone is wondering why the browser does not raise syntax errors, the answer is: the browser will ignore script tag's content when the `src` attribute is present. – Salman A Jul 03 '15 at 11:44
6

I have just tested this:

Consider the source

data:application/javascript;base64,Y29uc29sZS5sb2coIlRlc3QiKTs=

This points to the following code:

console.log("Test");

This snippet below generates

<script src="data:application/javascript;base64,Y29uc29sZS5sb2coIlRlc3QiKTs="/>

<div>A</div>
<script>
document.write('<script src="data:application/javascript;base64,Y29uc29sZS5sb2coIlRlc3QiKTs="/>');
</script>
<div>B</div>

However, this snippet below generates

<script src="data:application/javascript;base64,Y29uc29sZS5sb2coIlRlc3QiKTs="></script>

<div>A</div>
<script>
document.write('<script src="data:application/javascript;base64,Y29uc29sZS5sb2coIlRlc3QiKTs="></'+'script>');
</script>
<div>B</div>

The first snippet logs "Test" but doesn’t display “B” in the HTML. The second works properly. In the Real-time HTML Editor not even "Test" gets logged for the first one. The implication of that is that all the HTML below the <script/> (which is inserted as <script>) gets consumed as Salman A’s answer points out.

This is because the only valid syntax for <script> tags is <script></script> and not <script/>.

Community
  • 1
  • 1
Sebastian Simon
  • 14,320
  • 6
  • 42
  • 61
3

This works:

<script type="text/javascript">
var url = window.location.href + "";
document.write('<script type="application/javascript" src="https://testdomain.com/mik21?add=2140535&mik21=' + url + '"></scr'+'ipt>');
document.close();
</script>

To prevent js from crashing, i've split the <script> tag into two strings.

Alex Tartan
  • 6,465
  • 10
  • 33
  • 41