Skip to main content

Bug Tracker

Side navigation

#11473 closed bug (wontfix)

Opened March 14, 2012 08:33PM UTC

Closed March 21, 2012 12:06AM UTC

Last modified March 23, 2012 05:51PM UTC

$.fn.html clears children in IE

Reported by: braddunbar Owned by:
Priority: undecided Milestone: None
Component: unfiled Version: git
Keywords: Cc: dmethvin
Blocked by: Blocking:
Description

When using innerHTML to set the contents of an element, descendant elements are also altered.

Observed using IE9 on Windows 7.

http://jsfiddle.net/Hej6h/6/

This is not a jQuery bug per se, but something that I think jQuery should handle if possible.

Attachments (0)
Change History (20)

Changed March 15, 2012 12:10AM UTC by rwaldron comment:1

cc: → dmethvin

My initial thoughts is that this isn't a bug. If you empty the contents of a node, there is nothing for an existing reference to point to.

Changed March 15, 2012 12:18AM UTC by scottgonzalez comment:2

_comment0: I wouldn't expect any specific behavior of the child elements other than not cleaning up any data stored by jQuery to avoid leaks. What specifically is this affecting that you think needs to be addressed?1331770708037345

I wouldn't expect any specific behavior of the child elements other than cleaning up any data stored by jQuery to avoid leaks. What specifically is this affecting that you think needs to be addressed?

Changed March 15, 2012 12:28AM UTC by rwaldron comment:3

resolution: → invalid
status: newclosed

The correct way to preserve anything you want to reuse is to store the actual innerHTML value in a variable - otherwise all nodes and their references will be cleared.

http://jsfiddle.net/rwaldron/DwusY/

Changed March 15, 2012 12:34AM UTC by braddunbar comment:4

_comment0: I agree, all nodes and their references will be cleared. However, their innerHTML should not be altered. For instance, if element `c` is a child of element `p`, calling `p.html('')` should leave the innerHTML of `c` unaltered. Is this not correct? \ \ var p = $('<p><a>x</a></p>'); \ var c = p.find('a'); \ p.html(''); \ console.log(c.html()); //should produce 'x'1331771699208828

I agree, all nodes and their references will be cleared. However, their innerHTML should not be altered. For instance, if element c is a child of element p, calling p.html('') should leave the innerHTML of c unaltered. Is this not correct?

var p = $('<p><a>x</a></p>');
var c = p.find('a');
p.html('');
console.log(c.html()); //should produce 'x'

Changed March 15, 2012 12:57AM UTC by braddunbar comment:5

For what it's worth, the above is not the current behavior in IE (http://jsfiddle.net/BG45f/). In any case, jQuery should behave consistently.

Changed March 15, 2012 01:16AM UTC by scottgonzalez comment:6

Brad makes a good point. The behavior of using innerHTML in IE seems incorrect.

Changed March 15, 2012 01:26AM UTC by braddunbar comment:7

Also, a proposed solution is here: https://github.com/jquery/jquery/pull/708

Changed March 15, 2012 01:45AM UTC by scottgonzalez comment:8

I just discussed this with Hixie and he agrees that this is a bug in IE. I'll report it to Microsoft and see what they say about it.

Changed March 15, 2012 02:39PM UTC by dmethvin comment:9

resolution: invalid
status: closedreopened

Changed March 15, 2012 02:43PM UTC by dmethvin comment:10

I saw the pull request and agree the behavior described by @braddunbar above should be what IE does as well. We can make it work that way, but it seems like the performance penalty will be pretty high to do it. That concerns me. Given how this hasn't been reported before, I have to think it's not a common use case.

Changed March 15, 2012 03:47PM UTC by rwaldron comment:11

Existing non-jQuery discussion, re: lost child nodes as a result of innerHTML being set:

http://stackoverflow.com/questions/595808/is-it-possible-to-append-to-innerhtml-without-destroying-descendants-onclick-fu

Latest innerHTML spec: (attention to Step #3)

http://www.w3.org/TR/html5/apis-in-html-documents.html#innerhtml

Previous innerHTML spec: (attention to Step #2)

http://www.w3.org/TR/2008/WD-html5-20080610/dom.html#innerhtml0

Changed March 16, 2012 03:46AM UTC by dmethvin comment:12

@rwaldron is cheating by quoting the specs that could be interpreted to allow the IE behavior. :)

I'll leave this open for further discussion, but am still leaning towards not trying to fix it. Someone who wants to depend on the behavior can use .empty().append(html) explicitly and get consistent cross-browser behavior. We could lobby for Microsoft to make the behavior consistent with the other browsers in IE10 though.

Changed March 17, 2012 10:21PM UTC by braddunbar comment:13

I understand that the performance penalty is steep and perhaps makes fixing this issue a non-starter. Given the obscurity of the problem it seems like a valid trade-off. If this is the case, I think the side effects of .html() should certainly be documented so that new users can make an informed decision about .empty().append(...) vs .html(...). Also, how can I help lobby to Microsoft for a consistent behavior in IE10?

Changed March 20, 2012 09:31PM UTC by rkatic comment:14

the performance penalty is steep

Not sure about that. Am I missing something?

Changed March 20, 2012 09:51PM UTC by rwaldron comment:15

Replying to [comment:14 rkatic]:

> the performance penalty is steep Not sure about that. Am I missing something?

The penatly of looping through and element's child nodes and removing them one at a time? There has to be a reflow in there...

Changed March 20, 2012 09:53PM UTC by braddunbar comment:16

Yes, essentially it changes the time complexity of that portion of the function from O(1) to O(# of child nodes). In some casual testing I did I saw a performance hit of 60% or more.

Changed March 21, 2012 12:06AM UTC by dmethvin comment:17

resolution: → wontfix
status: reopenedclosed

And it makes the performance worse for the browsers that have the worst performance already. IMO it would be better to wave people away from expecting the "correct" behavior in IE if they try to use .html(). And again it's easy to fix using .empty().append(...) so it's not as if the workaround is horrendous. I've updated the docs to note this issue.

We've contacted Microsoft about this issue and will try to get them to deal with it. Since it's a functional change it isn't likely to happen until IE10 at the earliest, unless you can prove a security problem is exposed by it. :)

Changed March 21, 2012 12:08AM UTC by braddunbar comment:18

Sounds good. Thanks @dmethvin!

Changed March 21, 2012 05:16PM UTC by rkatic comment:19

I would prefer correctness/consistency over performances, even in this case. Performance penalty is not that high, IMO. However, I can understand that fixing this could rise some revolt...

Changed March 23, 2012 05:51PM UTC by scottgonzalez comment:20

Microsoft's response is that they want to fix this, but it's a very large change to the underlying code and therefore won't make it in to IE 10. Removing the children, as in the PR, is their recommended workaround. However, they have the same opinion as Dave: this should not be addressed by jQuery because of the performance hit.