Skip to content

Commit f033061

Browse files
authored
feat: queueMicrotask support (#1868)
1 parent 99fcb75 commit f033061

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed

test-app/app/src/main/assets/app/mainpage.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,5 @@ require("./tests/testPostFrameCallback");
7272
require("./tests/console/logTests.js");
7373
require('./tests/testURLImpl.js');
7474
require('./tests/testURLSearchParamsImpl.js');
75-
require('./tests/testPerformanceNow');
75+
require('./tests/testPerformanceNow');
76+
require('./tests/testQueueMicrotask');
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
describe('queueMicrotask', () => {
2+
it('should be defined as a function', () => {
3+
expect(typeof queueMicrotask).toBe('function');
4+
});
5+
6+
it('should throw TypeError when callback is not a function', () => {
7+
expect(() => queueMicrotask(null)).toThrow();
8+
expect(() => queueMicrotask(123)).toThrow();
9+
expect(() => queueMicrotask({})).toThrow();
10+
});
11+
12+
it('runs after current stack but before setTimeout(0)', (done) => {
13+
const order = [];
14+
queueMicrotask(() => order.push('microtask'));
15+
setTimeout(() => {
16+
order.push('timeout');
17+
expect(order).toEqual(['microtask', 'timeout']);
18+
done();
19+
}, 0);
20+
// at this point, nothing should have run yet
21+
expect(order.length).toBe(0);
22+
});
23+
24+
it('preserves ordering with Promise microtasks', (done) => {
25+
const order = [];
26+
queueMicrotask(() => order.push('qm1'));
27+
Promise.resolve().then(() => order.push('p'));
28+
queueMicrotask(() => order.push('qm2'));
29+
30+
setTimeout(() => {
31+
expect(order).toEqual(['qm1', 'p', 'qm2']);
32+
done();
33+
}, 0);
34+
});
35+
});

test-app/runtime/src/main/cpp/Runtime.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,21 @@ Isolate* Runtime::PrepareV8Runtime(const string& filesPath, const string& native
537537
performanceTemplate->Set(ArgConverter::ConvertToV8String(isolate, "timeOrigin"), Number::New(isolate, m_realtimeOrigin));
538538
globalTemplate->Set(ArgConverter::ConvertToV8String(isolate, "performance"), performanceTemplate);
539539
}
540+
// queueMicrotask(callback) per spec: https://developer.mozilla.org/en-US/docs/Web/API/Window/queueMicrotask
541+
globalTemplate->Set(
542+
ArgConverter::ConvertToV8String(isolate, "queueMicrotask"),
543+
FunctionTemplate::New(
544+
isolate,
545+
[](const v8::FunctionCallbackInfo<v8::Value>& info) {
546+
auto* isolate = info.GetIsolate();
547+
if (info.Length() < 1 || !info[0]->IsFunction()) {
548+
isolate->ThrowException(v8::Exception::TypeError(
549+
ArgConverter::ConvertToV8String(isolate, "queueMicrotask: callback must be a function")));
550+
return;
551+
}
552+
v8::Local<v8::Function> cb = info[0].As<v8::Function>();
553+
isolate->EnqueueMicrotask(cb);
554+
}));
540555
globalTemplate->Set(ArgConverter::ConvertToV8String(isolate, "__releaseNativeCounterpart"), FunctionTemplate::New(isolate, CallbackHandlers::ReleaseNativeCounterpartCallback));
541556
globalTemplate->Set(ArgConverter::ConvertToV8String(isolate, "__markingMode"), Number::New(isolate, m_objectManager->GetMarkingMode()), readOnlyFlags);
542557
globalTemplate->Set(ArgConverter::ConvertToV8String(isolate, "__runOnMainThread"), FunctionTemplate::New(isolate, CallbackHandlers::RunOnMainThreadCallback));

0 commit comments

Comments
 (0)