On 5/31/12 3:54 AM, Blake Kaplan wrote:
> This raises a second question: right now all of the JS implemented DOM APIs
> use XPConnect to reflect themselves into content. As we implement HTML5 and
> move towards WebIDL, what's the best path forward to make them behave
> properly? The path of least resistance would be to use XPConnect on the
> backend and write C++ shims that do the Right Thing with the new DOM bindings
> (and generally work around XPConnect in the process).
Yeah, this would actually be pretty painless (for some values of
painless: you still have to write the shim). For cases where
performance doesn't matter too much, this is a perfectly viable approach.
> The best solution might be to have some fancy way of hooking new DOM bindings up to JS (possibly with
> a library .jsm to get edge cases right).
Indeed.
>> 2) Implementing prototypes in JS that "inherit" from prototypes
>> implemented in C++ is possible, but needs some DOM work.
>>
>> 3) Implementing objects in C++ that "inherit" from prototypes
>> implemented in JS is not much harder than just doing pure-JS stuff,
>> apart from the details of the prototype hookup process.
>
> I don't think we've run into this yet and I'd like to ignore it as long as
> possible. For now, things like nodes will have to be implemented in C++ and
> IMO allowing new node implementations in JS is very low priority.
Item #2 above people have already run into, I thought. Think
EventTarget for the C++ proto and "anything that's implemented in JS and
is an EventTarget" for the JS thing.
The basic pattern for implementing such things would be to have a C++
object the JS can instantiate that would then have the JS-provided proto
as its proto. The JS-provided proto would chain up to the existing C++
protos (e.g. EventTarget). At that point the higher-up protos would
just operate on the underlying C++ object, and the JS proto can
implement things however it wants.
Note that this requires us to create some infrastructure for every C++
proto we want to thus subclass (e.g. this object that the JS would
instantiate).
>> 4) WebIDL has all sorts of things that depend on a distinction between
>> "platform objects" and other objects. We'll need a way to flag our
>> JS-implemented objects as "platform objects" from the point of view of
>> the C++ bindings and our C++-implemented objects as "platform objects"
>> from the point of view of the JS WebIDL bindings. I'm not quite sure
>> what the right way to do this is; right now we basically use the JSClass
>> on the C++ side to determine whether we have a platform object.
>
> Where does this distinction occur?
Typically during argument conversion. So for example, when converting
to a non-callback interface type you have to check that the object is
actually a platform object that implements that interface. That's not
too bad, if we implement things inheriting from c++ protos per my
proposal above and expose a way to do platform object detection to JS.
But there are some worse things. For example, when converting to a
sequence type, the only allowed inputs are platform array objects, JS
Arrays, and platform objects that support indexed properties. So we
need a way to detect in both the JS and C++ version of bindings, for an
arbitrary object, whether it's a "platform object that supports indexed
properties". Also, platform objects are not allowed to be converted to
dictionary types or callback interface types, or to callback function
types.
That _might_ be all the cases that care about the distinction.
> No matter what we do on the backend side, we're almost certainly going to end up with a "chrome" JS object and a DOM
> reflection of that object into content (for things like state and helper
> methods. gal might know more from his experience with dom.js). We can make that reflection have any JS class we want and forward
> appropriately.
Good, good.
>> 5) JS DOM implementations can't easily do the tricks with examining the
>> JS caller to decide whether to grant permission for something that C++
>> can do. We'd need to fix that.
>
> We've worked around this in the current implementations by installing our
> objects manually as the result of events that pass the window to the
> implementation and taking a snapshot of who we're being created for. Is that
> not sufficient?
I don't know. If an extension then touches your objects, will they
perceive that as being called "from chrome" or not? Maybe it doesn't
matter too much for them anyway, of course; this is only important for
cases where we want chrome to be able to do things with a DOM object
that the web page that object belongs to can't do.
>> It's hard to say. We have a lot of weird edge cases in our
>> JS-implemented APIs. For example, window.console.foopy() is a silent
>> no-op instead of throwing. Various other things have properties
>
> That's wild, is there a bug?
There is now.
https://bugzilla.mozilla.org/show_bug.cgi?id=760144
> Yeah. So, this is why this question needs to be asked and answered. There's
> work to be done and we have to decide that we're going to do it.
Agreed.
I, like Peter, would be interested in just sorting this out at the
bindings meeting on Monday.
-Boris