JSON encoding inconsistencies with host objects

52 views
Skip to first unread message

andris

unread,
Mar 3, 2011, 3:40:49 AM3/3/11
to Prototype: Core
Hi,

Native JSON encoding in WbKit based browsers is a bit different from
the others - if an object that is being encoded contains a host object
(DOM elements etc.), then the encoding fails and a TypeError is cast.

When other browsers simply skip host objects (treated as being empty
"{}"), then WebKit is actually trying to serialize these and ends up
with recursions (element.ownerDocument.body.ownerDocument etc.).

For example JSON.stringify({elm: document.createElement("div"}) ends
up with an error in WebKit but not in other browsers. See my testpage
here http://node.ee/json.html

I filed a bug to V8 (http://code.google.com/p/v8/issues/detail?
id=1223) but it was rejected as WorkingAsIntended and I don't blame
them, there really isn't any specs defining correct behavior for this.

The question is, should Prototype address it or is it a developers
problem? Isn't the work of a JS library to smooth out these kind of
inconsistencies - for example either falling back to a non native
encoder with WebKit or forcing other browser to follow the same rules?

Best regards,
Andris Reinman

Bob Kerns

unread,
Mar 5, 2011, 1:31:22 AM3/5/11
to prototy...@googlegroups.com, andris
It will feel SO much better when you stop!

I can't see supporting serializing host objects, ever.

But I could support doing something to make it ALWAYS error. It IS the developer's problem, but sometimes it helps to have one's mistakes pointed out to you promptly, before you go public...


--
You received this message because you are subscribed to the Google Groups "Prototype: Core" group.
To post to this group, send email to prototy...@googlegroups.com
To unsubscribe from this group, send email to prototype-cor...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en

Andrew Dupont

unread,
Mar 5, 2011, 3:48:38 AM3/5/11
to prototy...@googlegroups.com

On Mar 3, 2011, at 2:40 AM, andris wrote:
> The question is, should Prototype address it or is it a developers
> problem? Isn't the work of a JS library to smooth out these kind of
> inconsistencies - for example either falling back to a non native
> encoder with WebKit or forcing other browser to follow the same rules?

Falling back to a non-native encoder isn't an option; it would result in a _massive_ performance drop, an issue far more severe than the one you're describing.

Forcing other browsers to follow the same rules isn't an option; not only would it require us to do non-native JSON encoding for certain code paths, it would also require us to comb an object for any references to host objects to know whether or not we'd need to bypass the native encoder.

So it's got to be the developer's problem because there's nothing Prototype can do, even if we wanted to.

Cheers,
Andrew

andris

unread,
Mar 5, 2011, 4:58:18 AM3/5/11
to Prototype: Core
Thanks for the answer, I understand the performance drop is a far more
important issue, I just hoped there would be an easy solution.

But just to be clear - I didn't want Prototype to force *other*
browsers to behave as WebKit but to force WebKit to behave as others.
So when I do Object.toJSON({elm:HTMLDIVElement}) it wouldn't end on
error but with {elm:{}} instead.

Best regards,
Andris Reinman

Mislav Marohnić

unread,
Mar 5, 2011, 8:03:39 AM3/5/11
to prototy...@googlegroups.com, andris
On Sat, Mar 5, 2011 at 10:58, andris <andris....@gmail.com> wrote:

But just to be clear - I didn't want Prototype to force *other*
browsers to behave as WebKit but to force WebKit to behave as others.
So when I do Object.toJSON({elm:HTMLDIVElement}) it wouldn't end on
error but with {elm:{}} instead.

I agree with Andrew that Prototype shouldn't do anything in this regard. You've got a good point that it's the job of a JS library to smooth out such inconsistencies, but any meddling in this case would result in slowdowns.

There could exist a Prototype plugin which performs a simple traversal of the array/hash before sending it to JSON encoder, and if it finds properties that reference DOM elements it could blank those out. Someone whose JS app suffers from these DOM references creeping in their JSON data might want to use such plugin.

Bob Kerns

unread,
Mar 5, 2011, 9:48:59 PM3/5/11
to prototy...@googlegroups.com
I'd like to reiterate -- this is going about it backwards.

You do NOT want errors to go undetected.

You do NOT want data that you may have expected to be captured to be SILENTLY discarded.

You do not want YOUR BUG to be papered over!  You want your  bugs to be IN YOUR FACE IN ALL CAPS SHOUTING AT YOU! :=)  Or at least, hard-to-miss.

I agree, we don't want to replace the native implementation. But to take your idea, and rework it -- Prototype could supply a a validateJSON() routine, that checks for, and objects to, invalid output -- and perhaps puts a configurable limit on depth of recursion, or total size. The input would be returned, unmodified, if it is acceptable, otherwise an exception would be thrown.

Depending on need, this could be injected during debug/test only, or during production. (Performance isn't ALWAYS a problem).

It might also POSSIBLY be useful to have a filterObject() function that traverses some hierarchy, and applies a predicate, which if true, results in that key/value pair being included in the result. It would make a copy iff the result were not identical to the input, and would return the result.

This would have other application -- for example, rejecting attempts to insert additional data, or filtering out private information, or taking a recursive structure and returning a hierarchical version for transmission.

This is different from just papering over the bug. It is making an explicit decision about the datastructure you transmit, rather than relying on the behavior of the underlying system to not fail given broken inputs.

I would still question your architecture, if you are using it in this way -- I think it suggests that there may be poor modularization at work. I'd take a good look at whether the information to be transmitted would be better separated from the information that contains live data, perhaps with a level of indirection (a side lookup table). I suspect you'd find such an approach to be more flexible and better in the long run anyway. But that's a suspicion, not a conclusion; I'll leave it to you to ponder whether it fits your situation.

The other question is whether either of these ideas has enough wide-spread value to be worth implementing -- and then to be loaded into millions upon millions of browser sessions.  Personally, I think I'd just write them myself if I need them -- they're not difficult -- but it might be worth it they encourage people to write better code or test it better. But my default position here is, "we don't need it in Prototype", but if you write it, they'd be worth sharing some other way.

Perhaps a parallel package of debugging tools you load, and enable, to add additional error checking.

--
Reply all
Reply to author
Forward
0 new messages