summaryrefslogtreecommitdiff
path: root/cli/ops/runtime_compiler.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/ops/runtime_compiler.rs')
-rw-r--r--cli/ops/runtime_compiler.rs153
1 files changed, 55 insertions, 98 deletions
diff --git a/cli/ops/runtime_compiler.rs b/cli/ops/runtime_compiler.rs
index bb3e47226..774b280ba 100644
--- a/cli/ops/runtime_compiler.rs
+++ b/cli/ops/runtime_compiler.rs
@@ -1,8 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-use crate::ast;
-use crate::colors;
-use crate::media_type::MediaType;
+use crate::import_map::ImportMap;
use crate::module_graph::BundleType;
use crate::module_graph::EmitOptions;
use crate::module_graph::GraphBuilder;
@@ -10,11 +8,10 @@ use crate::program_state::ProgramState;
use crate::specifier_handler::FetchHandler;
use crate::specifier_handler::MemoryHandler;
use crate::specifier_handler::SpecifierHandler;
-use crate::tsc_config;
+use deno_core::error::generic_error;
use deno_core::error::AnyError;
use deno_core::error::Context;
-use deno_core::serde::Serialize;
use deno_core::serde_json;
use deno_core::serde_json::json;
use deno_core::serde_json::Value;
@@ -30,37 +27,46 @@ use std::sync::Arc;
use std::sync::Mutex;
pub fn init(rt: &mut deno_core::JsRuntime) {
- super::reg_json_async(rt, "op_compile", op_compile);
- super::reg_json_async(rt, "op_transpile", op_transpile);
+ super::reg_json_async(rt, "op_emit", op_emit);
}
-#[derive(Deserialize, Debug)]
+#[derive(Debug, Deserialize)]
+enum RuntimeBundleType {
+ #[serde(rename = "esm")]
+ Esm,
+}
+
+#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
-struct CompileArgs {
- root_name: String,
+struct EmitArgs {
+ bundle: Option<RuntimeBundleType>,
+ check: Option<bool>,
+ compiler_options: Option<HashMap<String, Value>>,
+ import_map: Option<Value>,
+ import_map_path: Option<String>,
+ root_specifier: String,
sources: Option<HashMap<String, String>>,
- bundle: bool,
- options: Option<String>,
}
-async fn op_compile(
+async fn op_emit(
state: Rc<RefCell<OpState>>,
args: Value,
_data: BufVec,
) -> Result<Value, AnyError> {
- let args: CompileArgs = serde_json::from_value(args)?;
- if args.bundle {
- deno_runtime::ops::check_unstable2(&state, "Deno.bundle");
- } else {
- deno_runtime::ops::check_unstable2(&state, "Deno.compile");
- }
+ deno_runtime::ops::check_unstable2(&state, "Deno.emit");
+ let args: EmitArgs = serde_json::from_value(args)?;
let program_state = state.borrow().borrow::<Arc<ProgramState>>().clone();
let runtime_permissions = {
let state = state.borrow();
state.borrow::<Permissions>().clone()
};
+ // when we are actually resolving modules without provided sources, we should
+ // treat the root module as a dynamic import so that runtime permissions are
+ // applied.
+ let mut is_dynamic = false;
let handler: Arc<Mutex<dyn SpecifierHandler>> =
if let Some(sources) = args.sources {
+ is_dynamic = true;
Arc::new(Mutex::new(MemoryHandler::new(sources)))
} else {
Arc::new(Mutex::new(FetchHandler::new(
@@ -68,93 +74,44 @@ async fn op_compile(
runtime_permissions,
)?))
};
- let mut builder = GraphBuilder::new(handler, None, None);
- let specifier = ModuleSpecifier::resolve_url_or_path(&args.root_name)
- .context("The root specifier is invalid.")?;
- builder.add(&specifier, false).await?;
- let graph = builder.get_graph();
- let bundle_type = if args.bundle {
- BundleType::Esm
+ let maybe_import_map = if let Some(import_map_str) = args.import_map_path {
+ let import_map_specifier =
+ ModuleSpecifier::resolve_url_or_path(&import_map_str).context(
+ format!("Bad file path (\"{}\") for import map.", import_map_str),
+ )?;
+ let import_map_url = import_map_specifier.as_url();
+ let import_map = if let Some(value) = args.import_map {
+ ImportMap::from_json(&import_map_url.to_string(), &value.to_string())?
+ } else {
+ ImportMap::load(&import_map_str)?
+ };
+ Some(import_map)
+ } else if args.import_map.is_some() {
+ return Err(generic_error("An importMap was specified, but no importMapPath was provided, which is required."));
} else {
- BundleType::None
+ None
+ };
+ let mut builder = GraphBuilder::new(handler, maybe_import_map, None);
+ let root_specifier =
+ ModuleSpecifier::resolve_url_or_path(&args.root_specifier)?;
+ builder.add(&root_specifier, is_dynamic).await?;
+ let bundle_type = match args.bundle {
+ Some(RuntimeBundleType::Esm) => BundleType::Esm,
+ _ => BundleType::None,
};
+ let graph = builder.get_graph();
let debug = program_state.flags.log_level == Some(log::Level::Debug);
- let maybe_user_config: Option<HashMap<String, Value>> =
- if let Some(options) = args.options {
- Some(serde_json::from_str(&options)?)
- } else {
- None
- };
- let (emitted_files, result_info) = graph.emit(EmitOptions {
+ let (files, result_info) = graph.emit(EmitOptions {
bundle_type,
+ check: args.check.unwrap_or(true),
debug,
- maybe_user_config,
+ maybe_user_config: args.compiler_options,
})?;
Ok(json!({
- "emittedFiles": emitted_files,
"diagnostics": result_info.diagnostics,
+ "files": files,
+ "ignoredOptions": result_info.maybe_ignored_options,
+ "stats": result_info.stats,
}))
}
-
-#[derive(Deserialize, Debug)]
-struct TranspileArgs {
- sources: HashMap<String, String>,
- options: Option<String>,
-}
-
-#[derive(Debug, Serialize)]
-struct RuntimeTranspileEmit {
- source: String,
- map: Option<String>,
-}
-
-async fn op_transpile(
- state: Rc<RefCell<OpState>>,
- args: Value,
- _data: BufVec,
-) -> Result<Value, AnyError> {
- deno_runtime::ops::check_unstable2(&state, "Deno.transpileOnly");
- let args: TranspileArgs = serde_json::from_value(args)?;
-
- let mut compiler_options = tsc_config::TsConfig::new(json!({
- "checkJs": true,
- "emitDecoratorMetadata": false,
- "jsx": "react",
- "jsxFactory": "React.createElement",
- "jsxFragmentFactory": "React.Fragment",
- "inlineSourceMap": false,
- }));
-
- let user_options: HashMap<String, Value> = if let Some(options) = args.options
- {
- serde_json::from_str(&options)?
- } else {
- HashMap::new()
- };
- let maybe_ignored_options =
- compiler_options.merge_user_config(&user_options)?;
- // TODO(@kitsonk) these really should just be passed back to the caller
- if let Some(ignored_options) = maybe_ignored_options {
- info!("{}: {}", colors::yellow("warning"), ignored_options);
- }
-
- let emit_options: ast::EmitOptions = compiler_options.into();
- let mut emit_map = HashMap::new();
-
- for (specifier, source) in args.sources {
- let media_type = MediaType::from(&specifier);
- let parsed_module = ast::parse(&specifier, &source, &media_type)?;
- let (source, maybe_source_map) = parsed_module.transpile(&emit_options)?;
-
- emit_map.insert(
- specifier.to_string(),
- RuntimeTranspileEmit {
- source,
- map: maybe_source_map,
- },
- );
- }
- let result = serde_json::to_value(emit_map)?;
- Ok(result)
-}