Bug Tracker

Opened 7 years ago

Closed 7 years ago

Last modified 7 years ago

#11456 closed bug (wontfix)

.html(htmlString) fails in IE when 1st char is space and a close div tag exists in the string

Reported by: phairow Owned by: phairow
Priority: low Milestone: None
Component: misc Version: 1.7.1
Keywords: Cc:
Blocked by: Blocking:

Description

when using .html(htmlString), the innerHTML of the specified element will be set to empty string when the htmlString passed starts with a space and contains a dangling end div tag.

EX: jQuery("#content").html(" Hello</div>");

Here is the jsFiddle: http://jsfiddle.net/Wj2cQ/

Tested in IE8 with all versions of jQuery that are available through jsFiddle. This does not repro in any other browser that I tested which include current versions of Chrome, Firefox, Opera, Safari on both pc and mac.

It fails any time the string starts with a space and contains a dangling </div> anywhere in the string.

Change History (8)

comment:1 Changed 7 years ago by dmethvin

Owner: set to phairow
Status: newpending

It doesn't look like it failed to me. It was fed invalid HTML which has undefined results. Although HTML5 has defined the parsing rules strictly, IE8 predates that.

Is there some way jQuery is supposed to fix this? We're not about to start RegExping strings to fix invalid HTML.

comment:2 in reply to:  1 Changed 7 years ago by phairow

Status: pendingnew

Replying to dmethvin:

It doesn't look like it failed to me. It was fed invalid HTML which has undefined results. Although HTML5 has defined the parsing rules strictly, IE8 predates that.

Is there some way jQuery is supposed to fix this? We're not about to start RegExping strings to fix invalid HTML.

The problem is that jQuery is attempting to provide a cross-browser abstraction which in this case behaves differently in different browsers. If I set the innerHTML directly on the dom element then this bug does not occur. It is specific to the way jQuery is adding the string to the dom that is not compatible with IE for this scenario. Here is an updated jsFiddle to illustrate the point: http://jsfiddle.net/Wj2cQ/1/

comment:3 Changed 7 years ago by addyosmani

Component: unfiledmisc
Priority: undecidedlow
Resolution: wontfix
Status: newclosed

My two cents on this are: garbage in, garbage out. As dmethvin has pointed out, it really doesn't make sense to start adding additional regex. (which would likely come with a performance cost) just to cover the case of someone inputting invalid HTML (and for just one browser). If a user absolutely needs to be covering the case of such input being used, you could simply write a plugin that does use innerHTML directly on the DOM element for their use case.

comment:4 in reply to:  3 ; Changed 7 years ago by phairow

Replying to addyosmani:

My two cents on this are: garbage in, garbage out. As dmethvin has pointed out, it really doesn't make sense to start adding additional regex. (which would likely come with a performance cost) just to cover the case of someone inputting invalid HTML (and for just one browser). If a user absolutely needs to be covering the case of such input being used, you could simply write a plugin that does use innerHTML directly on the DOM element for their use case.

I understand your reasoning and I do agree that it is garbage. I don't want to cause you to add a regex that is only for this obscure case. I am simply dismayed at the outcome of this since setting innerHTML works and using jQuery .html(htmlString) does not. I am building a content publishing system. The system combines templates which are created by template developers and designers with content created by content editors. Since I have seen their existing system and it contains malformed templates I must ensure the consistency of my system by putting any string however malformed that they give me into the output page. In addition to that some of the content is also html and could be malformed. Since I am simply providing a way for the different teams to render their content and if their templates and content render in their stand-alone browser tests then it must also work when the content and templates are uploaded into my system for rendering. I will continue to use the innerHTML directly and hopefully future versions of IE will not contain this bug. If you know why it is happening then perhaps we can file a bug with the IE team.

comment:5 in reply to:  4 Changed 7 years ago by phairow

I have looked into this further and I have found the cause. It is the result of another IE workaround that is causing this issue.

Around line 1347 is this setting:

// Make sure that link elements get serialized correctly by innerHTML
// This requires a wrapper element in IE
htmlSerialize: !!div.getElementsByTagName("link").length

Around line 5673 is this check which adds the workaround wrapper text:

// IE can't serialize <link> and <script> tags normally
if ( !jQuery.support.htmlSerialize ) {
    wrapMap._default = [ 1, "div<div>", "</div>" ];
}

Around line 6287 we take the workaround wrapper text:

wrap = wrapMap[ tag ] || wrapMap._default,

Next around line 6301 we wrap the html content and insert it into the dom:

// Go to html and back, then peel off extra wrappers
div.innerHTML = wrap[1] + elem + wrap[2];

Finally we remove the wrapper:

// Move to the right depth
while ( depth-- ) {
    div = div.lastChild;
}

While the existing .html(htmlString) workaround may fix a problem with how link and script tags are inserted into the dom in IE, it introduces the problem with rogue div tags in IE.

comment:6 Changed 7 years ago by cmcnulty

phairow, you're exactly correct about the workaround, and the problems it causes with invalid html. And actually, a "fix" that you could apply would be pretty simple. You could use the existing regex tests rnoInnerHtml and rnoshimcache as tests and only apply the wrapper fix if there's a match. *However* that's going to cause other potential issues. This bug exists in IE <=8 for *all* unknown html elements. So, while only applying the wrapper fix for rnoInnerHtml and rnoshimcache will fix the "NoScope" bug for the majority of cases, IE will still fail on using

$(foo).html("<bar></bar>");

Basically the choice is to have the wrapMap._default apply selectively and break IE for unknown elements that aren't in those lists, or apply wrapMap._default on all snippets and have it return unpredicted results when inserting borked html.

By the way, for a full understanding of what the code you highlighted is attempting to fix, I highly recommend this thread

comment:7 Changed 7 years ago by cmcnulty

Duplicate of #5353

comment:8 Changed 7 years ago by anonymous

Thanks cmcnulty, I really appreciate the follow up and I understand that it the goal of jQuery to behave consistently across browsers especially IE is very difficult to accomplish.

I checked out the link and it does a good job of explaining the need for the workaround with style tags. I also agree based on your explanation that the fix for my issue would cause other inconsistencies. I hope that eventually a fix can be found since it is a difficult issue to detect and in my case the solution was to not use jQuery html() for the rendering portion of the cms.

Do you think it would make sense to update the documentation to warn about malformed or invalid html?

Note: See TracTickets for help on using tickets.