1

I have the following javascript:

var iframe = document.createElement('iframe');
iframe.src='javascript:""';
document.body.appendChild(iframe);
var doc = iframe.contentDocument;
doc.open();
doc.write('<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />');
doc.write('<link type="text/css" rel="stylesheet" href="http://cdn.sstatic.net/stackoverflow/all.css?v=db16ef7a3fac" />');
doc.write('<script type="text/javascript">;</' + 'script>');
doc.write('<title>test</title></head><body><br>test</body></html>');
doc.close();
console.log(doc.body);
setTimeout(function() {
    console.log(doc.body);
}, 1000);

jsfiddle, open your console first

If I execute it in Firefox, it dumps <body> properly two times.

If I execute it in Chrome, it displays first null, then <body>. However, If I execute it then again, Chrome also displays <body> twice.

If you look at doc.childNodes when body is null, you see that chrome has somehow stopped processing the HTML string right after the </script>, therefore the body is not set.

The problem only occurs if the <link> tag is present. If I comment out this line, it works properly.

Can you reproduce the problem with chrome? Is there a way to force Chrome to synchronously process the HTML string?

Edit: I just fixed the fiddle, it had the css line commented out.

Yogu
  • 9,165
  • 5
  • 37
  • 58
  • have you tried to run this code on IE by decreasing its security and allowing the scripts.. – user2502227 Jun 25 '13 at 20:10
  • No, I did not check IE. Firefox works, but I have it to work in Chrome. Btw, the script is executed, but everything *after* the script tag is ignored. – Yogu Jun 25 '13 at 20:20
  • check every line by placing alert('')in between lines – user2502227 Jun 25 '13 at 20:29
  • Every line executes successfully, there are no Errors and the last line is obviously reached (otherwise nothing would be written to console.log) – Yogu Jun 25 '13 at 20:32
  • possible duplicate of [DOM parser that allows HTML5-style in – Paul Sweatte May 12 '14 at 17:46
  • @PaulSweatte I changed the code to `<' + '/script>'` and still the same. I now guess that chrome parses the HTML asynchronously, and `doc.write` returns before the HTML has been parsed. But it's no longer an issue for me. – Yogu May 12 '14 at 18:16
  • Thanks for the update. Glad it's no longer an issue. The Unicode escape of the backslash, ` – Paul Sweatte May 12 '14 at 18:36
  • There's a [great article](http://mathiasbynens.be/notes/etago) which covers this issue in detail for future reference. – Paul Sweatte May 12 '14 at 18:53

1 Answers1

0

The Unicode escape of the backslash should work:

doc.write('<script type="text/javascript"><\u002Fscript>')

Use try/catch to escape the semicolon:

try{;}catch(e){}

Use appendChild or other DOM methods as a better alternative.

References

Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265
  • As I wrote in the comments, that did not help. Note that I already split up the close tag in my code. The cause is something more subtle, probably a concurrency problem. – Yogu May 29 '14 at 17:28
  • I used the Unicode escape, not the string split. In the comments, referenced two links, one with several PHP specific answers, another with JavaScript DOM history. Here is an updated [fiddle](http://jsfiddle.net/u4gwA/4/) as well. – Paul Sweatte May 29 '14 at 19:38
  • In your fiddle, you removed the semicolon in the scipt tag. If I add id back, I get the problem back. If I remove the semicolon in my code, the problem goes away. The unicode escaping makes no difference; only the empty script tag does because it eliminates its semantics. – Yogu May 29 '14 at 20:08
  • You can also use `try{;}catch(e){}` as an alternative to eval the semicolon safely. – Paul Sweatte May 29 '14 at 20:30
  • It was code to initialize an iframe. I fixed it by appending the resources with DOM instead of `document.write`.` – Yogu May 29 '14 at 20:40