mirror of
https://github.com/denoland/deno.git
synced 2024-12-25 16:49:18 -05:00
Add --seed for setting RNG seed (#2483)
This commit is contained in:
parent
cb58162052
commit
d82c1991cf
7 changed files with 112 additions and 2 deletions
68
cli/flags.rs
68
cli/flags.rs
|
@ -29,6 +29,7 @@ pub struct DenoFlags {
|
|||
pub allow_hrtime: bool,
|
||||
pub no_prompts: bool,
|
||||
pub no_fetch: bool,
|
||||
pub seed: Option<u64>,
|
||||
pub v8_flags: Option<Vec<String>>,
|
||||
pub xeval_replvar: Option<String>,
|
||||
pub xeval_delim: Option<String>,
|
||||
|
@ -145,6 +146,19 @@ To get help on the another subcommands (run in this case):
|
|||
.help("Load compiler configuration file")
|
||||
.takes_value(true)
|
||||
.global(true),
|
||||
).arg(
|
||||
Arg::with_name("seed")
|
||||
.long("seed")
|
||||
.value_name("NUMBER")
|
||||
.help("Seed Math.random()")
|
||||
.takes_value(true)
|
||||
.validator(|val: String| {
|
||||
match val.parse::<u64>() {
|
||||
Ok(_) => Ok(()),
|
||||
Err(_) => Err("Seed should be a number".to_string())
|
||||
}
|
||||
})
|
||||
.global(true),
|
||||
).arg(
|
||||
Arg::with_name("v8-options")
|
||||
.long("v8-options")
|
||||
|
@ -379,6 +393,22 @@ pub fn parse_flags(matches: &ArgMatches) -> DenoFlags {
|
|||
v8_flags.insert(0, "deno".to_string());
|
||||
flags.v8_flags = Some(v8_flags);
|
||||
}
|
||||
if matches.is_present("seed") {
|
||||
let seed_string = matches.value_of("seed").unwrap();
|
||||
let seed = seed_string.parse::<u64>().unwrap();
|
||||
flags.seed = Some(seed);
|
||||
|
||||
let v8_seed_flag = format!("--random-seed={}", seed);
|
||||
|
||||
match flags.v8_flags {
|
||||
Some(ref mut v8_flags) => {
|
||||
v8_flags.push(v8_seed_flag);
|
||||
}
|
||||
None => {
|
||||
flags.v8_flags = Some(svec!["deno", v8_seed_flag]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flags = parse_run_args(flags, matches);
|
||||
// flags specific to "run" subcommand
|
||||
|
@ -1112,4 +1142,42 @@ mod tests {
|
|||
assert_eq!(subcommand, DenoSubcommand::Run);
|
||||
assert_eq!(argv, svec!["deno", "script.ts"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_flags_from_vec_28() {
|
||||
let (flags, subcommand, argv) =
|
||||
flags_from_vec(svec!["deno", "--seed", "250", "run", "script.ts"]);
|
||||
assert_eq!(
|
||||
flags,
|
||||
DenoFlags {
|
||||
seed: Some(250 as u64),
|
||||
v8_flags: Some(svec!["deno", "--random-seed=250"]),
|
||||
..DenoFlags::default()
|
||||
}
|
||||
);
|
||||
assert_eq!(subcommand, DenoSubcommand::Run);
|
||||
assert_eq!(argv, svec!["deno", "script.ts"])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_flags_from_vec_29() {
|
||||
let (flags, subcommand, argv) = flags_from_vec(svec![
|
||||
"deno",
|
||||
"--seed",
|
||||
"250",
|
||||
"--v8-flags=--expose-gc",
|
||||
"run",
|
||||
"script.ts"
|
||||
]);
|
||||
assert_eq!(
|
||||
flags,
|
||||
DenoFlags {
|
||||
seed: Some(250 as u64),
|
||||
v8_flags: Some(svec!["deno", "--expose-gc", "--random-seed=250"]),
|
||||
..DenoFlags::default()
|
||||
}
|
||||
);
|
||||
assert_eq!(subcommand, DenoSubcommand::Run);
|
||||
assert_eq!(argv, svec!["deno", "script.ts"])
|
||||
}
|
||||
}
|
||||
|
|
11
cli/ops.rs
11
cli/ops.rs
|
@ -2211,10 +2211,17 @@ fn op_host_post_message(
|
|||
}
|
||||
|
||||
fn op_get_random_values(
|
||||
_state: &ThreadSafeState,
|
||||
state: &ThreadSafeState,
|
||||
_base: &msg::Base<'_>,
|
||||
data: Option<PinnedBuf>,
|
||||
) -> Box<OpWithError> {
|
||||
thread_rng().fill(&mut data.unwrap()[..]);
|
||||
if let Some(ref seeded_rng) = state.seeded_rng {
|
||||
let mut rng = seeded_rng.lock().unwrap();
|
||||
rng.fill(&mut data.unwrap()[..]);
|
||||
} else {
|
||||
let mut rng = thread_rng();
|
||||
rng.fill(&mut data.unwrap()[..]);
|
||||
}
|
||||
|
||||
Box::new(ok_future(empty_buf()))
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ use deno::PinnedBuf;
|
|||
use futures::future::Either;
|
||||
use futures::future::Shared;
|
||||
use futures::Future;
|
||||
use rand::rngs::StdRng;
|
||||
use rand::SeedableRng;
|
||||
use std;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
|
@ -82,6 +84,7 @@ pub struct State {
|
|||
pub dispatch_selector: ops::OpSelector,
|
||||
/// Reference to global progress bar.
|
||||
pub progress: Progress,
|
||||
pub seeded_rng: Option<Mutex<StdRng>>,
|
||||
|
||||
/// Set of all URLs that have been compiled. This is a hacky way to work
|
||||
/// around the fact that --reload will force multiple compilations of the same
|
||||
|
@ -295,6 +298,11 @@ impl ThreadSafeState {
|
|||
}
|
||||
}
|
||||
|
||||
let mut seeded_rng = None;
|
||||
if let Some(seed) = flags.seed {
|
||||
seeded_rng = Some(Mutex::new(StdRng::seed_from_u64(seed)));
|
||||
};
|
||||
|
||||
ThreadSafeState(Arc::new(State {
|
||||
main_module,
|
||||
dir,
|
||||
|
@ -312,6 +320,7 @@ impl ThreadSafeState {
|
|||
resource,
|
||||
dispatch_selector,
|
||||
progress,
|
||||
seeded_rng,
|
||||
compiled: Mutex::new(HashSet::new()),
|
||||
}))
|
||||
}
|
||||
|
|
11
tests/seed_random.js
Normal file
11
tests/seed_random.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
for (let i = 0; i < 10; ++i) {
|
||||
console.log(Math.random());
|
||||
}
|
||||
|
||||
const arr = new Uint8Array(32);
|
||||
|
||||
crypto.getRandomValues(arr);
|
||||
console.log(arr);
|
||||
|
||||
crypto.getRandomValues(arr);
|
||||
console.log(arr);
|
12
tests/seed_random.js.out
Normal file
12
tests/seed_random.js.out
Normal file
|
@ -0,0 +1,12 @@
|
|||
0.858562739044346
|
||||
0.8973397944553141
|
||||
0.15335012655691727
|
||||
0.36867387434349963
|
||||
0.3591039342838782
|
||||
0.7044499748617652
|
||||
0.7461423057751548
|
||||
0.3824611207183364
|
||||
0.5950178237266042
|
||||
0.22440633214343908
|
||||
Uint8Array [ 31, 147, 233, 143, 64, 159, 189, 114, 137, 153, 196, 156, 133, 210, 78, 4, 125, 255, 147, 234, 169, 149, 228, 46, 166, 246, 137, 49, 50, 182, 106, 219 ]
|
||||
Uint8Array [ 220, 209, 104, 94, 239, 165, 8, 254, 123, 163, 160, 177, 229, 105, 171, 232, 236, 71, 107, 28, 132, 143, 113, 44, 86, 251, 159, 102, 20, 119, 174, 230 ]
|
2
tests/seed_random.test
Normal file
2
tests/seed_random.test
Normal file
|
@ -0,0 +1,2 @@
|
|||
args: run --seed=100 tests/seed_random.js
|
||||
output: tests/seed_random.js.out
|
|
@ -635,6 +635,7 @@ OPTIONS:
|
|||
--allow-write=<allow-write> Allow file system write access
|
||||
-c, --config <FILE> Load compiler configuration file
|
||||
--importmap <FILE> Load import map file
|
||||
--seed <NUMBER> Seed Math.random() and crypto.getRandomValues()
|
||||
--v8-flags=<v8-flags> Set V8 command line options
|
||||
|
||||
SUBCOMMANDS:
|
||||
|
|
Loading…
Reference in a new issue