Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does my javascript only fire when the code is repeated?

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,

like image 689
Michael Wa Avatar asked Jul 03 '15 09:07

Michael Wa


3 Answers

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>
like image 179
Salman A Avatar answered Sep 18 '22 01:09

Salman A


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

like image 36
Sebastian Simon Avatar answered Sep 17 '22 01:09

Sebastian Simon


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.

like image 26
Alex Tartan Avatar answered Sep 18 '22 01:09

Alex Tartan