summaryrefslogtreecommitdiff
path: root/cli/ops/runtime_compiler.rs
diff options
context:
space:
mode:
authorKitson Kelly <me@kitsonkelly.com>2021-10-11 08:26:22 +1100
committerGitHub <noreply@github.com>2021-10-11 08:26:22 +1100
commita7baf5f2bbb50dc0cb571de141b800b9155faca7 (patch)
tree4bebaabd1d3ed4595e8a388e0fae559bb5558974 /cli/ops/runtime_compiler.rs
parent5a8a989b7815023f33a1e3183a55cc8999af5d98 (diff)
refactor: integrate deno_graph into CLI (#12369)
Diffstat (limited to 'cli/ops/runtime_compiler.rs')
-rw-r--r--cli/ops/runtime_compiler.rs213
1 files changed, 160 insertions, 53 deletions
diff --git a/cli/ops/runtime_compiler.rs b/cli/ops/runtime_compiler.rs
index d63d97f58..ab6992d19 100644
--- a/cli/ops/runtime_compiler.rs
+++ b/cli/ops/runtime_compiler.rs
@@ -1,27 +1,30 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-use crate::module_graph::BundleType;
-use crate::module_graph::EmitOptions;
-use crate::module_graph::GraphBuilder;
+use crate::cache;
+use crate::config_file::IgnoredCompilerOptions;
+use crate::diagnostics::Diagnostics;
+use crate::emit;
+use crate::errors::get_error_class_name;
use crate::proc_state::ProcState;
-use crate::specifier_handler::FetchHandler;
-use crate::specifier_handler::MemoryHandler;
-use crate::specifier_handler::SpecifierHandler;
+use crate::resolver::ImportMapResolver;
+use deno_core::error::custom_error;
use deno_core::error::generic_error;
-use deno_core::error::type_error;
use deno_core::error::AnyError;
use deno_core::error::Context;
-use deno_core::parking_lot::Mutex;
use deno_core::resolve_url_or_path;
+use deno_core::serde_json;
use deno_core::serde_json::Value;
+use deno_core::ModuleSpecifier;
use deno_core::OpState;
+use deno_graph;
use deno_runtime::permissions::Permissions;
use import_map::ImportMap;
use serde::Deserialize;
use serde::Serialize;
use std::cell::RefCell;
use std::collections::HashMap;
+use std::collections::HashSet;
use std::rc::Rc;
use std::sync::Arc;
@@ -37,6 +40,15 @@ enum RuntimeBundleType {
Classic,
}
+impl<'a> From<&'a RuntimeBundleType> for emit::BundleType {
+ fn from(bundle_type: &'a RuntimeBundleType) -> Self {
+ match bundle_type {
+ RuntimeBundleType::Classic => Self::Classic,
+ RuntimeBundleType::Module => Self::Module,
+ }
+ }
+}
+
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct EmitArgs {
@@ -52,10 +64,21 @@ struct EmitArgs {
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct EmitResult {
- diagnostics: crate::diagnostics::Diagnostics,
+ diagnostics: Diagnostics,
files: HashMap<String, String>,
- ignored_options: Option<crate::config_file::IgnoredCompilerOptions>,
- stats: crate::module_graph::Stats,
+ #[serde(rename = "ignoredOptions")]
+ maybe_ignored_options: Option<IgnoredCompilerOptions>,
+ stats: emit::Stats,
+}
+
+fn to_maybe_imports(
+ referrer: &ModuleSpecifier,
+ maybe_options: Option<&HashMap<String, Value>>,
+) -> Option<Vec<(ModuleSpecifier, Vec<String>)>> {
+ let options = maybe_options.as_ref()?;
+ let types_value = options.get("types")?;
+ let types: Vec<String> = serde_json::from_value(types_value.clone()).ok()?;
+ Some(vec![(referrer.clone(), types)])
}
async fn op_emit(
@@ -65,23 +88,19 @@ async fn op_emit(
) -> Result<EmitResult, AnyError> {
deno_runtime::ops::check_unstable2(&state, "Deno.emit");
let root_specifier = args.root_specifier;
- let ps = state.borrow().borrow::<ProcState>().clone();
- let mut 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 handler: Arc<Mutex<dyn SpecifierHandler>> =
- if let Some(sources) = args.sources {
- Arc::new(Mutex::new(MemoryHandler::new(sources)))
+ let state = state.borrow();
+ let ps = state.borrow::<ProcState>();
+ let mut runtime_permissions = { state.borrow::<Permissions>().clone() };
+ let mut cache: Box<dyn cache::CacherLoader> =
+ if let Some(sources) = &args.sources {
+ Box::new(cache::MemoryCacher::new(sources.clone()))
} else {
- Arc::new(Mutex::new(FetchHandler::new(
- &ps,
+ Box::new(cache::FetchCacher::new(
+ ps.dir.gen_cache.clone(),
+ ps.file_fetcher.clone(),
runtime_permissions.clone(),
runtime_permissions.clone(),
- )?))
+ ))
};
let maybe_import_map = if let Some(import_map_str) = args.import_map_path {
let import_map_specifier = resolve_url_or_path(&import_map_str)
@@ -107,37 +126,125 @@ async fn op_emit(
} else {
None
};
- let mut builder = GraphBuilder::new(handler, maybe_import_map, None);
- let root_specifier = resolve_url_or_path(&root_specifier)?;
- builder.add(&root_specifier, false).await.map_err(|_| {
- type_error(format!(
- "Unable to handle the given specifier: {}",
- &root_specifier
- ))
- })?;
- builder
- .analyze_compiler_options(&args.compiler_options)
- .await?;
- let bundle_type = match args.bundle {
- Some(RuntimeBundleType::Module) => BundleType::Module,
- Some(RuntimeBundleType::Classic) => BundleType::Classic,
- None => BundleType::None,
- };
- let graph = builder.get_graph();
+ let roots = vec![resolve_url_or_path(&root_specifier)?];
+ let maybe_imports =
+ to_maybe_imports(&roots[0], args.compiler_options.as_ref());
+ let maybe_resolver = maybe_import_map.as_ref().map(ImportMapResolver::new);
+ let graph = Arc::new(
+ deno_graph::create_graph(
+ roots,
+ true,
+ maybe_imports,
+ cache.as_mut_loader(),
+ maybe_resolver.as_ref().map(|r| r.as_resolver()),
+ None,
+ None,
+ )
+ .await,
+ );
+ // There are certain graph errors that we want to return as an error of an op,
+ // versus something that gets returned as a diagnostic of the op, this is
+ // handled here.
+ if let Err(err) = graph.valid() {
+ let err: AnyError = err.into();
+ if get_error_class_name(&err) == "PermissionDenied" {
+ return Err(err);
+ }
+ }
+ let check = args.check.unwrap_or(true);
let debug = ps.flags.log_level == Some(log::Level::Debug);
- let graph_errors = graph.get_errors();
- let (files, mut result_info) = graph.emit(EmitOptions {
- bundle_type,
- check: args.check.unwrap_or(true),
- debug,
- maybe_user_config: args.compiler_options,
- })?;
- result_info.diagnostics.extend_graph_errors(graph_errors);
+ let tsc_emit = check && args.bundle.is_none();
+ let (ts_config, maybe_ignored_options) = emit::get_ts_config(
+ emit::ConfigType::RuntimeEmit { tsc_emit },
+ None,
+ args.compiler_options.as_ref(),
+ )?;
+ let (files, mut diagnostics, stats) = if check && args.bundle.is_none() {
+ let (diagnostics, stats) = if args.sources.is_none()
+ && emit::valid_emit(
+ graph.as_ref(),
+ cache.as_cacher(),
+ &ts_config,
+ ps.flags.reload,
+ &HashSet::default(),
+ ) {
+ log::debug!(
+ "cache is valid for \"{}\", skipping check/emit",
+ root_specifier
+ );
+ (Diagnostics::default(), emit::Stats::default())
+ } else {
+ let emit_result = emit::check_and_maybe_emit(
+ graph.clone(),
+ cache.as_mut_cacher(),
+ emit::CheckOptions {
+ debug,
+ emit_with_diagnostics: true,
+ maybe_config_specifier: None,
+ ts_config,
+ },
+ )?;
+ (emit_result.diagnostics, emit_result.stats)
+ };
+ let files = emit::to_file_map(graph.as_ref(), cache.as_mut_cacher());
+ (files, diagnostics, stats)
+ } else if let Some(bundle) = &args.bundle {
+ let (diagnostics, stats) = if check {
+ if ts_config.get_declaration() {
+ return Err(custom_error("TypeError", "The bundle option is set, but the compiler option of `declaration` is true which is not currently supported."));
+ }
+ let emit_result = emit::check_and_maybe_emit(
+ graph.clone(),
+ cache.as_mut_cacher(),
+ emit::CheckOptions {
+ debug,
+ emit_with_diagnostics: true,
+ maybe_config_specifier: None,
+ ts_config: ts_config.clone(),
+ },
+ )?;
+ (emit_result.diagnostics, emit_result.stats)
+ } else {
+ (Diagnostics::default(), Default::default())
+ };
+ let (emit, maybe_map) = emit::bundle(
+ graph.as_ref(),
+ emit::BundleOptions {
+ bundle_type: bundle.into(),
+ ts_config,
+ },
+ )?;
+ let mut files = HashMap::new();
+ files.insert("deno:///bundle.js".to_string(), emit);
+ if let Some(map) = maybe_map {
+ files.insert("deno:///bundle.js.map".to_string(), map);
+ }
+ (files, diagnostics, stats)
+ } else {
+ if ts_config.get_declaration() {
+ return Err(custom_error("TypeError", "The option of `check` is false, but the compiler option of `declaration` is true which is not currently supported."));
+ }
+ let emit_result = emit::emit(
+ graph.as_ref(),
+ cache.as_mut_cacher(),
+ emit::EmitOptions {
+ reload: ps.flags.reload,
+ ts_config,
+ reload_exclusions: HashSet::default(),
+ },
+ )?;
+ let files = emit::to_file_map(graph.as_ref(), cache.as_mut_cacher());
+ (files, emit_result.diagnostics, emit_result.stats)
+ };
+
+ // we want to add any errors that were returned as an `Err` earlier by adding
+ // them to the diagnostics.
+ diagnostics.extend_graph_errors(graph.errors());
Ok(EmitResult {
- diagnostics: result_info.diagnostics,
+ diagnostics,
files,
- ignored_options: result_info.maybe_ignored_options,
- stats: result_info.stats,
+ maybe_ignored_options,
+ stats,
})
}