diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/js/40_testing.js | 43 | ||||
-rw-r--r-- | runtime/worker.rs | 94 |
2 files changed, 116 insertions, 21 deletions
diff --git a/runtime/js/40_testing.js b/runtime/js/40_testing.js index 276fef6a6..e3a6ce324 100644 --- a/runtime/js/40_testing.js +++ b/runtime/js/40_testing.js @@ -16,6 +16,7 @@ ArrayPrototypePush, ArrayPrototypeShift, ArrayPrototypeSort, + BigInt, DateNow, Error, FunctionPrototype, @@ -600,7 +601,8 @@ const testStates = new Map(); /** @type {BenchDescription[]} */ const benchDescs = []; - let isTestOrBenchSubcommand = false; + let isTestSubcommand = false; + let isBenchSubcommand = false; // Main test function provided by Deno. function test( @@ -608,7 +610,7 @@ optionsOrFn, maybeFn, ) { - if (!isTestOrBenchSubcommand) { + if (!isTestSubcommand) { return; } @@ -727,7 +729,7 @@ optionsOrFn, maybeFn, ) { - if (!isTestOrBenchSubcommand) { + if (!isBenchSubcommand) { return; } @@ -1032,11 +1034,12 @@ return ops.op_bench_now(); } - // This function is called by Rust side if we're in `deno test` or - // `deno bench` subcommand. If this function is not called then `Deno.test()` - // and `Deno.bench()` become noops. - function enableTestAndBench() { - isTestOrBenchSubcommand = true; + function enableTest() { + isTestSubcommand = true; + } + + function enableBench() { + isBenchSubcommand = true; } async function runTests({ @@ -1062,15 +1065,16 @@ if (shuffle !== null) { // http://en.wikipedia.org/wiki/Linear_congruential_generator + // Use BigInt for everything because the random seed is u64. const nextInt = (function (state) { - const m = 0x80000000; - const a = 1103515245; - const c = 12345; + const m = 0x80000000n; + const a = 1103515245n; + const c = 12345n; return function (max) { - return state = ((a * state + c) % m) % max; + return state = ((a * state + c) % m) % BigInt(max); }; - }(shuffle)); + }(BigInt(shuffle))); for (let i = filtered.length - 1; i > 0; i--) { const j = nextInt(i); @@ -1390,15 +1394,12 @@ return testFn; } - window.__bootstrap.internals = { - ...window.__bootstrap.internals ?? {}, - enableTestAndBench, - runTests, - runBenchmarks, - }; - window.__bootstrap.testing = { - test, bench, + enableBench, + enableTest, + runBenchmarks, + runTests, + test, }; })(this); diff --git a/runtime/worker.rs b/runtime/worker.rs index 79b1b5537..632805e6d 100644 --- a/runtime/worker.rs +++ b/runtime/worker.rs @@ -11,6 +11,9 @@ use deno_core::error::AnyError; use deno_core::error::JsError; use deno_core::futures::Future; use deno_core::located_script_name; +use deno_core::serde_json::json; +use deno_core::serde_v8; +use deno_core::v8; use deno_core::CompiledWasmModuleStore; use deno_core::Extension; use deno_core::GetErrorClassFn; @@ -59,6 +62,10 @@ pub struct MainWorker { pub js_runtime: JsRuntime, should_break_on_first_statement: bool, exit_code: ExitCode, + js_run_tests_callback: v8::Global<v8::Function>, + js_run_benchmarks_callback: v8::Global<v8::Function>, + js_enable_test_callback: v8::Global<v8::Function>, + js_enable_bench_callback: v8::Global<v8::Function>, } pub struct WorkerOptions { @@ -86,6 +93,15 @@ pub struct WorkerOptions { pub stdio: Stdio, } +fn grab_cb( + scope: &mut v8::HandleScope, + path: &str, +) -> v8::Global<v8::Function> { + let cb = JsRuntime::grab_global::<v8::Function>(scope, path) + .unwrap_or_else(|| panic!("{} must be defined", path)); + v8::Global::new(scope, cb) +} + impl MainWorker { pub fn bootstrap_from_options( main_module: ModuleSpecifier, @@ -198,10 +214,29 @@ impl MainWorker { ); } + let ( + js_run_tests_callback, + js_run_benchmarks_callback, + js_enable_test_callback, + js_enable_bench_callback, + ) = { + let scope = &mut js_runtime.handle_scope(); + ( + grab_cb(scope, "__bootstrap.testing.runTests"), + grab_cb(scope, "__bootstrap.testing.runBenchmarks"), + grab_cb(scope, "__bootstrap.testing.enableTest"), + grab_cb(scope, "__bootstrap.testing.enableBench"), + ) + }; + Self { js_runtime, should_break_on_first_statement: options.should_break_on_first_statement, exit_code, + js_run_tests_callback, + js_run_benchmarks_callback, + js_enable_test_callback, + js_enable_bench_callback, } } @@ -289,6 +324,65 @@ impl MainWorker { self.evaluate_module(id).await } + /// Run tests declared with `Deno.test()`. Test events will be dispatched + /// by calling ops which are currently only implemented in the CLI crate. + // TODO(nayeemrmn): Move testing ops to deno_runtime and redesign/unhide. + #[doc(hidden)] + pub async fn run_tests( + &mut self, + shuffle: &Option<u64>, + ) -> Result<(), AnyError> { + let promise = { + let scope = &mut self.js_runtime.handle_scope(); + let cb = self.js_run_tests_callback.open(scope); + let this = v8::undefined(scope).into(); + let options = + serde_v8::to_v8(scope, json!({ "shuffle": shuffle })).unwrap(); + let promise = cb.call(scope, this, &[options]).unwrap(); + v8::Global::new(scope, promise) + }; + self.js_runtime.resolve_value(promise).await?; + Ok(()) + } + + /// Run benches declared with `Deno.bench()`. Bench events will be dispatched + /// by calling ops which are currently only implemented in the CLI crate. + // TODO(nayeemrmn): Move benchmark ops to deno_runtime and redesign/unhide. + #[doc(hidden)] + pub async fn run_benchmarks(&mut self) -> Result<(), AnyError> { + let promise = { + let scope = &mut self.js_runtime.handle_scope(); + let cb = self.js_run_benchmarks_callback.open(scope); + let this = v8::undefined(scope).into(); + let promise = cb.call(scope, this, &[]).unwrap(); + v8::Global::new(scope, promise) + }; + self.js_runtime.resolve_value(promise).await?; + Ok(()) + } + + /// Enable `Deno.test()`. If this isn't called before executing user code, + /// `Deno.test()` calls will noop. + // TODO(nayeemrmn): Move testing ops to deno_runtime and redesign/unhide. + #[doc(hidden)] + pub fn enable_test(&mut self) { + let scope = &mut self.js_runtime.handle_scope(); + let cb = self.js_enable_test_callback.open(scope); + let this = v8::undefined(scope).into(); + cb.call(scope, this, &[]).unwrap(); + } + + /// Enable `Deno.bench()`. If this isn't called before executing user code, + /// `Deno.bench()` calls will noop. + // TODO(nayeemrmn): Move benchmark ops to deno_runtime and redesign/unhide. + #[doc(hidden)] + pub fn enable_bench(&mut self) { + let scope = &mut self.js_runtime.handle_scope(); + let cb = self.js_enable_bench_callback.open(scope); + let this = v8::undefined(scope).into(); + cb.call(scope, this, &[]).unwrap(); + } + fn wait_for_inspector_session(&mut self) { if self.should_break_on_first_statement { self |