mirror of
https://github.com/espruino/Espruino.git
synced 2025-12-08 19:06:15 +00:00
Fixes for Promise.all (ordering) (fix #976)
This commit is contained in:
parent
0f4da0a64f
commit
21e8f034a6
@ -1,4 +1,4 @@
|
||||
1v90 : Partial fixes for Promise.all (passing in non-promises) #976
|
||||
1v90 : Fixes for Promise.all (passing in non-promises, pre-resolved, and ordering) (fix #976)
|
||||
|
||||
1v89 : Allow entering of multi-line Templated Literals on the command-line (fix #970)
|
||||
Make lexer fail when parsing non-templated strings with newlines in
|
||||
|
||||
@ -20,8 +20,9 @@
|
||||
|
||||
#define JS_PROMISE_THEN_NAME JS_HIDDEN_CHAR_STR"thn"
|
||||
#define JS_PROMISE_CATCH_NAME JS_HIDDEN_CHAR_STR"cat"
|
||||
#define JS_PROMISE_COUNT_NAME JS_HIDDEN_CHAR_STR"cnt"
|
||||
#define JS_PROMISE_REMAINING_NAME JS_HIDDEN_CHAR_STR"left"
|
||||
#define JS_PROMISE_RESULT_NAME JS_HIDDEN_CHAR_STR"res"
|
||||
#define JS_PROMISE_RESOLVED_NAME "resolved"
|
||||
|
||||
|
||||
/*JSON{
|
||||
@ -114,7 +115,7 @@ void _jswrap_promise_resolve_or_reject_chain(JsVar *promise, JsVar *data, bool r
|
||||
jsvUnLock(fn);
|
||||
} else {
|
||||
if (resolve)
|
||||
jsvObjectSetChild(promise, "resolved", data);
|
||||
jsvObjectSetChild(promise, JS_PROMISE_RESOLVED_NAME, data);
|
||||
else
|
||||
jsExceptionHere(JSET_ERROR, "Unhandled promise rejection: %v", data);
|
||||
}
|
||||
@ -142,12 +143,16 @@ void _jswrap_promise_queuereject(JsVar *promise, JsVar *data) {
|
||||
jsvUnLock(fn);
|
||||
}
|
||||
|
||||
void jswrap_promise_all_resolve(JsVar *promise, JsVar *data) {
|
||||
JsVarInt i = jsvGetIntegerAndUnLock(jsvObjectGetChild(promise, JS_PROMISE_COUNT_NAME, 0));
|
||||
void jswrap_promise_all_resolve(JsVar *promise, JsVarInt index, JsVar *data) {
|
||||
JsVarInt remaining = jsvGetIntegerAndUnLock(jsvObjectGetChild(promise, JS_PROMISE_REMAINING_NAME, 0));
|
||||
JsVar *arr = jsvObjectGetChild(promise, JS_PROMISE_RESULT_NAME, 0);
|
||||
if (arr) {
|
||||
// we may have already rejected...
|
||||
if (jsvArrayPush(arr, data) == i) {
|
||||
// set the result
|
||||
jsvSetArrayItem(arr, index, data);
|
||||
// Update remaining list
|
||||
remaining--;
|
||||
jsvObjectSetChildAndUnLock(promise, JS_PROMISE_REMAINING_NAME, jsvNewFromInteger(remaining));
|
||||
if (remaining==0) {
|
||||
_jswrap_promise_queueresolve(promise, arr);
|
||||
}
|
||||
jsvUnLock(arr);
|
||||
@ -239,32 +244,43 @@ JsVar *jswrap_promise_all(JsVar *arr) {
|
||||
}
|
||||
JsVar *promise = jspNewObject(0, "Promise");
|
||||
if (!promise) return 0;
|
||||
JsVar *resolve = jsvNewNativeFunction((void (*)(void))jswrap_promise_all_resolve, JSWAT_VOID|JSWAT_THIS_ARG|(JSWAT_JSVAR<<JSWAT_BITS));
|
||||
JsVar *reject = jsvNewNativeFunction((void (*)(void))jswrap_promise_all_reject, JSWAT_VOID|JSWAT_THIS_ARG|(JSWAT_JSVAR<<JSWAT_BITS));
|
||||
if (resolve && reject) {
|
||||
jsvObjectSetChild(resolve, JSPARSE_FUNCTION_THIS_NAME, promise);
|
||||
if (reject) {
|
||||
jsvObjectSetChild(reject, JSPARSE_FUNCTION_THIS_NAME, promise);
|
||||
JsVar *promiseResults = jsvNewEmptyArray();
|
||||
int promises = 0;
|
||||
int promiseIndex = 0;
|
||||
int promisesComplete = 0;
|
||||
JsvObjectIterator it;
|
||||
jsvObjectIteratorNew(&it, arr);
|
||||
while (jsvObjectIteratorHasValue(&it)) {
|
||||
JsVar *p = jsvObjectIteratorGetValue(&it);
|
||||
if (_jswrap_promise_is_promise(p)) {
|
||||
jsvUnLock(jswrap_promise_then(p, resolve, reject));
|
||||
JsVar *resolve = jsvNewNativeFunction((void (*)(void))jswrap_promise_all_resolve, JSWAT_VOID|JSWAT_THIS_ARG|(JSWAT_INT32<<JSWAT_BITS)|(JSWAT_JSVAR<<(JSWAT_BITS*2)));
|
||||
// bind the index variable
|
||||
JsVar *paramName = jsvNewFromEmptyString();
|
||||
if (paramName) {
|
||||
jsvMakeFunctionParameter(paramName); // force this to be called a function parameter
|
||||
JsVar *indexVar = jsvNewFromInteger(promiseIndex);
|
||||
jsvSetValueOfName(paramName, indexVar);
|
||||
jsvAddName(resolve, paramName);
|
||||
jsvUnLock2(indexVar, paramName);
|
||||
}
|
||||
jsvObjectSetChild(resolve, JSPARSE_FUNCTION_THIS_NAME, promise);
|
||||
jsvUnLock2(jswrap_promise_then(p, resolve, reject), resolve);
|
||||
} else {
|
||||
jsvArrayPush(promiseResults, p);
|
||||
jsvSetArrayItem(promiseResults, promiseIndex, p);
|
||||
promisesComplete++;
|
||||
}
|
||||
jsvUnLock(p);
|
||||
promises++;
|
||||
promiseIndex++;
|
||||
jsvObjectIteratorNext(&it);
|
||||
}
|
||||
jsvObjectIteratorFree(&it);
|
||||
|
||||
jsvObjectSetChildAndUnLock(promise, JS_PROMISE_COUNT_NAME, jsvNewFromInteger(promises));
|
||||
jsvObjectSetChildAndUnLock(promise, JS_PROMISE_REMAINING_NAME, jsvNewFromInteger(promiseIndex-promisesComplete));
|
||||
jsvObjectSetChildAndUnLock(promise, JS_PROMISE_RESULT_NAME, promiseResults);
|
||||
}
|
||||
jsvUnLock2(resolve, reject);
|
||||
jsvUnLock(reject);
|
||||
return promise;
|
||||
}
|
||||
|
||||
@ -321,7 +337,7 @@ void _jswrap_promise_add(JsVar *parent, JsVar *callback, bool resolve) {
|
||||
// Check to see if promise has already been resolved
|
||||
/* Note: we use jsvFindChildFromString not ObjectGetChild so we get the name.
|
||||
* If we didn't then we wouldn't know if it was resolved, but with undefined */
|
||||
JsVar *resolved = jsvFindChildFromString(parent, "resolved", 0);
|
||||
JsVar *resolved = jsvFindChildFromString(parent, JS_PROMISE_RESOLVED_NAME, 0);
|
||||
if (resolved) {
|
||||
resolved = jsvSkipNameAndUnLock(resolved);
|
||||
// If so, queue a resolve event
|
||||
|
||||
18
tests/test_promise_all.js
Normal file
18
tests/test_promise_all.js
Normal file
@ -0,0 +1,18 @@
|
||||
var alreadyCompleted1 = new Promise( function(resolve,reject) { resolve(42); } );
|
||||
var alreadyCompleted2 = new Promise( function(resolve,reject) { resolve(); } );
|
||||
|
||||
setTimeout(function() {
|
||||
var p1 = Promise.resolve(3);
|
||||
var p2 = 1337;
|
||||
/*var p3 = new Promise((resolve, reject) => {
|
||||
setTimeout(resolve, 100, "foo");
|
||||
}); */
|
||||
var p3 = new Promise(function(resolve, reject) {
|
||||
setTimeout(resolve, 100, "foo");
|
||||
});
|
||||
|
||||
Promise.all([alreadyCompleted1,alreadyCompleted2,p1, p2, p3]).then(values => {
|
||||
allresult = values.toString();
|
||||
result = allresult=="42,,3,1337,foo";
|
||||
});
|
||||
}, 1);
|
||||
Loading…
x
Reference in New Issue
Block a user