Side navigation
#9897 closed bug (fixed)
Opened July 22, 2011 10:30PM UTC
Closed August 25, 2011 07:26PM UTC
Last modified March 10, 2012 03:37AM UTC
try-catch isPlainObject detection
Reported by: | bkrausz | Owned by: | rwaldron |
---|---|---|---|
Priority: | low | Milestone: | 1.6.3 |
Component: | core | Version: | 1.6.2 |
Keywords: | Cc: | ||
Blocked by: | Blocking: |
Description
A mildly convoluted case, but it caused me some hours of pain: http://nerdlife.net/jquery_bug_test.html
IE8 & 9 both throw exceptions on this, but they're silent for some reason unless you have IE9 script debugging on, in which case "SCRIPT65535:" is thrown. I understand the desire to not special-case every host object, but it seems worth throwing a try/catch around the checks there to return false (as jaubourg suggested in #7780) given that nothing but a non-plain object should be causing an exception here.
At the very least that would prevent a silent exception from being thrown.
Attachments (0)
Change History (15)
Changed July 25, 2011 04:24PM UTC by comment:1
component: | unfiled → core |
---|---|
owner: | → bkrausz |
priority: | undecided → low |
status: | new → pending |
Changed July 25, 2011 06:08PM UTC by comment:2
status: | pending → new |
---|
I did not use jsfiddle because this requires a popup window on the same domain, which it doesn't look like you can do with their tech (at least not easily without some hacks).
Tested on 27291f, confirmed still there.
Changed July 25, 2011 07:02PM UTC by comment:3
resolution: | → invalid |
---|---|
status: | new → closed |
This is not a jQuery issue. The exception being thrown was caused by you calling console.log(). As soon as I added firebug-lite, the errors dissappeared..
Tested with:
http://dl.dropbox.com/u/3531958/9897.html
Result:
Changed July 25, 2011 07:10PM UTC by comment:4
_comment0: | The exception is being thrown in the extend function for me...check http://nerdlife.net/jquery_bug_test.html again...even when you don't enable debugging on IE9, the alert I added after the extend function does not get called. \ \ This time at least is does throw an actual exceptions: \ {{{ \ Line: 525 \ Error: Unexpected call to method or property access. \ }}} → 1311621084796245 |
---|
The exception is being thrown in the extend function for me...check http://nerdlife.net/jquery_bug_test.html again...even when you don't enable debugging on IE9, the alert I added after the extend function does not get executed.
This time at least is does throw an actual exceptions:
Line: 525 Error: Unexpected call to method or property access.
Changed July 25, 2011 07:45PM UTC by comment:5
resolution: | invalid |
---|---|
status: | closed → reopened |
Ugh. Possibly the check for obj.constructor
OK, thanks
Changed July 25, 2011 07:45PM UTC by comment:6
owner: | bkrausz → rwaldron |
---|---|
status: | reopened → assigned |
Changed July 25, 2011 08:33PM UTC by comment:7
Replying to [comment:5 rwaldron]:
Ugh. Possibly the check for obj.constructor
OK, thanks
Bingo, it's a permission issue there. I don't think there's any way to pre-detect it, as this looks like an IE bug (or at least spec deviation). Would recommend a try/catch around that block:
diff --git a/src/core.js b/src/core.js index 715d73a..e061996 100644 --- a/src/core.js +++ b/src/core.js @@ -500,10 +500,16 @@ jQuery.extend({ return false; } - // Not own constructor property must be Object - if ( obj.constructor && - !hasOwn.call(obj, "constructor") && - !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // In some very specific cases (ex: IE accessing window.location of another window) + // constructor accesses throw an exception (see #9897) return false; }
Changed July 25, 2011 08:38PM UTC by comment:8
I was actually in the middle of replying with this:
This is actually a case covered here: #7743 & #7780
jQuery.isPlainObject() is simply not meant to be used with host objects such as window.location
. Host objects have no obligation to implement standard internal properties that native objects do, this makes it extraordinarily hard to test host objects
Changed July 25, 2011 08:51PM UTC by comment:9
Sorry for the collision, I had assumed this was queued up to be looked at later :).
I agree that this is a weird use case that should be avoided, but throwing an exception (or sometimes pseudo-silently failing) is a pretty bad failure case when doing this. Given that an object that throws an exception when trying to access the constructor is most certainly not plain, it seems worth the added lines to detect.
This adds another inconsistency to isPlainObject across different browsers, but if the goal is to detect situations where normal operations on objects should not be performed, then this seems better than an exception.
Changed July 25, 2011 09:01PM UTC by comment:10
No significant performance difference to be seen: http://jsperf.com/isplainobject-with-try-catch-junk
Changed July 25, 2011 09:10PM UTC by comment:11
Changed July 25, 2011 09:14PM UTC by comment:12
This seems like a pretty strange situation, and we've been working hard to eliminate try/catch since it often catches things we don't want to catch. (I do see that you've tried to think through what else might be caught, that's good.)
If the url needs to be passed back, why not use window.location.href
?
Changed July 25, 2011 10:05PM UTC by comment:13
Replying to [comment:12 dmethvin]:
This seems like a pretty strange situation, and we've been working hard to eliminate try/catch since it often catches things we don't want to catch. (I do see that you've tried to think through what else might be caught, that's good.) If the url needs to be passed back, why not use window.location.href
?
In this specific case, this was a bug in my code, and the solution was to just toString() the object (which I should have done in the first place).
More generally, we have a system to transfer data between windows so that they can persist between pages. Due to arbitrary garbage collection policies in IE we deep copy everything in the new window. Generic deep-copying like this where you're not 100% sure what's going to be sent into it is the reason I think we should handle the failure case...there's no obvious reason for isPlainObject to throw an exception, it would be like isArray throwing an exception.
Changed August 25, 2011 07:26PM UTC by comment:14
Changed August 26, 2011 02:21AM UTC by comment:15
milestone: | None → 1.6.3 |
---|
Thanks for taking the time to contribute to the jQuery project! Please provide a complete reduced test case on jsFiddle to help us assess your ticket!
Additionally, be sure to test against the jQuery Edge version to ensure the issue still exists. To get you started, use this boilerplate: http://jsfiddle.net/FrKyN/
Open the link and click to "Fork" (in the top menu) to get started.