Skip to content

Commit

Permalink
Add queueMicrotask
Browse files Browse the repository at this point in the history
Ref: #16
  • Loading branch information
saghul committed Nov 21, 2023
1 parent 1fcb573 commit 8d496b3
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 0 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 17 additions & 0 deletions quickjs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 ),
Expand Down
84 changes: 84 additions & 0 deletions tests/test_queue_microtask.js
Original file line number Diff line number Diff line change
@@ -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();

0 comments on commit 8d496b3

Please sign in to comment.