summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
Diffstat (limited to 'cli')
-rw-r--r--cli/compiler.rs102
-rw-r--r--cli/flags.rs33
-rw-r--r--cli/main.rs22
-rw-r--r--cli/state.rs8
-rw-r--r--cli/worker.rs5
5 files changed, 162 insertions, 8 deletions
diff --git a/cli/compiler.rs b/cli/compiler.rs
index 3a036a627..4233262a3 100644
--- a/cli/compiler.rs
+++ b/cli/compiler.rs
@@ -50,16 +50,22 @@ impl ModuleMetaData {
type CompilerConfig = Option<(String, Vec<u8>)>;
/// Creates the JSON message send to compiler.ts's onmessage.
-fn req(root_names: Vec<String>, compiler_config: CompilerConfig) -> Buf {
+fn req(
+ root_names: Vec<String>,
+ compiler_config: CompilerConfig,
+ bundle: Option<String>,
+) -> Buf {
let j = if let Some((config_path, config_data)) = compiler_config {
json!({
"rootNames": root_names,
+ "bundle": bundle,
"configPath": config_path,
"config": str::from_utf8(&config_data).unwrap(),
})
} else {
json!({
"rootNames": root_names,
+ "bundle": bundle,
})
};
j.to_string().into_boxed_str().into_boxed_bytes()
@@ -82,6 +88,67 @@ pub fn get_compiler_config(
}
}
+pub fn bundle_async(
+ state: ThreadSafeState,
+ module_name: String,
+ out_file: String,
+) -> impl Future<Item = (), Error = Diagnostic> {
+ debug!(
+ "Invoking the compiler to bundle. module_name: {}",
+ module_name
+ );
+
+ let root_names = vec![module_name.clone()];
+ let compiler_config = get_compiler_config(&state, "typescript");
+ let req_msg = req(root_names, compiler_config, Some(out_file));
+
+ // Count how many times we start the compiler worker.
+ state.metrics.compiler_starts.fetch_add(1, Ordering::SeqCst);
+
+ let mut worker = Worker::new(
+ "TS".to_string(),
+ startup_data::compiler_isolate_init(),
+ // TODO(ry) Maybe we should use a separate state for the compiler.
+ // as was done previously.
+ state.clone(),
+ );
+ js_check(worker.execute("denoMain()"));
+ js_check(worker.execute("workerMain()"));
+ js_check(worker.execute("compilerMain()"));
+
+ let resource = worker.state.resource.clone();
+ let compiler_rid = resource.rid;
+ let first_msg_fut = resources::post_message_to_worker(compiler_rid, req_msg)
+ .then(move |_| worker)
+ .then(move |result| {
+ if let Err(err) = result {
+ // TODO(ry) Need to forward the error instead of exiting.
+ eprintln!("{}", err.to_string());
+ std::process::exit(1);
+ }
+ debug!("Sent message to worker");
+ let stream_future =
+ resources::get_message_stream_from_worker(compiler_rid).into_future();
+ stream_future.map(|(f, _rest)| f).map_err(|(f, _rest)| f)
+ });
+
+ first_msg_fut.map_err(|_| panic!("not handled")).and_then(
+ move |maybe_msg: Option<Buf>| {
+ debug!("Received message from worker");
+
+ if let Some(msg) = maybe_msg {
+ let json_str = std::str::from_utf8(&msg).unwrap();
+ debug!("Message: {}", json_str);
+ if let Some(diagnostics) = Diagnostic::from_emit_result(json_str) {
+ return Err(diagnostics);
+ }
+ }
+
+ Ok(())
+ },
+ )
+}
+
pub fn compile_async(
state: ThreadSafeState,
module_meta_data: &ModuleMetaData,
@@ -95,7 +162,7 @@ pub fn compile_async(
let root_names = vec![module_name.clone()];
let compiler_config = get_compiler_config(&state, "typescript");
- let req_msg = req(root_names, compiler_config);
+ let req_msg = req(root_names, compiler_config, None);
// Count how many times we start the compiler worker.
state.metrics.compiler_starts.fetch_add(1, Ordering::SeqCst);
@@ -197,7 +264,13 @@ mod tests {
maybe_source_map: None,
};
- out = compile_sync(ThreadSafeState::mock(), &out).unwrap();
+ out = compile_sync(
+ ThreadSafeState::mock(vec![
+ String::from("./deno"),
+ String::from("hello.js"),
+ ]),
+ &out,
+ ).unwrap();
assert!(
out
.maybe_output_code
@@ -210,8 +283,29 @@ mod tests {
#[test]
fn test_get_compiler_config_no_flag() {
let compiler_type = "typescript";
- let state = ThreadSafeState::mock();
+ let state = ThreadSafeState::mock(vec![
+ String::from("./deno"),
+ String::from("hello.js"),
+ ]);
let out = get_compiler_config(&state, compiler_type);
assert_eq!(out, None);
}
+
+ #[test]
+ fn test_bundle_async() {
+ let specifier = "./tests/002_hello.ts";
+ use crate::worker;
+ let module_name = worker::root_specifier_to_url(specifier)
+ .unwrap()
+ .to_string();
+
+ let state = ThreadSafeState::mock(vec![
+ String::from("./deno"),
+ String::from("./tests/002_hello.ts"),
+ String::from("$deno$/bundle.js"),
+ ]);
+ let out =
+ bundle_async(state, module_name, String::from("$deno$/bundle.js"));
+ assert_eq!(tokio_util::block_on(out), Ok(()));
+ }
}
diff --git a/cli/flags.rs b/cli/flags.rs
index a7245eba1..b9a298d28 100644
--- a/cli/flags.rs
+++ b/cli/flags.rs
@@ -155,6 +155,16 @@ Includes versions of Deno, V8 JavaScript Engine, and the TypeScript
compiler.",
),
).subcommand(
+ SubCommand::with_name("bundle")
+ .setting(AppSettings::DisableVersion)
+ .about("Bundle module and dependnecies into single file")
+ .long_about(
+ "Fetch, compile, and output to a single file a module and its dependencies.
+"
+ )
+ .arg(Arg::with_name("source_file").takes_value(true).required(true))
+ .arg(Arg::with_name("out_file").takes_value(true).required(true)),
+ ).subcommand(
SubCommand::with_name("fetch")
.setting(AppSettings::DisableVersion)
.about("Fetch the dependencies")
@@ -436,6 +446,7 @@ const PRETTIER_URL: &str = "https://deno.land/std@v0.7.0/prettier/main.ts";
/// There is no "Help" subcommand because it's handled by `clap::App` itself.
#[derive(Debug, PartialEq)]
pub enum DenoSubcommand {
+ Bundle,
Eval,
Fetch,
Info,
@@ -455,6 +466,13 @@ pub fn flags_from_vec(
let mut flags = parse_flags(&matches.clone());
let subcommand = match matches.subcommand() {
+ ("bundle", Some(bundle_match)) => {
+ flags.allow_write = true;
+ let source_file: &str = bundle_match.value_of("source_file").unwrap();
+ let out_file: &str = bundle_match.value_of("out_file").unwrap();
+ argv.extend(vec![source_file.to_string(), out_file.to_string()]);
+ DenoSubcommand::Bundle
+ }
("eval", Some(eval_match)) => {
flags.allow_net = true;
flags.allow_env = true;
@@ -1034,4 +1052,19 @@ mod tests {
assert_eq!(subcommand, DenoSubcommand::Run);
assert_eq!(argv, svec!["deno", "script.ts"]);
}
+
+ #[test]
+ fn test_flags_from_vec_26() {
+ let (flags, subcommand, argv) =
+ flags_from_vec(svec!["deno", "bundle", "source.ts", "bundle.js"]);
+ assert_eq!(
+ flags,
+ DenoFlags {
+ allow_write: true,
+ ..DenoFlags::default()
+ }
+ );
+ assert_eq!(subcommand, DenoSubcommand::Bundle);
+ assert_eq!(argv, svec!["deno", "source.ts", "bundle.js"])
+ }
}
diff --git a/cli/main.rs b/cli/main.rs
index cfce2254b..ad0374af2 100644
--- a/cli/main.rs
+++ b/cli/main.rs
@@ -41,6 +41,7 @@ mod tokio_write;
pub mod version;
pub mod worker;
+use crate::compiler::bundle_async;
use crate::errors::RustOrJsError;
use crate::progress::Progress;
use crate::state::ThreadSafeState;
@@ -261,6 +262,26 @@ fn xeval_command(flags: DenoFlags, argv: Vec<String>) {
tokio_util::run(main_future);
}
+fn bundle_command(flags: DenoFlags, argv: Vec<String>) {
+ let (mut _worker, state) = create_worker_and_state(flags, argv);
+
+ let main_module = state.main_module().unwrap();
+ let main_url = root_specifier_to_url(&main_module).unwrap();
+ assert!(state.argv.len() >= 3);
+ let out_file = state.argv[2].clone();
+ debug!(">>>>> bundle_async START");
+ let bundle_future = bundle_async(state, main_url.to_string(), out_file)
+ .map_err(|e| {
+ debug!("diagnostics returned, exiting!");
+ eprintln!("\n{}", e.to_string());
+ std::process::exit(1);
+ }).and_then(move |_| {
+ debug!(">>>>> bundle_async END");
+ Ok(())
+ });
+ tokio_util::run(bundle_future);
+}
+
fn run_repl(flags: DenoFlags, argv: Vec<String>) {
let (mut worker, _state) = create_worker_and_state(flags, argv);
@@ -322,6 +343,7 @@ fn main() {
});
match subcommand {
+ DenoSubcommand::Bundle => bundle_command(flags, argv),
DenoSubcommand::Eval => eval_command(flags, argv),
DenoSubcommand::Fetch => fetch_or_info_command(flags, argv, false),
DenoSubcommand::Info => fetch_or_info_command(flags, argv, true),
diff --git a/cli/state.rs b/cli/state.rs
index d7681fc79..9a8b1cab2 100644
--- a/cli/state.rs
+++ b/cli/state.rs
@@ -311,8 +311,7 @@ impl ThreadSafeState {
}
#[cfg(test)]
- pub fn mock() -> ThreadSafeState {
- let argv = vec![String::from("./deno"), String::from("hello.js")];
+ pub fn mock(argv: Vec<String>) -> ThreadSafeState {
ThreadSafeState::new(
flags::DenoFlags::default(),
argv,
@@ -349,5 +348,8 @@ impl ThreadSafeState {
#[test]
fn thread_safe() {
fn f<S: Send + Sync>(_: S) {}
- f(ThreadSafeState::mock());
+ f(ThreadSafeState::mock(vec![
+ String::from("./deno"),
+ String::from("hello.js"),
+ ]));
}
diff --git a/cli/worker.rs b/cli/worker.rs
index f95826674..99470c2a7 100644
--- a/cli/worker.rs
+++ b/cli/worker.rs
@@ -280,7 +280,10 @@ mod tests {
}
fn create_test_worker() -> Worker {
- let state = ThreadSafeState::mock();
+ let state = ThreadSafeState::mock(vec![
+ String::from("./deno"),
+ String::from("hello.js"),
+ ]);
let mut worker =
Worker::new("TEST".to_string(), startup_data::deno_isolate_init(), state);
js_check(worker.execute("denoMain()"));