mirror of
https://github.com/denoland/deno.git
synced 2024-11-28 16:20:57 -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 allow_hrtime: bool,
|
||||||
pub no_prompts: bool,
|
pub no_prompts: bool,
|
||||||
pub no_fetch: bool,
|
pub no_fetch: bool,
|
||||||
|
pub seed: Option<u64>,
|
||||||
pub v8_flags: Option<Vec<String>>,
|
pub v8_flags: Option<Vec<String>>,
|
||||||
pub xeval_replvar: Option<String>,
|
pub xeval_replvar: Option<String>,
|
||||||
pub xeval_delim: 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")
|
.help("Load compiler configuration file")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.global(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(
|
||||||
Arg::with_name("v8-options")
|
Arg::with_name("v8-options")
|
||||||
.long("v8-options")
|
.long("v8-options")
|
||||||
|
@ -379,6 +393,22 @@ pub fn parse_flags(matches: &ArgMatches) -> DenoFlags {
|
||||||
v8_flags.insert(0, "deno".to_string());
|
v8_flags.insert(0, "deno".to_string());
|
||||||
flags.v8_flags = Some(v8_flags);
|
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 = parse_run_args(flags, matches);
|
||||||
// flags specific to "run" subcommand
|
// flags specific to "run" subcommand
|
||||||
|
@ -1112,4 +1142,42 @@ mod tests {
|
||||||
assert_eq!(subcommand, DenoSubcommand::Run);
|
assert_eq!(subcommand, DenoSubcommand::Run);
|
||||||
assert_eq!(argv, svec!["deno", "script.ts"]);
|
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(
|
fn op_get_random_values(
|
||||||
_state: &ThreadSafeState,
|
state: &ThreadSafeState,
|
||||||
_base: &msg::Base<'_>,
|
_base: &msg::Base<'_>,
|
||||||
data: Option<PinnedBuf>,
|
data: Option<PinnedBuf>,
|
||||||
) -> Box<OpWithError> {
|
) -> 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()))
|
Box::new(ok_future(empty_buf()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@ use deno::PinnedBuf;
|
||||||
use futures::future::Either;
|
use futures::future::Either;
|
||||||
use futures::future::Shared;
|
use futures::future::Shared;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
|
use rand::rngs::StdRng;
|
||||||
|
use rand::SeedableRng;
|
||||||
use std;
|
use std;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
@ -82,6 +84,7 @@ pub struct State {
|
||||||
pub dispatch_selector: ops::OpSelector,
|
pub dispatch_selector: ops::OpSelector,
|
||||||
/// Reference to global progress bar.
|
/// Reference to global progress bar.
|
||||||
pub progress: Progress,
|
pub progress: Progress,
|
||||||
|
pub seeded_rng: Option<Mutex<StdRng>>,
|
||||||
|
|
||||||
/// Set of all URLs that have been compiled. This is a hacky way to work
|
/// 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
|
/// 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 {
|
ThreadSafeState(Arc::new(State {
|
||||||
main_module,
|
main_module,
|
||||||
dir,
|
dir,
|
||||||
|
@ -312,6 +320,7 @@ impl ThreadSafeState {
|
||||||
resource,
|
resource,
|
||||||
dispatch_selector,
|
dispatch_selector,
|
||||||
progress,
|
progress,
|
||||||
|
seeded_rng,
|
||||||
compiled: Mutex::new(HashSet::new()),
|
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
|
--allow-write=<allow-write> Allow file system write access
|
||||||
-c, --config <FILE> Load compiler configuration file
|
-c, --config <FILE> Load compiler configuration file
|
||||||
--importmap <FILE> Load import map file
|
--importmap <FILE> Load import map file
|
||||||
|
--seed <NUMBER> Seed Math.random() and crypto.getRandomValues()
|
||||||
--v8-flags=<v8-flags> Set V8 command line options
|
--v8-flags=<v8-flags> Set V8 command line options
|
||||||
|
|
||||||
SUBCOMMANDS:
|
SUBCOMMANDS:
|
||||||
|
|
Loading…
Reference in a new issue