Closed
Bug 684601
Opened 13 years ago
Closed 12 years ago
window.toString.call() with native JS Object
Categories
(Core :: XPConnect, defect)
Core
XPConnect
Tracking
()
RESOLVED
FIXED
mozilla19
People
(Reporter: evilpie, Assigned: gkrizsanits)
References
Details
Attachments
(2 files, 3 obsolete files)
2.71 KB,
patch
|
Details | Diff | Splinter Review | |
5.71 KB,
patch
|
bzbarsky
:
review+
|
Details | Diff | Splinter Review |
We should try to figure out some way to make toString behave consistent with Object.prototoype.toString. I don't fully understand the necessary of them, because most of time they are not needed, and i think we already unwrap some of them. Testcase: window.toString.call(new Number()) should be '[object Number]', but is '[xpconnect wrapped native prototype]'. Which is very nasty, because it does not even follow the '[object ' + [[Class]] + ']' pattern.
Reporter | ||
Comment 1•13 years ago
|
||
This is a patch i wrote a while back, that just shadows this problem. I showed this to gal on irc, but he proposed some different solution, that i don't remember anymore :O
Comment 2•13 years ago
|
||
Well, a good first question is what should happen here per spec....
Comment 3•13 years ago
|
||
Per spec, window.toString.call(new Number()) should indeed return "[object Number]", since window.toString should be the one from Object.prototype; Window doesn't define its own. It looks like `window.toString != Object.prototype.toString` however.
Assignee | ||
Comment 4•13 years ago
|
||
(In reply to Cameron McCormack (:heycam) from comment #3) > Per spec, window.toString.call(new Number()) should indeed return "[object > Number]", since window.toString should be the one from Object.prototype; > Window doesn't define its own. > > It looks like `window.toString != Object.prototype.toString` however. So what happens here is that the window is actually a native wrapper with a reference to the native chrome window. It has a toString method (also native) XPC_WN_Shared_ToString (xpcwrappednativejsops.cpp) and works fine with other native wrappers, but for objects like that number it falls back to ToStringGuts (same file). This function is not really supposed to be called on a none wrapper object, like a Number instance for example, and simply returns "[xpconnect wrapped native prototype]". My guess is that this part could be changed to call Object.prototype.toString on it (maybe with some condition...), but don't really know what is this string originally stands for. I mean is there a case where it's the expected return value, or is it just a 'this should not really happen' branch?
Comment 5•13 years ago
|
||
The simplest way to invoke XPC_WN_Shared_ToString with a non-XPCWN object as |this| is to do window.__proto__.toString(). In which case, "[xpconnect wrapped native prototype]" is sort of a purposeful return value. Not sure what the DOM spec says nowadays about what window.__proto__.toString() should return.
Assignee | ||
Comment 6•13 years ago
|
||
(In reply to Boris Zbarsky (:bz) from comment #5) > In which case, "[xpconnect wrapped native prototype]" is sort of a > purposeful return value. Right, this makes sense, then the question is if it would be a good enough solution to fake the behavior of the Object.prototype.toString function here? Or we want a solution for the window.toString != Object.prototype.toString problem as well. In the first case we could check the 'this' object and either return this const string or simulate the Object.prototype.toString on the 'this' object (we would get the 'this' object as an optional 2nd arg). In the second case however it's a more complicated problem (at my knowledge level at least)...
Comment 7•13 years ago
|
||
Long-term, we probably just want to nuke the XPConnect toString hook on DOM classes. In my opinion. That will make toString on DOM prototypes kinda useless like it is on native JS objects, but it's what the spec seems to call for.... Now one issue with that approach is that the XPC toString actually does something interesting in debug builds. I suppose we could keep it in debug builds if we wanted.
Assignee | ||
Comment 8•13 years ago
|
||
(In reply to Boris Zbarsky (:bz) from comment #7) > Long-term, we probably just want to nuke the XPConnect toString hook on DOM > classes. In my opinion. I can ifdef it out in DefinePropertyIfFound. But I'm not sure I can identify if the object is from a DOM class easily. There are a set of interfaces the object implements so it is possible probably (slow and not nice at all), do we need this toString method for not DOM objects? Or can I just ifdef it out? > Now one issue with that approach is that the XPC toString actually does > something interesting in debug builds. I suppose we could keep it in debug > builds if we wanted. It would confuse me a bit at some bug debugging that I get totally different results for a toString... If not many ppl need it maybe it would be better to link this to a mozconfig flag, like some other debugging helper features. What do you think?
Comment 9•13 years ago
|
||
> do we need this toString method for not DOM objects? It's very useful when debugging, at least. So generally yes. > But I'm not sure I can identify if the object is from a DOM class easily We could add a flag to nsIXPCScriptable for this (or rather try to repurpose one of the existing flags, since we're out of flags).
Comment 10•13 years ago
|
||
> It's very useful when debugging, at least.
Debugging extensions, so can't be linked to build-time stuff.
Comment 11•13 years ago
|
||
(In reply to Boris Zbarsky (:bz) from comment #5) > Not sure what the DOM spec says nowadays about what > window.__proto__.toString() should return. "[object Object]", since window.__proto__ should be a plain object.
Assignee | ||
Comment 12•13 years ago
|
||
So I reused the WANT_CONVERT flag since that was not used by any class, so it's now IS_DOM_CLASS. And I added an extra about:config flag (dom.XPCToStringForDOMClasses) if someone wants to use the xpc version of toString for dom classes too (for debugging). Since we don't support prototypes per webidl as Boris pointed it out on irc, the window.__proto__.toString() returns now [object XPC_WN_ModsAllowed_NoCall_Proto_JSClass] Which is not the best. The proper fix for this issue would be to support proper prototypes per webidl, but I think for that we should open a new bug. And actually since the new binding will solve this problem, maybe it's a won't fix for now...
Attachment #562737 -
Flags: review?(bzbarsky)
Comment 13•13 years ago
|
||
Comment on attachment 562737 [details] [diff] [review] Fix proposal I'd really like peterv to look over the nsIXPCSCriptable changes... Another thing I just realized. nsIClassInfo already has a DOM_OBJECT flag. Is there a reason to not just use that here? Does involve getting the scriptable helper, etc, but for prototype setup maybe that;s ok?
Attachment #562737 -
Flags: review?(bzbarsky) → review?(peterv)
Comment 14•13 years ago
|
||
Comment on attachment 562737 [details] [diff] [review] Fix proposal >+PRBool NeedXPCToStringForDOMClasses() >+{ >+ PRBool result = PR_FALSE; >+ nsCOMPtr<nsIPrefBranch> prefs; >+ nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID)); >+ if (pserve) >+ pserve->GetBranch("", getter_AddRefs(prefs)); >+ if (prefs) >+ prefs->GetBoolPref("dom.XPCToStringForDOMClasses", &result); >+ return result; Could this use mozilla::Preferences? >+ bool overwriteToString = >+ (scriptableInfo && scriptableInfo->GetFlags().IsDOMClass()) >+ ? NeedXPCToStringForDOMClasses() >+ : true; This can be !scriptableInfo || !scriptableInfo->GetFlags().IsDOMClass() || NeedXPCToStringForDOMClasses(), no?
Assignee | ||
Comment 15•13 years ago
|
||
(In reply to Boris Zbarsky (:bz) from comment #13) > Another thing I just realized. nsIClassInfo already has a DOM_OBJECT flag. > Is there a reason to not just use that here? Does involve getting the > scriptable helper, etc, but for prototype setup maybe that;s ok? I have not realized that I can get a reference to an nsIClassInfo here... so tried this approach and it simplifies the patch a lot. It works, but the raw casting of xpc_GetJSPrivate worries me a bit... Is there any guarding condition I should use before that here? I have not modified anything in nsIXPCSCriptable in this version so I have not put peterv on the review list yet, but feel free to do so. (In reply to Ms2ger from comment #14) > Could this use mozilla::Preferences? Thanks for pointing it out! I was not aware of that api... > This can be !scriptableInfo || !scriptableInfo->GetFlags().IsDOMClass() || > NeedXPCToStringForDOMClasses(), no? It's a matter of taste I guess... I thought it's easier to understand the other version at first read, but since you are asking this question probably it's not the case. I used this style in the new version since it's shorter.
Attachment #562737 -
Attachment is obsolete: true
Attachment #562737 -
Flags: review?(peterv)
Attachment #563038 -
Flags: review?(bzbarsky)
Attachment #563038 -
Flags: review?(Ms2ger)
Comment 16•13 years ago
|
||
Comment on attachment 563038 [details] [diff] [review] Bug 684601 - window.toString.call() with native JS Object >+ XPCWrappedNativeProto* self = >+ (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj); >+ >+ bool overwriteToString = !self || !self->ClassIsDOMObject() >+ || mozilla::Preferences::GetBool("dom.XPCToStringForDOMClasses", PR_FALSE); 'using namespace mozilla;' and 'Preferences::GetBool("dom.XPCToStringForDOMClasses", PR_FALSE)', please. As for clearer... It's more that I find foo ? bar : true a pretty weird pattern. I think it came out slightly better, though.
Attachment #563038 -
Flags: review?(Ms2ger)
Comment 17•13 years ago
|
||
Comment on attachment 563038 [details] [diff] [review] Bug 684601 - window.toString.call() with native JS Object I don't think this is right. In particular, nothing really guarantees that |obj| is an XPConnect proto as far as I can tell. But the good news is that you don't need that. You have a XPCNativeScriptableInfo (possibly null). I believe for DOM objects the GetCallback from that actually QIs to nsIClassInfo. Again, please have Peter review changes to this stuff.
Attachment #563038 -
Flags: review?(bzbarsky) → review-
Assignee | ||
Comment 18•13 years ago
|
||
Thanks for both reviews, I hope this time it'll be better.
Attachment #563038 -
Attachment is obsolete: true
Attachment #564476 -
Flags: review?(peterv)
Attachment #564476 -
Flags: review?(bzbarsky)
Attachment #564476 -
Flags: review?(Ms2ger)
Comment 19•13 years ago
|
||
Comment on attachment 564476 [details] [diff] [review] 3rd attempt >--- a/js/src/xpconnect/src/xpcwrappednativejsops.cpp >+++ b/js/src/xpconnect/src/xpcwrappednativejsops.cpp >+ nsCOMPtr<nsIClassInfo> classInfo; >+ nsresult rv = NS_OK; >+ classInfo = do_QueryInterface(scriptableInfo->GetCallback()); >+ if (classInfo && NS_FAILED(rv = classInfo->GetFlags(&flags))) >+ return Throw(rv, ccx); I would write this as if (nsCOMPtr<nsIClassInfo> classInfo = do_QueryInterface(scriptableInfo->GetCallback())) { nsresult rv = classInfo->GetFlags(&flags) if (NS_FAILED(rv)) { return Throw(rv, ccx); } } (Unless your reviewer disagrees, and with 4-space indent.) >+ bool overwriteToString = !(flags & nsIClassInfo::DOM_OBJECT) >+ || Preferences::GetBool("dom.XPCToStringForDOMClasses", PR_FALSE); s/PR_FALSE/false/ here, and || should be at the end of the line.
Attachment #564476 -
Flags: review?(Ms2ger)
Assignee | ||
Comment 20•13 years ago
|
||
(In reply to Ms2ger from comment #19) Lesson learned: re-read our coding standards. But... > > if (nsCOMPtr<nsIClassInfo> classInfo = > do_QueryInterface(scriptableInfo->GetCallback())) { > nsresult rv = classInfo->GetFlags(&flags) > if (NS_FAILED(rv)) { > return Throw(rv, ccx); > } > } > Would you mind instead of if () { } using if() { } here, since the whole file is using this pattern I don't want to break that only here... In general, if a whole file using different patterns than the coding standard, which one leads? I personally don't like mixing different styles in one file, but I'll follow whatever standard we have in these cases.
Comment 21•13 years ago
|
||
Yes, do indeed follow local "style". (XPConnect, blech.)
Comment 22•13 years ago
|
||
Comment on attachment 564476 [details] [diff] [review] 3rd attempt r=me
Attachment #564476 -
Flags: review?(bzbarsky) → review+
Reporter | ||
Comment 23•13 years ago
|
||
push
Assignee | ||
Comment 24•13 years ago
|
||
(In reply to Tom Schuster (evilpie) from comment #23) > push This patch is not ready to be pulled yet. I still need a conformation from peterv that we are doing the right thing here and then I will file an updated, cleaned up patch that can be pushed.
Reporter | ||
Comment 25•13 years ago
|
||
*Ping* I think bholley should just look at this.
Comment 26•13 years ago
|
||
These files were moved, renamed, and re-styled several months ago. In particular, comment 20 is no longer valid. I'm happy to be the reviewer here if you don't need peterv's DOM expertise, though in that case bz's review is probably Sufficient. Feel free to flag me for review on a rebased patch.
Assignee | ||
Comment 27•13 years ago
|
||
(In reply to Bobby Holley (:bholley) from comment #26) > These files were moved, renamed, and re-styled several months ago. In > particular, comment 20 is no longer valid. > > I'm happy to be the reviewer here if you don't need peterv's DOM expertise, > though in that case bz's review is probably Sufficient. Feel free to flag me > for review on a rebased patch. I'm also happy to rebase the patch, or make any changes on it I have to, but since bc asked my clearly twice to ask peterv to take a look at it (whether or not this is the right thing we do here), I'm going to take his request seriously and wait for peterv's opinion.
Reporter | ||
Comment 28•12 years ago
|
||
This is still not working right. If necessary I can rebase this patch.
Comment 29•12 years ago
|
||
Comment on attachment 564476 [details] [diff] [review] 3rd attempt I don't think this needs a separate review from Peter. Just land it?
Assignee | ||
Comment 30•12 years ago
|
||
So I wanted to land this patch after an update, but it turned out on try that it has a side effect... The chrome window returns [object ChromeWindow] pre-patch but [object Window] post-patch. And some tests expects ChromeWindow ( http://mxr.mozilla.org/mozilla-central/source/docshell/test/navigation/NavigationUtils.js#111 ). So now I'm trying to figure out why is this happening, or how to fix it... Boris, what do you think?
Comment 31•12 years ago
|
||
Presumably the JSClass for that object should have ChromeWindow as its name?
Assignee | ||
Comment 32•12 years ago
|
||
(In reply to Boris Zbarsky (:bz) from comment #31) > Presumably the JSClass for that object should have ChromeWindow as its name? According to it's scriptableInfo yes. I'm not sure where is that "Window" coming from and got lost in the debugging so far...
Assignee | ||
Comment 33•12 years ago
|
||
Ok I got this. So it was the nsOuterWindowProxy::obj_toString that returned that [object Window] string... I think I can just change that to return [object ChromeWindow] if the proxy was created for a chrome window. Except if an outer window that was chrome once can somehow turn into a non-chrome window or the other way around... Since the proxy has no idea about the object it proxies to, if this state can change dynamically then I have no idea how to fix this. (pushed my patch to try again to see what happens...)
Assignee | ||
Comment 34•12 years ago
|
||
Could you take a second look at this patch since I had to modify it? The changes in the nsGlobalGlobalWindow.cpp is the new stuff. As in my previously comment described I have to create different proxy class for chrome outher windows to return different value from the obj_toString method than for the non-chrome ones. It's green on try.
Attachment #564476 -
Attachment is obsolete: true
Attachment #564476 -
Flags: review?(peterv)
Attachment #666920 -
Flags: review?(bzbarsky)
Updated•12 years ago
|
Attachment #666920 -
Attachment is patch: true
Comment 35•12 years ago
|
||
Comment on attachment 666920 [details] [diff] [review] no XPC_WN_Shared_ToString for DOM objects Review of attachment 666920 [details] [diff] [review]: ----------------------------------------------------------------- ::: dom/base/nsGlobalWindow.cpp @@ +625,5 @@ > > +class nsChromeOuterWindowProxy : public nsOuterWindowProxy > +{ > +public: > + nsChromeOuterWindowProxy() {} Add : nsOuterWindowProxy() I think @@ +627,5 @@ > +{ > +public: > + nsChromeOuterWindowProxy() {} > + > + JSString *obj_toString(JSContext *cx, JSObject *wrapper); Add 'virtual' here for clarity, please. @@ +635,5 @@ > + > +JSString * > +nsChromeOuterWindowProxy::obj_toString(JSContext *cx, JSObject *proxy) > +{ > + JS_ASSERT(js::IsProxy(proxy)); MOZ_ASSERT in dom/ ::: js/xpconnect/src/XPCWrappedNativeJSOps.cpp @@ +255,5 @@ > > if (!found) { > if (reflectToStringAndToSource) { > JSNative call; > + PRUint32 flags = 0; uint32_t @@ +262,5 @@ > + nsCOMPtr<nsIClassInfo> classInfo; > + nsresult rv = NS_OK; > + classInfo = do_QueryInterface(scriptableInfo->GetCallback()); > + if (classInfo && NS_FAILED(rv = classInfo->GetFlags(&flags))) > + return Throw(rv, ccx); if (scriptableInfo) { nsCOMPtr<nsIClassInfo> classInfo = do_QueryInterface(scriptableInfo->GetCallback()); if (classInfo) { nsresult rv = classInfo->GetFlags(&flags); if (NS_FAILED(rv)) return Throw(rv, ccx); } } @@ +266,5 @@ > + return Throw(rv, ccx); > + } > + > + bool overwriteToString = !(flags & nsIClassInfo::DOM_OBJECT) > + || Preferences::GetBool("dom.XPCToStringForDOMClasses", false); Trailing whitespace @@ +269,5 @@ > + bool overwriteToString = !(flags & nsIClassInfo::DOM_OBJECT) > + || Preferences::GetBool("dom.XPCToStringForDOMClasses", false); > + > + if(id == rt->GetStringID(XPCJSRuntime::IDX_TO_STRING) > + && overwriteToString) more
Assignee | ||
Comment 36•12 years ago
|
||
(In reply to :Ms2ger from comment #35) > Comment on attachment 666920 [details] [diff] [review] > Add > > : nsOuterWindowProxy() > > I think Is that necessary if it takes 0 args? > more I'll fix the rest locally.
Comment 37•12 years ago
|
||
Comment on attachment 666920 [details] [diff] [review] no XPC_WN_Shared_ToString for DOM objects With Ms2ger's comments addressed, r=me
Attachment #666920 -
Flags: review?(bzbarsky) → review+
Assignee | ||
Comment 38•12 years ago
|
||
http://hg.mozilla.org/integration/mozilla-inbound/rev/5a4513c759b9
Comment 39•12 years ago
|
||
(In reply to Gabor Krizsanits [:krizsa :gabor] from comment #36) > (In reply to :Ms2ger from comment #35) > > Comment on attachment 666920 [details] [diff] [review] > > Add > > > > : nsOuterWindowProxy() > > > > I think > > Is that necessary if it takes 0 args? Not really. Omitting an initializer for a base class or member field causes that thing to be default-initialized. Default initialization for an object which isn't POD (I can't imagine nsOuterWindowProxy is, but I haven't checked) is just calling the default constructor. I'd assume the rationale for visibly calling the base class constructor, then, is simply explicitness and clarity.
Comment 40•12 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/5a4513c759b9 Should this have a test?
Assignee: nobody → gkrizsanits
Status: NEW → RESOLVED
Closed: 12 years ago
Flags: in-testsuite?
Resolution: --- → FIXED
Target Milestone: --- → mozilla19
Reporter | ||
Comment 41•12 years ago
|
||
Yes, we should not forget about a testcase!
You need to log in
before you can comment on or make changes to this bug.
Description
•