Add queueMicrotask
Ref: https://github.com/quickjs-ng/quickjs/issues/16
This commit is contained in:
parent
1fcb573e6b
commit
8d496b3e3c
3 changed files with 102 additions and 0 deletions
1
Makefile
1
Makefile
|
@ -64,6 +64,7 @@ test: build
|
|||
$(QJS) tests/test_loop.js
|
||||
$(QJS) tests/test_std.js
|
||||
$(QJS) tests/test_worker.js
|
||||
$(QJS) tests/test_queue_microtask.js
|
||||
|
||||
test262: build
|
||||
$(RUN262) -m -c test262.conf -a
|
||||
|
|
17
quickjs.c
17
quickjs.c
|
@ -33745,6 +33745,22 @@ static JSValue js_global_isFinite(JSContext *ctx, JSValueConst this_val,
|
|||
return JS_NewBool(ctx, res);
|
||||
}
|
||||
|
||||
static JSValue js_microtask_job(JSContext *ctx,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
return JS_Call(ctx, argv[0], ctx->global_obj, 0, NULL);
|
||||
}
|
||||
|
||||
static JSValue js_global_queueMicrotask(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
if (check_function(ctx, argv[0]))
|
||||
return JS_EXCEPTION;
|
||||
if (JS_EnqueueJob(ctx, js_microtask_job, 1, &argv[0]))
|
||||
return JS_EXCEPTION;
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
/* Object class */
|
||||
|
||||
static JSValue JS_ToObject(JSContext *ctx, JSValueConst val)
|
||||
|
@ -45683,6 +45699,7 @@ static const JSCFunctionListEntry js_global_funcs[] = {
|
|||
JS_CFUNC_DEF("parseFloat", 1, js_parseFloat ),
|
||||
JS_CFUNC_DEF("isNaN", 1, js_global_isNaN ),
|
||||
JS_CFUNC_DEF("isFinite", 1, js_global_isFinite ),
|
||||
JS_CFUNC_DEF("queueMicrotask", 1, js_global_queueMicrotask ),
|
||||
|
||||
JS_CFUNC_MAGIC_DEF("decodeURI", 1, js_global_decodeURI, 0 ),
|
||||
JS_CFUNC_MAGIC_DEF("decodeURIComponent", 1, js_global_decodeURI, 1 ),
|
||||
|
|
84
tests/test_queue_microtask.js
Normal file
84
tests/test_queue_microtask.js
Normal file
|
@ -0,0 +1,84 @@
|
|||
function assert(actual, expected, message) {
|
||||
if (arguments.length == 1)
|
||||
expected = true;
|
||||
|
||||
if (actual === expected)
|
||||
return;
|
||||
|
||||
if (actual !== null && expected !== null
|
||||
&& typeof actual == 'object' && typeof expected == 'object'
|
||||
&& actual.toString() === expected.toString())
|
||||
return;
|
||||
|
||||
throw Error("assertion failed: got |" + actual + "|" +
|
||||
", expected |" + expected + "|" +
|
||||
(message ? " (" + message + ")" : ""));
|
||||
}
|
||||
|
||||
function assert_throws(expected_error, func)
|
||||
{
|
||||
var err = false;
|
||||
try {
|
||||
func();
|
||||
} catch(e) {
|
||||
err = true;
|
||||
if (!(e instanceof expected_error)) {
|
||||
throw Error("unexpected exception type");
|
||||
}
|
||||
}
|
||||
if (!err) {
|
||||
throw Error("expected exception");
|
||||
}
|
||||
}
|
||||
|
||||
function assert_array_equals(a, b) {
|
||||
if (!Array.isArray(a) || !Array.isArray(b))
|
||||
return assert(false);
|
||||
|
||||
assert(a.length === b.length);
|
||||
|
||||
a.forEach((value, idx) => {
|
||||
assert(b[idx] === value);
|
||||
});
|
||||
}
|
||||
|
||||
// load more elaborate version of assert if available
|
||||
try { std.loadScript("test_assert.js"); } catch(e) {}
|
||||
|
||||
function test_types() {
|
||||
assert_throws(TypeError, () => queueMicrotask(), "no argument");
|
||||
assert_throws(TypeError, () => queueMicrotask(undefined), "undefined");
|
||||
assert_throws(TypeError, () => queueMicrotask(null), "null");
|
||||
assert_throws(TypeError, () => queueMicrotask(0), "0");
|
||||
assert_throws(TypeError, () => queueMicrotask({ handleEvent() { } }), "an event handler object");
|
||||
assert_throws(TypeError, () => queueMicrotask("window.x = 5;"), "a string");
|
||||
}
|
||||
|
||||
function test_async() {
|
||||
let called = false;
|
||||
queueMicrotask(() => {
|
||||
called = true;
|
||||
});
|
||||
assert(!called);
|
||||
}
|
||||
|
||||
function test_arguments() {
|
||||
queueMicrotask(function () { // note: intentionally not an arrow function
|
||||
assert(arguments.length === 0);
|
||||
}, "x", "y");
|
||||
};
|
||||
|
||||
function test_async_order() {
|
||||
const happenings = [];
|
||||
Promise.resolve().then(() => happenings.push("a"));
|
||||
queueMicrotask(() => happenings.push("b"));
|
||||
Promise.reject().catch(() => happenings.push("c"));
|
||||
queueMicrotask(() => {
|
||||
assert_array_equals(happenings, ["a", "b", "c"]);
|
||||
});
|
||||
}
|
||||
|
||||
test_types();
|
||||
test_async();
|
||||
test_arguments();
|
||||
test_async_order();
|
Loading…
Reference in a new issue