Why is CDATA needed and not working everywhere the same way?

Posted by baptx on Stack Overflow See other posts from Stack Overflow or by baptx
Published on 2012-06-22T17:56:40Z Indexed on 2012/06/24 15:16 UTC
Read the original article Hit count: 251

In Firefox's and Chrome's consoles, this works (alerts script content):

var script = document.createElement("script");
script.textContent = (
    function test() {
        var a = 1;
    }
);
document.getElementsByTagName("head")[0].appendChild(script);
alert(document.getElementsByTagName("head")[0].lastChild.textContent);

Using this code as a Greasemonkey script for Firefox works too.

Now, if want to add a "private method" do() to test() It is not working anymore, in neither Firefox/Chrome console nor in a Greasemonkey script:

var script = document.createElement("script");
script.textContent = (
    function test() {
        var a = 1;
        var do = function () {
            var b = 2;
        };
    }
);
document.getElementsByTagName("head")[0].appendChild(script);
alert(document.getElementsByTagName("head")[0].lastChild.textContent);

To make this work in a Greasemonkey script, I have to put all the code in a CDATA tag block:

var script = document.createElement("script");
script.textContent = (<![CDATA[
    function test() {
        var a = 1;
        var do = function() {
            var b = 2;
        };
    }
]]>);
document.getElementsByTagName("head")[0].appendChild(script);
alert(document.getElementsByTagName("head")[0].lastChild.textContent);

This is only works in a Greasemonkey script; it throws an error from the Firefox/Chrome console. I don't understand why I should use a CDATA tag, I have no XML rules to respect here because I'm not using XHTML.

To make it work in Firefox console (or Firebug), I need to do put CDATA into tags like <> and </>:

var script = document.createElement("script");
script.textContent = (<><![CDATA[
    function test() {
        var a = 1;
        var do = function() {
            var b = 2;
        };
    }
]]></>);
document.getElementsByTagName("head")[0].appendChild(script);
alert(document.getElementsByTagName("head")[0].lastChild.textContent);

This doesn't working from the Chrome console. I've tried adding .toString() at the end like many people are doing (]]></>).toString();), but it's useless.

I tried to replace <> and </> with a tag name <foo> </foo> but that didn't work either.

Why doesn't my first code snippet work if I define var do = function(){} inside another function?

Why should I use CDATA as a workaround even if I'm not using XHTML?

And why should I add <> </> for Firefox console if it's working without in a Greasemonkey script?

Finally, what is the solution for Chrome and other browsers?

EDIT:

My bad, I've never used do-while in JS and I've created this example in a simple text editor, so I didn't see "do" was a reserved keyword :p

But problem is still here, I've not initialized the Javascript class in my examples. With this new example, CDATA is needed for Greasemonkey, Firefox need CDATA between E4X <> </> and Chrome fails:

var script = document.createElement("script");
script.textContent = (
<><![CDATA[var aClass = new aClass();
function aClass() {
    var a = 1;
    var aPrivateMethod = function() {
        var b = 2;
        alert(b);
    };
    this.aPublicMethod = function() {
        var c = 3;
        alert(c);
    };
}
aClass.aPublicMethod();]]></>
);
document.getElementsByTagName("head")[0].appendChild(script);

Question: why?

© Stack Overflow or respective owner

Related posts about JavaScript

Related posts about Xml