-
Notifications
You must be signed in to change notification settings - Fork 165
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
Consider simplifying serializers #188
Comments
Syntax bikeshed proposal:
It would be really nice to not wonder "WTF is a serializer" whenever I see it :) |
Fwiw, what Gecko implements at the moment is this syntax:
Which leads to a toJSON implementation which does the following:
That is, you always do your own attributes, and your ancestor interfaces can opt in to do theirs too. This has been sufficient for all the use cases we've actually encountered, I believe. |
That sounds even better. |
At this point, is it still worth having dedicated syntax? Couldn't this just be a mixin we'd define in §4. Common definitions? |
A mixin? I'd think you would just define |
Right. I meant for the common case described by @bzbarsky above and for which the proposed syntax is simply |
See also #260. |
A few questions for @bzbarsky regarding the
|
Talking a bit with @tobie in IRC, I'm hopeful that we can come up with something as simple as "declare your own toJSON method, always". Then you can either go completely custom (using a custom dictionary type, for example, as the return value, or returning a certain string like URL wants to) or you can call some helper abstract op we define in Web IDL that gives you some kind of "serialize all attributes" behavior. The Another issue: the spec doesn't currently seem clear on whether the default serializer observably does a
This seems pretty bogus... |
Fyi a case where only specific attributes are serialized: http://w3c.github.io/webrtc-pc/#idl-def-rtcicecandidate A content script is expected to serialize ice candidates and send them over a signaling channel. Only some of the parameters are needed for this. At the same time, the object has grown other inspection attributes which presumably are useful locally, but need not be sent. |
Yeah, that would still be possible but require adding a interface RTCIceCandidate {
// members
RTCIceCandidateJSON toJSON();
};
dictionary RTCIceCandidateJSON {
DOMString candidate;
DOMString? sdpMid;
unsigned short? sdpMLineIndex;
DOMString ufrag;
}; |
@domenic, re:
Currently the spec converts serializable types to serialized values via the serialization behavior, then converts those to ES types via the ES binding. This—I think—explains the above language. I'm proposing to remove the serialization values altogether and instead simply require that the |
My concern is with the default serializer behavior. |
However JSON.stringify normally does. All the "jsonifier" thing does is expose a toJSON function that gets called from that algorithm. In practice, circular references throw.
Fwiw, I think I covered this in the description of the algorithm.... ;)
Well it would if you put a [Constructor] on
A more interesting example is this:
In this case, the value for "foo" would be the one from B, not from A.
That's a good question. I don't see any way to make these play nice together: toJSON can return primitives, but
We could imagine it, but it's a bit less useful to me as a UA implementor, because "overridden in prose" is not expressed in IDL, so I have no way to know whether my binding generator should generate and use the default algorithm or not, short of annotating the IDL with that information. At which point we've basically pushed the problem over to one of having
Why would it do any such thing? Why should the toJSON method on A know anything about attributes of descendant interfaces?
Probably not; it's not used in practice in Gecko. It happened to be simple to implement in Gecko: the binding generator for an interface with a jsonifier generates a method to stick the properties on an object, and descendant interfaces can call that method if they want. Your approach means that the binding generator for an interface has to check whether any descendants have a jsonifier and generate the method based on that more-global information. It's doable, but quite a bit more annoying to implement (e.g. in terms of getting build-system dependencies right, etc), which is why I didn't do it that way. Alternately, we could just forbid interfaces with a jsonifier from having a parent with no jsonifier or something. That adds more coupling between specs if spec X extends an interface from spec Y and wants X to be serializable, but maybe that's ok... Then again, given how W3C specs work maybe this is a terrible idea.
As I said above, that's probably fine in terms of spec factoring, but may complicate implementation, because that helper may be quite hard to implement generically in an automated way (and half the point here is to have this be automated, so people don't screw up things like adding a new attribute but not adding it to the serializer). Certainly I'd want a way to express the "use the helper" bit in IDL for Gecko's purposes, but I can just use an extended attribute for that.
I agree.
Indeed. Fwiw, in Gecko we call the default getter directly. |
Thanks for the thorough explanation, @bzbarsky. Now I have a better understanding of your proposal. Sounds like we want to treat Should we add |
http://searchfox.org/mozilla-central/search?q=jsonifier&path=dom%2Fwebidl |
So one thing I realized might be a problem with the default serializer + custom toJSON approach is that it introduces an inconsistency in whether there's a Get() performed. That is, given the following hypothetical future Web IDL: interface A {
attribute DOMString x;
attribute DOMString y;
toJSON = default; // or whatever, e.g. `jsonifier;` or `[DefaultSerializer] object toJSON();`
};
interface B {
attribute DOMString x;
attribute DOMString y;
BJSON toJSON();
};
dictionary BJSON {
DOMString x;
};
// In prose, define that `B`'s `toJSON()` returns a dictionary initialized
// with the value of `B`'s associated x. it appears that I think we should ensure consistency somehow, besides just requiring spec writers to do manual Get()s. For example:
We also want to handle the case of serializing to the value of a specific attribute, so that This is still simpler than the existing spec in the following respects:
|
Why? See the end of #188 (comment) |
I see; I misunderstood "default getter directly". So that's completely unobservable, right? I guess that is implementable, and thus probably specable. So we can ignore my mega-post entirely and go back to the simpler plan... |
Correct. |
* Remove all serializers. * Add support for JSON stringification through the toJSON operation. * Add the [Default] extended attribute. * Add a default JSON operation. Fixes whatwg#260. Fixes whatwg#188. Closes https://www.w3.org/Bugs/Public/show_bug.cgi?id=27428.
Here are all the interfaces I could find (thanks to searchfox) which are using serializers:
|
* Remove all serializers. * Add support for JSON stringification through the toJSON operation. * Add the [Default] extended attribute. * Add a default JSON operation. Fixes whatwg#260. Fixes whatwg#188. Closes https://www.w3.org/Bugs/Public/show_bug.cgi?id=27428.
I think they're vastly overengineered compared to what people actually want/need in practice. See https://www.w3.org/Bugs/Public/show_bug.cgi?id=20361#c4 and https://www.w3.org/Bugs/Public/show_bug.cgi?id=20361#c5 and the fact that there are multiple open issues on the current grammar being buggy, not least because it's too complicated.
The text was updated successfully, but these errors were encountered: