I didn't know about the JavaScript Promises stuff, that's interesting. To allow sync-looking code on the C++ side, it would need to integrate with something there, if there is a c++11 feature that works there, as you say, then this might work very well.
- Alon On Sun, Mar 16, 2014 at 11:44 PM, Joel Croteau <[email protected]> wrote: > I was able to implement this using Javascript Promises (I haven't made > this a pull request because it's rather experimental): > > emscripten_sync_wget2_data: function(url, request, param, arg, free, > onload, onerror, onprogress) { > var _url = Pointer_stringify(url); > var _request = Pointer_stringify(request); > var _param = Pointer_stringify(param); > > var promise = new Promise(function(resolve, reject) { > var http = new XMLHttpRequest(); > http.open(_request, _url, true); > http.responseType = 'arraybuffer'; > > // LOAD > http.onload = function http_onload(e) { > if (http.status == 200 || _url.substr(0,4).toLowerCase() != > "http") { > resolve(http.response); > } > else { > reject(http.status, http.statusText); > } > }; > > // ERROR > http.onerror = function http_onerror(e) { > reject(http.status, http.statusText); > }; > > // PROGRESS > http.onprogress = function http_onprogress(e) { > if (onprogress) Runtime.dynCall('viii', onprogress, [arg, > e.loaded, e.lengthComputable || e.lengthComputable === undefined ? e.total > : 0]); > }; > > // Useful because the browser can limit the number of redirection > try { > if (http.channel instanceof Ci.nsIHttpChannel) > http.channel.redirectionLimit = 0; > } catch (ex) { /* whatever */ } > > if (_request == "POST") { > //Send the proper header information along with the request > http.setRequestHeader("Content-type", > "application/x-www-form-urlencoded"); > http.setRequestHeader("Content-length", _param.length); > http.setRequestHeader("Connection", "close"); > http.send(_param); > } else { > http.send(null); > } > }); > > promise.then(function(data) { > var byteArray = new Uint8Array(data); > var buffer = _malloc(byteArray.length); > HEAPU8.set(byteArray, buffer); > if (onload) Runtime.dynCall('viii', onload, [arg, buffer, > byteArray.length]); > if (free) _free(buffer); > }, function(status, statusText) { > if (onerror) Runtime.dynCall('viii', onerror, [arg, status, > statusText]); > }); > }, > > Promises are still fairly new, and only supported by the most recent > versions of Chrome and Firefox, but they do give us the functionality we > want here. I think the best way to implement this in code would be if I > could use the C++ promise and future APIs. You can use these if you compile > with -std=c++11. All this seems to do at present is send the code into an > infinite loop, but if they could map into equivalent Javascript promise > calls, I think it could work quite well. At least in the case of > emscripten_sync_wget2_data, it could be set to use synchronous XHRs as a > fallback. This would still work, just require some extra conversion work, > and wouldn't call onprogress events. > > On Sunday, March 16, 2014 7:17:56 PM UTC-7, Alon Zakai wrote: > >> It can capture its environment, so you can put the second half of the >> function in a lambda, and call the lambda later on when you want to, in >> response to something. >> >> - Alon >> >> >> >> On Sun, Mar 16, 2014 at 7:12 PM, Joel Croteau <[email protected]> wrote: >> >>> I can understand using Javascript generators, but how would c++ lambdas >>> help? >>> On Mar 16, 2014 3:47 PM, "Alon Zakai" <[email protected]> wrote: >>> >>>> Currently not. It would require a very different code generation >>>> approach than we currently have. >>>> >>>> In theory something similar could be done using generators, in very >>>> recent versions of firefox and chrome. But even with the help of >>>> generators, this is not easy to do, and it is not clear how it would affect >>>> performance - likely very adversely. >>>> >>>> One similar thing you can do is manage your own code using c++11 >>>> lambdas. You could write a little system that continues to run the current >>>> function once a callback triggers that. >>>> >>>> - Alon >>>> >>>> >>>> >>>> On Sun, Mar 16, 2014 at 1:43 AM, Joel Croteau <[email protected]>wrote: >>>> >>>>> I would like to have a function that makes an async call, and returns >>>>> control to the browser during the call, then resumes once the async call >>>>> is >>>>> complete. However, I would like this to appear to the calling code to be a >>>>> synchronous call. So for instance, I could do something like this: >>>>> >>>>> struct FileInfo >>>>> { >>>>> void* buffer; >>>>> unsigned size; >>>>> }; >>>>> >>>>> FileInfo loadUrl(const char* url) >>>>> { >>>>> FileInfo info; >>>>> emscripten_async_wget2_data(url, "GET", "", &info, false, onload, >>>>> onerror, onprogress); >>>>> emscripten_pause(); // Blocks until emscripten_resume() is called >>>>> return info; >>>>> } >>>>> >>>>> void onerror(void* ptr, int code, const char* desc) >>>>> { >>>>> // Handle not found, etc. >>>>> } >>>>> >>>>> void onprogress(void* ptr, int loaded, int total) >>>>> { >>>>> // Update progress bar >>>>> } >>>>> >>>>> void onload(void* ptr, void* buffer, unsigned size) >>>>> { >>>>> static_cast<FileInfo*>(ptr)->buffer = buffer; >>>>> static_cast<FileInfo*>(ptr)->size = size; >>>>> >>>>> emscripten_resume(); // Now loadUrl resumes and returns FileInfo. >>>>> } >>>>> >>>>> Is there any way to do this? >>>>> >>>>> -- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "emscripten-discuss" group. >>>>> To unsubscribe from this group and stop receiving emails from it, send >>>>> an email to [email protected]. >>>>> For more options, visit https://groups.google.com/d/optout. >>>>> >>>> >>>> -- >>>> You received this message because you are subscribed to a topic in the >>>> Google Groups "emscripten-discuss" group. >>>> To unsubscribe from this topic, visit https://groups.google.com/d/ >>>> topic/emscripten-discuss/Op5ifeMjauA/unsubscribe. >>>> To unsubscribe from this group and all its topics, send an email to >>>> [email protected]. >>>> >>>> For more options, visit https://groups.google.com/d/optout. >>>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "emscripten-discuss" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to [email protected]. >>> For more options, visit https://groups.google.com/d/optout. >>> >> >> -- > You received this message because you are subscribed to the Google Groups > "emscripten-discuss" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "emscripten-discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
