On 4/22/14, 12:24 AM, Joshua Cranmer 🐧 wrote:
I managed to, in one of my playground techniques, create a global using
a backstage pass and some xpconnect APIs, so it's not impossible but it
is damn annoying.
Right. If you don't have a global to start with, your life will
_really_ suck if you want to use promises as they're being specced and
implemented. :(
That's because promises are a JS-centric feature and JS _always_ has a
global to work with, ipso facto....
I consider Promise more like a generic platform feature (considering
that the specification is moving to ES6 instead of DOM)
ES assumes you always have a global. In fact, until ES6 it assumed that
there was only one global around, so of course you could always get
access to this singleton global. ES6 is introducing Realms (read
globals), but still assumes that any time any code is running that code
is associated with a realm and knows what realm that is....
(except maybe insofar as things like
realms/compartments/etc. are concerned)
That's a pretty huge exception.
I think there are proposals to
add it to XPCOM JS component/module scopes, which to me is the
definition of "should be usable outside of web platform APIs."
"web platform APIs" would include ES6 Realms.
Component/module scopes have an nsIGlobalObject... and a Promise
constructor, for that matter.
But that's only true if it's an actual Promise.
OK. Why is the thing you have not an actual Promise? Where did this
thing come from?
For more specific explanation then:
I have a (non-negotiably) JS-implemented XPCOM service called the Folder
Lookup Service. I want to add an API to it called getOrCreateFolder that
returns a Promise<nsIMsgFolder>. I have non-negotiable C++ code that
wants to call this method, and do something when the promise is resolved
or rejected.
Thank you for explaining what you're trying to do.
The JS implemented XPCOM service can call |new Promise| (or any of the
Promis static methods) to create an actual DOM Promise object, since we
install that constructor on all XPConnect globals.
You can have getOrCreateFolder return "jsval" in the xpidl, then
manually unwrap to a dom::Promise in the C++ like so:
if (!value.isObject()) {
// Throw
}
Promise* promise;
nsresult rv = UNWRAP_OBJECT(Promise, &value.toObject(), promise);
if (NS_FAILED(rv)) {
// Throw
}
Then you can call promise->AppendNativeHandler() with a handler you
implement. At least assuming your code is in libxul. If not, we may
need to add some symbol exported from libxul or a virtual function on
Promise that lets you make this call.
That leaves the problem of extracting the nsIMsgFolder from the value
you'll get resolved with, of course... nsIXPConnect has some methods
for doing that sort of thing, like getNativeOfWrapper(), but they're a
bit of an annoyance, I agree. I'd try harder to solve this problem if
any solution were not going to be jettisoned when Promise moves into
SpiderMonkey. :(
I think I would consider adding helpers to xpconnect before doing raw
JSAPI
Sold! ;)
I couldn't figure out how to pass undefined to a JS::Handle<JS::Value>.
JS::UndefinedHandleValue should do it. But yes, the docs are behind the
times.
I don't think WebIDL is applicable in this circumstance if the JS
promises are coming from Promises.jsm...
Ah, if the JS code is not getting to create the promise, that
complicates things a bit.
On the other hand, the JS code can always take the Promise.jsm thing
it's given, call Promise.resolve() on it (the DOM Promise one, of
course) and then end up with a DOM promise that will be resolved or
rejected with the exact value the Promise.jsm thing is resolved or
rejected with. Then return that to your callers.
but the problem is I have a lot of JS-implemented services that need to be
called from C++ which is where WebIDL is almost completely useless the
last time I checked.
WebIDL is totally happy letting C++ call into JS. You just declare a
callback interface, and get a generated C++ class that you can call into.
The missing piece is that this C++ class needs to be created with a
JSObject* pointing to the JS thing it needs to actually talk to.
We've considered factoring out the "hunt down the object" thing from
XPConnect's JS component loader so it's easier to reuse here, but for
now used the "createInstance an nsISupports, then dig out the JSObject*
from it" thing that dom::ConstructJSImplementation does.
We could add some IDL annotation that would let you get a C++ callback
interface representation for a JS-implemented XPCOM service or some
such, basically by running code like ConstructJSImplementation, but with
getService instead of createInstance, if this is something people will
want reasonably often. Note that unlike XPCOM services this would NOT
give you the same pointer identity every time you call it; doing that
would involve more annoying machinery that I'd like to not add unless
it's really required.
It might help if you ping me on IRC instead of trying to go back and
forth on the newsgroup...
Sure, if I had time today for in more than 15-minute snippets. But I'm
technically on PTO, so I don't. I could have waited a few more days
until I got back before responding at all, I guess.... ;)
-Boris
_______________________________________________
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform