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.

Reply via email to