1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-29 16:30:56 -05:00

feat(core): pump V8 message loop on event loop tick (#11221)

This commit adds support for Atomics and FinalizationRegistry by integrating
V8's message loop into "JsRuntime::poll_event_loop".
This commit is contained in:
Bartek Iwańczuk 2021-07-02 10:46:37 +02:00 committed by GitHub
parent 5648b22fe1
commit 513f921219
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 90 additions and 0 deletions

View file

@ -0,0 +1,20 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
"use strict";
function assertEquals(a, b) {
if (a === b) return;
throw a + " does not equal " + b;
}
const registry = new FinalizationRegistry((value) => {
assertEquals(value, "called!");
Deno.core.print("FinalizationRegistry called!\n");
});
(function () {
let x = {};
registry.register(x, "called!");
x = null;
})();
gc();

View file

@ -0,0 +1 @@
FinalizationRegistry called!

View file

@ -660,6 +660,12 @@ itest!(heapstats {
output: "heapstats.js.out", output: "heapstats.js.out",
}); });
itest!(finalization_registry {
args:
"run --quiet --unstable --v8-flags=--expose-gc finalization_registry.js",
output: "finalization_registry.js.out",
});
itest!(https_import { itest!(https_import {
args: "run --quiet --reload --cert tls/RootCA.pem https_import.ts", args: "run --quiet --reload --cert tls/RootCA.pem https_import.ts",
output: "https_import.ts.out", output: "https_import.ts.out",

View file

@ -591,6 +591,17 @@ impl JsRuntime {
} }
} }
fn pump_v8_message_loop(&mut self) {
let scope = &mut self.handle_scope();
while v8::Platform::pump_message_loop(
&v8::V8::get_current_platform(),
scope,
false, // don't block if there are no tasks
) {
// do nothing
}
}
/// Runs event loop to completion /// Runs event loop to completion
/// ///
/// This future resolves when: /// This future resolves when:
@ -647,6 +658,8 @@ impl JsRuntime {
// Top level module // Top level module
self.evaluate_pending_module(); self.evaluate_pending_module();
self.pump_v8_message_loop();
let state = state_rc.borrow(); let state = state_rc.borrow();
let module_map = module_map_rc.borrow(); let module_map = module_map_rc.borrow();
@ -1954,6 +1967,56 @@ main();
}) })
} }
#[test]
fn test_pump_message_loop() {
run_in_task(|cx| {
let mut runtime = JsRuntime::new(RuntimeOptions::default());
runtime
.execute_script(
"pump_message_loop.js",
r#"
function assertEquals(a, b) {
if (a === b) return;
throw a + " does not equal " + b;
}
const sab = new SharedArrayBuffer(16);
const i32a = new Int32Array(sab);
globalThis.resolved = false;
(function() {
const result = Atomics.waitAsync(i32a, 0, 0);
result.value.then(
(value) => { assertEquals("ok", value); globalThis.resolved = true; },
() => { assertUnreachable();
});
})();
const notify_return_value = Atomics.notify(i32a, 0, 1);
assertEquals(1, notify_return_value);
"#,
)
.unwrap();
match runtime.poll_event_loop(cx, false) {
Poll::Ready(Ok(())) => {}
_ => panic!(),
};
// noop script, will resolve promise from first script
runtime
.execute_script("pump_message_loop2.js", r#"assertEquals(1, 1);"#)
.unwrap();
// check that promise from `Atomics.waitAsync` has been resolved
runtime
.execute_script(
"pump_message_loop3.js",
r#"assertEquals(globalThis.resolved, true);"#,
)
.unwrap();
})
}
#[test] #[test]
fn test_core_js_stack_frame() { fn test_core_js_stack_frame() {
let mut runtime = JsRuntime::new(RuntimeOptions::default()); let mut runtime = JsRuntime::new(RuntimeOptions::default());