-
Notifications
You must be signed in to change notification settings - Fork 98
Incomplete Node.prototype.textContent shim causes errors #27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
After some debugging, I see where the issue manifests in jQuery. When This manifestation of the issue seems to have appeared after a bug fix introduced in jQuery 1.9 (issue, code). It seems to work fine when using jQuery 1.8.*... ...though don't get me wrong--this doesn't seem to be @jquery's bug. aight's |
I'm curious: does it occur when you include jquery before aight? For what it's worth, aight was never intended to work (or even tested) with jquery, specifically because d3 does most of what it does, and I personally haven't found much use for jquery when I'm using d3. There's an inherent conflict in jquery providing its own workarounds to missing features and aight shimming the browser's capabilities to play nice with d3 (which assumes ES5 and W3C DOM). If aight subverts jquery's feature detection, then I would say the two are fundamentally incompatible. |
Sorry, just re-read and saw that the load order is correct. Without understanding jquery's feature detection, it's hard to say. I'm curious to see what happens if you load aight after the window loads (and, presumably, jquery has done all that it needs to), though. |
@shawnbot Thanks for the quick response. I've tried loading aight after document load, and the issue persists. I'm fairly sure it's not specific to jQuery or its internal magic, but it's just one manifestation of the bug. I can reproduce it on any version of IE if I take out the check in element-properties. I'll try to post a simplified, jQuery-independent demo of the bug sometime tomorrow. |
Here's the test, which fails on a page with aight loaded regardless of whether or not jQuery is also loaded: var e = document.createElement('div');
e.innerHTML = " ";
var n = e.childNodes[0];
n.ownerDocument;
e.textContent = "";
n.ownerDocument; Without the |
It also looks like it's not related to HTML entities, as replacing the second line with I think this issue is caused by the supposition that Needs more investigation, but I think a solution would be either to remove the shim or to add some more logic to its existing get/set functions. |
I'm about to test this, but after another quick glance at your shim it looks like the issue is that you're adding the |
Okay, after some more investigation, it looks like there are two issues with the current shim:
A slightly nicer (though still incomplete) shim would look something like this: // ...
// see http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Node3-textContent
var nodeValue = Object.getOwnPropertyDescriptor(Text.prototype, "nodeValue");
Object.defineProperty(Text.prototype, "textContent", {
// It won't work if you just drop in nodeValue.get
// and nodeValue.set or the whole descriptor.
get: function() {
return nodeValue.get.call(this);
},
set: function(x) {
return nodeValue.set.call(this,x);
}
});
var innerText = Object.getOwnPropertyDescriptor(Element.prototype, "innerText");
Object.defineProperty(Element.prototype, "textContent", {
get: function() {
// It won't work if you just drop in innerText.get or the whole descriptor.
return innerText.get.call(this);
},
set: function(x) {
var c;
while(!!(c=this.firstChild)) { this.removeChild(c); }
if (x!==null) {
c=document.createTextNode(x);
this.appendChild(c);
}
c=null;
//return innerText.set.call(this,x); // nope! you do weird things!
return x;
}
});
// ... I've done some basic testing and it seems to work as expected for elements & text nodes. As it's already an improvement to what's currently in the plugin, I can either put this in a pull request now or fill out the cases to handle the remaining node types, exceptions, etc. @shawnbot, what do you think? |
Thanks for looking into this. Honestly, I just grabbed this shim from a gist somewhere, and I'm realizing that, now that aight is more popular, it definitely needs to be rewritten and that I probably need a formal test suite to catch these issues. That said, your code above looks like a good start, so go ahead and open a pull request (preferably on a branch) and note what else needs to be done, then I can merge it when it's ready. |
First draft, but closer to the spec: http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Node3-textContent - No longer uses Element.innerText as a setter, since there were undesirable side effects (recursive node modification, ew). - Works with Text nodes as well now. - Still needs to work with non-text, non-element nodes (e.g. cdata, comment, etc..), and to handle error cases as described in the spec. - (Would be nice to have tests, but maybe that's something for the plugin as a whole...)
Attached pull request to this issue. What's left to do:
References: |
Now works with non-text, non-element nodes (e.g. comment, document fragments, etc.) as well as weird IE elements that somehow have different behaviors (e.g. script, style, etc.). Fixes shawnbot#27.
@shawnbot, I think I'm done with all the changes -- feel free to check out the code, poke around, comment, or just merge if it looks good. |
It might be convenient to strategically add some newlines when recursively getting the After some more investigation, it looks like there's just no way around it without unnecessarily complicating things and/or adding significant performance penalties, so I wouldn't be too concerned about the line break issue. (For reference, jQuery's |
Whew, okay! Merged and tagged v1.2.5. Thanks for this! |
Firefox 45 below lack support for "innerText". Polyfill the property ("textContent") may not be viable for IE8 below. (no "defineProperty" etc.) Plus the unnecessary sophistry.
I've traced the issue to element-properties.js.
Here's the gist (sorry, neither jsbin nor jsFiddle support IE8 anymore):
https://gist.github.com/usmonster/9349332
Notice I load aight after jQuery. (Loading before causes other issues... see, e.g., #24, #29.)Note also that this could affect libraries or JS other than jQuery.