Skip to content

Commit a60b7c2

Browse files
authored
feat(ext/web): queueMicrotask
feat(ext/web): queueMicrotask
2 parents 4681c2e + fdbefbd commit a60b7c2

File tree

5 files changed

+49
-98
lines changed

5 files changed

+49
-98
lines changed

.github/workflows/release.yml

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ permissions:
1010

1111
jobs:
1212
build:
13-
name: Build and Release
13+
name: Build ${{ matrix.asset-name }}
1414
runs-on: ${{ matrix.os }}
1515
strategy:
1616
matrix:
@@ -57,20 +57,32 @@ jobs:
5757
mv andromeda ${{ matrix.asset-name }}
5858
fi
5959
60-
- name: Upload Binary to Release
61-
if: github.ref == 'refs/heads/main'
60+
- name: Upload Binary as Artifact
61+
uses: actions/upload-artifact@v4
62+
with:
63+
name: ${{ matrix.asset-name }}
64+
path: target/${{ matrix.rust-target }}/release/${{ matrix.asset-name }}
65+
66+
release:
67+
name: Create Release
68+
needs: build
69+
runs-on: ubuntu-latest
70+
if: github.ref == 'refs/heads/main'
71+
72+
steps:
73+
- uses: actions/checkout@v3
74+
75+
- name: Download all artifacts
76+
uses: actions/download-artifact@v4
77+
with:
78+
path: ./artifacts
79+
80+
- name: Create Draft Release
6281
uses: svenstaro/upload-release-action@v2
6382
with:
6483
repo_token: ${{ secrets.GITHUB_TOKEN }}
65-
file: target/${{ matrix.rust-target }}/release/${{ matrix.asset-name }}
66-
asset_name: ${{ matrix.asset-name }}
84+
file: ./artifacts/*/andromeda-*
85+
file_glob: true
6786
draft: true
6887
tag: latest
6988
overwrite: true
70-
71-
- name: Upload Binary as Artifact (Main Branch)
72-
if: github.ref == 'refs/heads/main'
73-
uses: actions/upload-artifact@v4
74-
with:
75-
name: ${{ matrix.asset-name }}
76-
path: target/${{ matrix.rust-target }}/release/${{ matrix.asset-name }}

runtime/src/event_loop.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

55
use crate::ext::{interval::IntervalId, timeout::TimeoutId};
6-
use nova_vm::{ecmascript::types::Value, engine::Global};
76

87
pub enum RuntimeMacroTask {
98
/// Run an interval.
@@ -14,6 +13,4 @@ pub enum RuntimeMacroTask {
1413
RunAndClearTimeout(TimeoutId),
1514
/// Stop a timeout from running no further.
1615
ClearTimeout(TimeoutId),
17-
/// Run a microtask callback
18-
RunMicrotaskCallback(Global<Value<'static>>),
1916
}

runtime/src/ext/web/mod.rs

Lines changed: 1 addition & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22
// License, v. 2.0. If a copy of the MPL was not distributed with this
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

5-
use crate::RuntimeMacroTask;
65
use andromeda_core::{Extension, ExtensionOp};
7-
use andromeda_core::{HostData, MacroTask};
8-
use nova_vm::engine::Global;
96
use nova_vm::{
107
ecmascript::{
118
builtins::ArgumentsList,
@@ -49,13 +46,13 @@ impl WebExt {
4946
Self::internal_performance_time_origin,
5047
0,
5148
),
52-
ExtensionOp::new("queueMicrotask", Self::queue_microtask, 1),
5349
],
5450
storage: None,
5551
files: vec![
5652
include_str!("./event.ts"),
5753
include_str!("./text_encoding.ts"),
5854
include_str!("./performance.ts"),
55+
include_str!("./queueMicrotask.ts"),
5956
],
6057
}
6158
}
@@ -422,53 +419,6 @@ impl WebExt {
422419
.as_secs_f64()
423420
* 1000.0
424421
});
425-
426422
Ok(Value::from_f64(agent, origin_ms, gc).unbind())
427423
}
428-
429-
/// Implementation of queueMicrotask as per HTML specification:
430-
/// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-queuemicrotask
431-
pub fn queue_microtask<'gc>(
432-
agent: &mut Agent,
433-
_this: Value,
434-
args: ArgumentsList,
435-
gc: GcScope<'gc, '_>,
436-
) -> JsResult<'gc, Value<'gc>> {
437-
let callback = args.get(0);
438-
let _: nova_vm::ecmascript::types::Function = match callback.try_into() {
439-
Ok(function) => function,
440-
Err(_) => {
441-
return Err(agent
442-
.throw_exception(
443-
ExceptionType::TypeError,
444-
"The callback provided as an argument to queueMicrotask must be a function.".to_string(),
445-
gc.nogc(),
446-
)
447-
.unbind());
448-
}
449-
};
450-
451-
// TODO: Implement proper microtask queueing when Nova APIs become available
452-
453-
// Store the callback globally so it can be called later
454-
let root_callback = Global::new(agent, callback.unbind());
455-
456-
// Get host data to access the macro task system
457-
let host_data = agent.get_host_data();
458-
let host_data: &HostData<RuntimeMacroTask> = host_data.downcast_ref().unwrap();
459-
let macro_task_tx = host_data.macro_task_tx();
460-
461-
// Schedule an immediate task to call the callback
462-
// Using spawn_macro_task with an immediately resolving future
463-
host_data.spawn_macro_task(async move {
464-
// Send a macro task to call the callback
465-
macro_task_tx
466-
.send(MacroTask::User(RuntimeMacroTask::RunMicrotaskCallback(
467-
root_callback,
468-
)))
469-
.unwrap();
470-
});
471-
472-
Ok(Value::Undefined)
473-
}
474424
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
5+
// deno-lint-ignore-file
6+
7+
function queueMicrotask(callback: () => void): void {
8+
if (typeof callback !== "function") {
9+
throw new TypeError(
10+
"The callback provided as an argument to queueMicrotask must be a function.",
11+
);
12+
}
13+
14+
Promise.resolve().then(() => {
15+
try {
16+
callback();
17+
} catch (error) {
18+
console.error("Uncaught error in microtask callback:", error);
19+
throw error;
20+
}
21+
});
22+
}

runtime/src/recommended.rs

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,8 @@
22
// License, v. 2.0. If a copy of the MPL was not distributed with this
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

5-
use andromeda_core::{AndromedaError, ErrorReporter, Extension, HostData};
6-
use nova_vm::{
7-
ecmascript::execution::agent::{GcAgent, RealmRoot},
8-
ecmascript::types::{Function, Value},
9-
};
5+
use andromeda_core::{Extension, HostData};
6+
use nova_vm::ecmascript::execution::agent::{GcAgent, RealmRoot};
107

118
use crate::{ConsoleExt, FsExt, HeadersExt, ProcessExt, RuntimeMacroTask, TimeExt, URLExt, WebExt};
129

@@ -47,32 +44,5 @@ pub fn recommended_eventloop_handler(
4744
RuntimeMacroTask::ClearTimeout(timeout_id) => {
4845
timeout_id.clear_and_abort(host_data);
4946
}
50-
RuntimeMacroTask::RunMicrotaskCallback(root_callback) => {
51-
// Execute the microtask callback - this is for queueMicrotask implementation
52-
agent.run_in_realm(realm_root, |agent, gc| {
53-
let callback = root_callback.get(agent, gc.nogc());
54-
if let Ok(callback_function) = Function::try_from(callback) {
55-
// Call the callback with no arguments as per HTML spec
56-
// If the callback throws an error, it should be reported but not stop execution
57-
if let Err(error) = callback_function.call(agent, Value::Undefined, &mut [], gc)
58-
{
59-
// Report the error as per Web IDL "invoke a callback function" with "report" error handling
60-
// This is the proper implementation of error reporting for queueMicrotask
61-
report_microtask_error(error);
62-
}
63-
}
64-
});
65-
}
6647
}
6748
}
68-
69-
/// Report a microtask error
70-
/// This is called when a queueMicrotask callback throws an exception.
71-
fn report_microtask_error<E>(error: E)
72-
where
73-
E: std::fmt::Debug,
74-
{
75-
let error_message = format!("Uncaught error in microtask callback: {:?}", error);
76-
let andromeda_error = AndromedaError::runtime_error(error_message);
77-
ErrorReporter::print_error(&andromeda_error);
78-
}

0 commit comments

Comments
 (0)