summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/flags.rs68
-rw-r--r--cli/ops.rs11
-rw-r--r--cli/state.rs9
-rw-r--r--tests/seed_random.js11
-rw-r--r--tests/seed_random.js.out12
-rw-r--r--tests/seed_random.test2
-rw-r--r--website/manual.md1
7 files changed, 112 insertions, 2 deletions
diff --git a/cli/flags.rs b/cli/flags.rs
index 9f37fb184..fa86df594 100644
--- a/cli/flags.rs
+++ b/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>,
@@ -146,6 +147,19 @@ To get help on the another subcommands (run in this case):
.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")
.help("Print V8 command line 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"])
+ }
}
diff --git a/cli/ops.rs b/cli/ops.rs
index f39daaab6..61f29ac9f 100644
--- a/cli/ops.rs
+++ b/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()))
}
diff --git a/cli/state.rs b/cli/state.rs
index 4a2db65c2..255a88144 100644
--- a/cli/state.rs
+++ b/cli/state.rs
@@ -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()),
}))
}
diff --git a/tests/seed_random.js b/tests/seed_random.js
new file mode 100644
index 000000000..7f6e336df
--- /dev/null
+++ b/tests/seed_random.js
@@ -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);
diff --git a/tests/seed_random.js.out b/tests/seed_random.js.out
new file mode 100644
index 000000000..06993cb1f
--- /dev/null
+++ b/tests/seed_random.js.out
@@ -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 ]
diff --git a/tests/seed_random.test b/tests/seed_random.test
new file mode 100644
index 000000000..20a3b3c8e
--- /dev/null
+++ b/tests/seed_random.test
@@ -0,0 +1,2 @@
+args: run --seed=100 tests/seed_random.js
+output: tests/seed_random.js.out
diff --git a/website/manual.md b/website/manual.md
index 684d44c2e..8b3d37521 100644
--- a/website/manual.md
+++ b/website/manual.md
@@ -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: