From da2b2a9c060f70789fc470fc89f990c3b28abf67 Mon Sep 17 00:00:00 2001 From: Robert Gaggl Date: Tue, 4 Jan 2022 14:38:34 +0100 Subject: [PATCH] call `processMicrotasks` before exiting context to ensure pending promises are settled (see [1]) afais these two places are the only ones where functions are called directly, but there might be more [1] https://github.com/mozilla/rhino/blob/master/src/org/mozilla/javascript/Context.java#L2326 --- src/org/ringojs/engine/RingoGlobal.java | 4 +++- src/org/ringojs/engine/RingoWorker.java | 1 + test/all.js | 1 + test/rhino/all.js | 4 ++++ test/rhino/promise_test.js | 22 ++++++++++++++++++++++ 5 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 test/rhino/all.js create mode 100644 test/rhino/promise_test.js diff --git a/src/org/ringojs/engine/RingoGlobal.java b/src/org/ringojs/engine/RingoGlobal.java index 86cd62a10..a4378a349 100644 --- a/src/org/ringojs/engine/RingoGlobal.java +++ b/src/org/ringojs/engine/RingoGlobal.java @@ -217,7 +217,9 @@ public static Object spawn(Context cx, Scriptable thisObj, public Object call() { return cxfactory.call(new ContextAction() { public Object run(Context cx) { - return function.call(cx, scope, scope, fnArgs); + Object result = function.call(cx, scope, scope, fnArgs); + cx.processMicrotasks(); + return result; } }); } diff --git a/src/org/ringojs/engine/RingoWorker.java b/src/org/ringojs/engine/RingoWorker.java index b82293f29..45cff1056 100644 --- a/src/org/ringojs/engine/RingoWorker.java +++ b/src/org/ringojs/engine/RingoWorker.java @@ -126,6 +126,7 @@ public Object invoke(Object module, Object function, Object... args) } } finally { releaseWorker(previous); + cx.processMicrotasks(); Context.exit(); } } diff --git a/test/all.js b/test/all.js index 8055dff6f..36f8a8c64 100644 --- a/test/all.js +++ b/test/all.js @@ -22,6 +22,7 @@ exports.testBinary = require('./binary/all'); exports.testRepository = require('./repository/all'); exports.testIo = require('./io_test'); exports.testModules = require('./modules/all'); +exports.testRhino = require("./rhino/all"); // Also include integration tests exports.testIntegration = require('./integration-tests/all'); diff --git a/test/rhino/all.js b/test/rhino/all.js new file mode 100644 index 000000000..3348710b4 --- /dev/null +++ b/test/rhino/all.js @@ -0,0 +1,4 @@ +exports.testArrowFunctions = require("./arrow_functions"); +exports.testConstStatement = require("./const_statement"); +exports.testLetStatement = require("./let_statement"); +exports.testPromise = require("./promise_test"); diff --git a/test/rhino/promise_test.js b/test/rhino/promise_test.js new file mode 100644 index 000000000..34ba42feb --- /dev/null +++ b/test/rhino/promise_test.js @@ -0,0 +1,22 @@ +const assert = require("assert"); +const {Semaphore} = require("ringo/concurrent"); + +exports.testResolve = () => { + const semaphore = new Semaphore(); + let expected = false; + spawn(() => { + return new Promise(resolve => { + java.lang.Thread.sleep(100); + resolve(true); + }).then(value => { + expected = value; + semaphore.signal(); + }); + }); + semaphore.tryWait(150); + assert.isTrue(expected); +}; + +if (require.main === module) { + require("system").exit(require("test").run(module.id)); +}