diff options
79 files changed, 12 insertions, 2355 deletions
diff --git a/cli/args/flags.rs b/cli/args/flags.rs index e80bf3a61..861cbb5fb 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -312,9 +312,6 @@ pub struct Flags { pub lock: Option<PathBuf>, pub log_level: Option<Level>, pub no_remote: bool, - /// If true, a list of Node built-in modules will be injected into - /// the import map. - pub compat: bool, pub no_prompt: bool, pub reload: bool, pub seed: Option<u64>, @@ -1869,7 +1866,6 @@ fn runtime_args( .arg(v8_flags_arg()) .arg(seed_arg()) .arg(enable_testing_features_arg()) - .arg(compat_arg()) } fn inspect_args(app: Command) -> Command { @@ -2009,21 +2005,6 @@ fn seed_arg<'a>() -> Arg<'a> { }) } -static COMPAT_HELP: Lazy<String> = Lazy::new(|| { - format!( - "See https://deno.land/manual@v{}/node/compatibility_mode", - SHORT_VERSION.as_str() - ) -}); - -fn compat_arg<'a>() -> Arg<'a> { - Arg::new("compat") - .long("compat") - .requires("unstable") - .help("UNSTABLE: Node compatibility mode.") - .long_help(COMPAT_HELP.as_str()) -} - fn watch_arg<'a>(takes_files: bool) -> Arg<'a> { let arg = Arg::new("watch") .long("watch") @@ -2916,7 +2897,6 @@ fn runtime_args_parse( location_arg_parse(flags, matches); v8_flags_arg_parse(flags, matches); seed_arg_parse(flags, matches); - compat_arg_parse(flags, matches); enable_testing_features_arg_parse(flags, matches); } @@ -3001,12 +2981,6 @@ fn seed_arg_parse(flags: &mut Flags, matches: &ArgMatches) { } } -fn compat_arg_parse(flags: &mut Flags, matches: &ArgMatches) { - if matches.is_present("compat") { - flags.compat = true; - } -} - fn no_check_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) { if let Some(cache_type) = matches.value_of("no-check") { match cache_type { @@ -5566,23 +5540,6 @@ mod tests { } #[test] - fn compat() { - let r = - flags_from_vec(svec!["deno", "run", "--compat", "--unstable", "foo.js"]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Run(RunFlags { - script: "foo.js".to_string(), - }), - compat: true, - unstable: true, - ..Flags::default() - } - ); - } - - #[test] fn test_config_path_args() { let flags = flags_from_vec(svec!["deno", "run", "foo.js"]).unwrap(); assert_eq!( diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 90fa5220b..261de6c87 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -35,7 +35,6 @@ use std::net::SocketAddr; use std::path::PathBuf; use crate::args::config_file::JsxImportSourceConfig; -use crate::compat; use crate::deno_dir::DenoDir; use crate::emit::get_ts_config_for_emit; use crate::emit::TsConfigType; @@ -230,9 +229,6 @@ impl CliOptions { imports.extend(config_imports); } } - if self.flags.compat { - imports.extend(compat::get_node_imports()); - } if imports.is_empty() { Ok(None) } else { @@ -277,10 +273,6 @@ impl CliOptions { .unwrap_or(false) } - pub fn compat(&self) -> bool { - self.flags.compat - } - pub fn coverage_dir(&self) -> Option<String> { fn allow_coverage(sub_command: &DenoSubcommand) -> bool { match sub_command { diff --git a/cli/compat/esm_resolver.rs b/cli/compat/esm_resolver.rs deleted file mode 100644 index 2a5da4fe1..000000000 --- a/cli/compat/esm_resolver.rs +++ /dev/null @@ -1,1288 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. - -use crate::node::errors; -use crate::resolver::ImportMapResolver; -use deno_core::error::generic_error; -use deno_core::error::AnyError; -use deno_core::serde_json; -use deno_core::serde_json::Map; -use deno_core::serde_json::Value; -use deno_core::url::Url; -use deno_core::ModuleSpecifier; -use deno_graph::source::ResolveResponse; -use deno_graph::source::Resolver; -use deno_runtime::deno_node::DEFAULT_CONDITIONS; -use regex::Regex; -use std::path::PathBuf; - -#[derive(Debug, Default)] -pub struct NodeEsmResolver { - maybe_import_map_resolver: Option<ImportMapResolver>, -} - -impl NodeEsmResolver { - pub fn new(maybe_import_map_resolver: Option<ImportMapResolver>) -> Self { - Self { - maybe_import_map_resolver, - } - } -} - -impl Resolver for NodeEsmResolver { - fn resolve( - &self, - specifier: &str, - referrer: &ModuleSpecifier, - ) -> ResolveResponse { - // First try to resolve using import map, ignoring any errors - if !specifier.starts_with("node:") { - if let Some(import_map_resolver) = &self.maybe_import_map_resolver { - let response = import_map_resolver.resolve(specifier, referrer); - if !matches!(response, ResolveResponse::Err(_)) { - return response; - } - } - } - - let current_dir = match std::env::current_dir() { - Ok(path) => path, - Err(err) => return ResolveResponse::Err(err.into()), - }; - let node_resolution = - node_resolve(specifier, referrer.as_str(), ¤t_dir); - - match node_resolution { - Ok(resolve_response) => { - // If node resolution succeeded, return the specifier - resolve_response - } - Err(err) => { - // If node resolution failed, check if it's because of unsupported - // URL scheme, and if so try to resolve using regular resolution algorithm - if err - .to_string() - .starts_with("[ERR_UNSUPPORTED_ESM_URL_SCHEME]") - { - return match deno_core::resolve_import(specifier, referrer.as_str()) { - Ok(specifier) => ResolveResponse::Esm(specifier), - Err(err) => ResolveResponse::Err(err.into()), - }; - } - - ResolveResponse::Err(err) - } - } - } -} - -/// This function is an implementation of `defaultResolve` in -/// `lib/internal/modules/esm/resolve.js` from Node. -fn node_resolve( - specifier: &str, - referrer: &str, - cwd: &std::path::Path, -) -> Result<ResolveResponse, AnyError> { - // TODO(bartlomieju): skipped "policy" part as we don't plan to support it - - if let Some(resolved) = crate::node::try_resolve_builtin_module(specifier) { - return Ok(ResolveResponse::Esm(resolved)); - } - - if let Ok(url) = Url::parse(specifier) { - if url.scheme() == "data" { - return Ok(ResolveResponse::Specifier(url)); - } - - let protocol = url.scheme(); - - if protocol == "node" { - let split_specifier = url.as_str().split(':'); - let specifier = split_specifier.skip(1).collect::<String>(); - if let Some(resolved) = - crate::node::try_resolve_builtin_module(&specifier) - { - return Ok(ResolveResponse::Esm(resolved)); - } else { - return Err(generic_error(format!("Unknown module {}", specifier))); - } - } - - if protocol != "file" && protocol != "data" { - return Err(errors::err_unsupported_esm_url_scheme(&url)); - } - - if referrer.starts_with("data:") { - let referrer_url = Url::parse(referrer)?; - let url = referrer_url.join(specifier).map_err(AnyError::from)?; - return Ok(ResolveResponse::Specifier(url)); - } - } - - let is_main = referrer.is_empty(); - let parent_url = if is_main { - Url::from_directory_path(cwd).unwrap() - } else { - Url::parse(referrer).expect("referrer was not proper url") - }; - - let conditions = DEFAULT_CONDITIONS; - let url = module_resolve(specifier, &parent_url, conditions)?; - - let resolve_response = if url.as_str().starts_with("http") { - ResolveResponse::Esm(url) - } else if url.as_str().ends_with(".js") { - let package_config = get_package_scope_config(&url)?; - if package_config.typ == "module" { - ResolveResponse::Esm(url) - } else { - ResolveResponse::CommonJs(url) - } - } else if url.as_str().ends_with(".cjs") { - ResolveResponse::CommonJs(url) - } else { - ResolveResponse::Esm(url) - }; - // TODO(bartlomieju): skipped checking errors for commonJS resolution and - // "preserveSymlinksMain"/"preserveSymlinks" options. - Ok(resolve_response) -} - -fn to_file_path(url: &ModuleSpecifier) -> PathBuf { - url - .to_file_path() - .unwrap_or_else(|_| panic!("Provided URL was not file:// URL: {}", url)) -} - -fn to_file_path_string(url: &ModuleSpecifier) -> String { - to_file_path(url).display().to_string() -} - -fn should_be_treated_as_relative_or_absolute_path(specifier: &str) -> bool { - if specifier.is_empty() { - return false; - } - - if specifier.starts_with('/') { - return true; - } - - is_relative_specifier(specifier) -} - -// TODO(ry) We very likely have this utility function elsewhere in Deno. -fn is_relative_specifier(specifier: &str) -> bool { - let specifier_len = specifier.len(); - let specifier_chars: Vec<_> = specifier.chars().collect(); - - if !specifier_chars.is_empty() && specifier_chars[0] == '.' { - if specifier_len == 1 || specifier_chars[1] == '/' { - return true; - } - if specifier_chars[1] == '.' - && (specifier_len == 2 || specifier_chars[2] == '/') - { - return true; - } - } - false -} - -fn module_resolve( - specifier: &str, - base: &ModuleSpecifier, - conditions: &[&str], -) -> Result<ModuleSpecifier, AnyError> { - let resolved = if should_be_treated_as_relative_or_absolute_path(specifier) { - base.join(specifier)? - } else if specifier.starts_with('#') { - package_imports_resolve(specifier, base, conditions)? - } else if let Ok(resolved) = Url::parse(specifier) { - resolved - } else { - package_resolve(specifier, base, conditions)? - }; - finalize_resolution(resolved, base) -} - -fn finalize_resolution( - resolved: ModuleSpecifier, - base: &ModuleSpecifier, -) -> Result<ModuleSpecifier, AnyError> { - // TODO(bartlomieju): this is not part of Node resolution algorithm - // (as it doesn't support http/https); but I had to short circuit here - // for remote modules because they are mainly used to polyfill `node` built - // in modules. Another option would be to leave the resolved URLs - // as `node:<module_name>` and do the actual remapping to std's polyfill - // in module loader. I'm not sure which approach is better. - if resolved.scheme().starts_with("http") { - return Ok(resolved); - } - - let encoded_sep_re = Regex::new(r"%2F|%2C").expect("bad regex"); - - if encoded_sep_re.is_match(resolved.path()) { - return Err(errors::err_invalid_module_specifier( - resolved.path(), - "must not include encoded \"/\" or \"\\\\\" characters", - Some(to_file_path_string(base)), - )); - } - - let path = to_file_path(&resolved); - - // TODO(bartlomieju): currently not supported - // if (getOptionValue('--experimental-specifier-resolution') === 'node') { - // ... - // } - - let p_str = path.to_str().unwrap(); - let p = if p_str.ends_with('/') { - p_str[p_str.len() - 1..].to_string() - } else { - p_str.to_string() - }; - - let (is_dir, is_file) = if let Ok(stats) = std::fs::metadata(&p) { - (stats.is_dir(), stats.is_file()) - } else { - (false, false) - }; - if is_dir { - return Err(errors::err_unsupported_dir_import( - resolved.as_str(), - base.as_str(), - )); - } else if !is_file { - return Err(errors::err_module_not_found( - resolved.as_str(), - base.as_str(), - "module", - )); - } - - Ok(resolved) -} - -fn throw_import_not_defined( - specifier: &str, - package_json_url: Option<ModuleSpecifier>, - base: &ModuleSpecifier, -) -> AnyError { - errors::err_package_import_not_defined( - specifier, - package_json_url.map(|u| to_file_path_string(&u.join(".").unwrap())), - &to_file_path_string(base), - ) -} - -fn pattern_key_compare(a: &str, b: &str) -> i32 { - let a_pattern_index = a.find('*'); - let b_pattern_index = b.find('*'); - - let base_len_a = if let Some(index) = a_pattern_index { - index + 1 - } else { - a.len() - }; - let base_len_b = if let Some(index) = b_pattern_index { - index + 1 - } else { - b.len() - }; - - if base_len_a > base_len_b { - return -1; - } - - if base_len_b > base_len_a { - return 1; - } - - if a_pattern_index.is_none() { - return 1; - } - - if b_pattern_index.is_none() { - return -1; - } - - if a.len() > b.len() { - return -1; - } - - if b.len() > a.len() { - return 1; - } - - 0 -} - -fn package_imports_resolve( - name: &str, - base: &ModuleSpecifier, - conditions: &[&str], -) -> Result<ModuleSpecifier, AnyError> { - if name == "#" || name.starts_with("#/") || name.ends_with('/') { - let reason = "is not a valid internal imports specifier name"; - return Err(errors::err_invalid_module_specifier( - name, - reason, - Some(to_file_path_string(base)), - )); - } - - let mut package_json_url = None; - - let package_config = get_package_scope_config(base)?; - if package_config.exists { - package_json_url = - Some(Url::from_file_path(package_config.pjsonpath).unwrap()); - if let Some(imports) = &package_config.imports { - if imports.contains_key(name) && !name.contains('*') { - let maybe_resolved = resolve_package_target( - package_json_url.clone().unwrap(), - imports.get(name).unwrap().to_owned(), - "".to_string(), - name.to_string(), - base, - false, - true, - conditions, - )?; - if let Some(resolved) = maybe_resolved { - return Ok(resolved); - } - } else { - let mut best_match = ""; - let mut best_match_subpath = None; - for key in imports.keys() { - let pattern_index = key.find('*'); - if let Some(pattern_index) = pattern_index { - let key_sub = &key[0..=pattern_index]; - if name.starts_with(key_sub) { - let pattern_trailer = &key[pattern_index + 1..]; - if name.len() > key.len() - && name.ends_with(&pattern_trailer) - && pattern_key_compare(best_match, key) == 1 - && key.rfind('*') == Some(pattern_index) - { - best_match = key; - best_match_subpath = Some( - name[pattern_index..=(name.len() - pattern_trailer.len())] - .to_string(), - ); - } - } - } - } - - if !best_match.is_empty() { - let target = imports.get(best_match).unwrap().to_owned(); - let maybe_resolved = resolve_package_target( - package_json_url.clone().unwrap(), - target, - best_match_subpath.unwrap(), - best_match.to_string(), - base, - true, - true, - conditions, - )?; - if let Some(resolved) = maybe_resolved { - return Ok(resolved); - } - } - } - } - } - - Err(throw_import_not_defined(name, package_json_url, base)) -} - -fn is_conditional_exports_main_sugar( - exports: &Value, - package_json_url: &ModuleSpecifier, - base: &ModuleSpecifier, -) -> Result<bool, AnyError> { - if exports.is_string() || exports.is_array() { - return Ok(true); - } - - if exports.is_null() || !exports.is_object() { - return Ok(false); - } - - let exports_obj = exports.as_object().unwrap(); - let mut is_conditional_sugar = false; - let mut i = 0; - for key in exports_obj.keys() { - let cur_is_conditional_sugar = key.is_empty() || !key.starts_with('.'); - if i == 0 { - is_conditional_sugar = cur_is_conditional_sugar; - i += 1; - } else if is_conditional_sugar != cur_is_conditional_sugar { - return Err(errors::err_invalid_package_config( - &to_file_path_string(package_json_url), - Some(base.as_str().to_string()), - Some("\"exports\" cannot contains some keys starting with \'.\' and some not. - The exports object must either be an object of package subpath keys - or an object of main entry condition name keys only.".to_string()) - )); - } - } - - Ok(is_conditional_sugar) -} - -fn throw_invalid_package_target( - subpath: String, - target: String, - package_json_url: &ModuleSpecifier, - internal: bool, - base: &ModuleSpecifier, -) -> AnyError { - errors::err_invalid_package_target( - to_file_path_string(&package_json_url.join(".").unwrap()), - subpath, - target, - internal, - Some(base.as_str().to_string()), - ) -} - -fn throw_invalid_subpath( - subpath: String, - package_json_url: &ModuleSpecifier, - internal: bool, - base: &ModuleSpecifier, -) -> AnyError { - let ie = if internal { "imports" } else { "exports" }; - let reason = format!( - "request is not a valid subpath for the \"{}\" resolution of {}", - ie, - to_file_path_string(package_json_url) - ); - errors::err_invalid_module_specifier( - &subpath, - &reason, - Some(to_file_path_string(base)), - ) -} - -#[allow(clippy::too_many_arguments)] -fn resolve_package_target_string( - target: String, - subpath: String, - match_: String, - package_json_url: ModuleSpecifier, - base: &ModuleSpecifier, - pattern: bool, - internal: bool, - conditions: &[&str], -) -> Result<ModuleSpecifier, AnyError> { - if !subpath.is_empty() && !pattern && !target.ends_with('/') { - return Err(throw_invalid_package_target( - match_, - target, - &package_json_url, - internal, - base, - )); - } - - let invalid_segment_re = - Regex::new(r"(^|\|/)(..?|node_modules)(\|/|$)").expect("bad regex"); - let pattern_re = Regex::new(r"\*").expect("bad regex"); - - if !target.starts_with("./") { - if internal && !target.starts_with("../") && !target.starts_with('/') { - let is_url = Url::parse(&target).is_ok(); - if !is_url { - let export_target = if pattern { - pattern_re - .replace(&target, |_caps: ®ex::Captures| subpath.clone()) - .to_string() - } else { - format!("{}{}", target, subpath) - }; - return package_resolve(&export_target, &package_json_url, conditions); - } - } - return Err(throw_invalid_package_target( - match_, - target, - &package_json_url, - internal, - base, - )); - } - - if invalid_segment_re.is_match(&target[2..]) { - return Err(throw_invalid_package_target( - match_, - target, - &package_json_url, - internal, - base, - )); - } - - let resolved = package_json_url.join(&target)?; - let resolved_path = resolved.path(); - let package_url = package_json_url.join(".").unwrap(); - let package_path = package_url.path(); - - if !resolved_path.starts_with(package_path) { - return Err(throw_invalid_package_target( - match_, - target, - &package_json_url, - internal, - base, - )); - } - - if subpath.is_empty() { - return Ok(resolved); - } - - if invalid_segment_re.is_match(&subpath) { - let request = if pattern { - match_.replace('*', &subpath) - } else { - format!("{}{}", match_, subpath) - }; - return Err(throw_invalid_subpath( - request, - &package_json_url, - internal, - base, - )); - } - - if pattern { - let replaced = pattern_re - .replace(resolved.as_str(), |_caps: ®ex::Captures| subpath.clone()); - let url = Url::parse(&replaced)?; - return Ok(url); - } - - Ok(resolved.join(&subpath)?) -} - -#[allow(clippy::too_many_arguments)] -fn resolve_package_target( - package_json_url: ModuleSpecifier, - target: Value, - subpath: String, - package_subpath: String, - base: &ModuleSpecifier, - pattern: bool, - internal: bool, - conditions: &[&str], -) -> Result<Option<ModuleSpecifier>, AnyError> { - if let Some(target) = target.as_str() { - return Ok(Some(resolve_package_target_string( - target.to_string(), - subpath, - package_subpath, - package_json_url, - base, - pattern, - internal, - conditions, - )?)); - } else if let Some(target_arr) = target.as_array() { - if target_arr.is_empty() { - return Ok(None); - } - - let mut last_error = None; - for target_item in target_arr { - let resolved_result = resolve_package_target( - package_json_url.clone(), - target_item.to_owned(), - subpath.clone(), - package_subpath.clone(), - base, - pattern, - internal, - conditions, - ); - - if let Err(e) = resolved_result { - let err_string = e.to_string(); - last_error = Some(e); - if err_string.starts_with("[ERR_INVALID_PACKAGE_TARGET]") { - continue; - } - return Err(last_error.unwrap()); - } - let resolved = resolved_result.unwrap(); - if resolved.is_none() { - last_error = None; - continue; - } - return Ok(resolved); - } - if last_error.is_none() { - return Ok(None); - } - return Err(last_error.unwrap()); - } else if let Some(target_obj) = target.as_object() { - for key in target_obj.keys() { - // TODO(bartlomieju): verify that keys are not numeric - // return Err(errors::err_invalid_package_config( - // to_file_path_string(package_json_url), - // Some(base.as_str().to_string()), - // Some("\"exports\" cannot contain numeric property keys.".to_string()), - // )); - - if key == "default" || conditions.contains(&key.as_str()) { - let condition_target = target_obj.get(key).unwrap().to_owned(); - let resolved = resolve_package_target( - package_json_url.clone(), - condition_target, - subpath.clone(), - package_subpath.clone(), - base, - pattern, - internal, - conditions, - )?; - if resolved.is_none() { - continue; - } - return Ok(resolved); - } - } - } else if target.is_null() { - return Ok(None); - } - - Err(throw_invalid_package_target( - package_subpath, - target.to_string(), - &package_json_url, - internal, - base, - )) -} - -fn throw_exports_not_found( - subpath: String, - package_json_url: &ModuleSpecifier, - base: &ModuleSpecifier, -) -> AnyError { - errors::err_package_path_not_exported( - to_file_path_string(&package_json_url.join(".").unwrap()), - subpath, - Some(to_file_path_string(base)), - ) -} - -fn package_exports_resolve( - package_json_url: ModuleSpecifier, - package_subpath: String, - package_config: PackageConfig, - base: &ModuleSpecifier, - conditions: &[&str], -) -> Result<ModuleSpecifier, AnyError> { - let exports = &package_config.exports.unwrap(); - - let exports_map = - if is_conditional_exports_main_sugar(exports, &package_json_url, base)? { - let mut map = Map::new(); - map.insert(".".to_string(), exports.to_owned()); - map - } else { - exports.as_object().unwrap().to_owned() - }; - - if exports_map.contains_key(&package_subpath) - && package_subpath.find('*').is_none() - && !package_subpath.ends_with('/') - { - let target = exports_map.get(&package_subpath).unwrap().to_owned(); - let resolved = resolve_package_target( - package_json_url.clone(), - target, - "".to_string(), - package_subpath.to_string(), - base, - false, - false, - conditions, - )?; - if resolved.is_none() { - return Err(throw_exports_not_found( - package_subpath, - &package_json_url, - base, - )); - } - return Ok(resolved.unwrap()); - } - - let mut best_match = ""; - let mut best_match_subpath = None; - for key in exports_map.keys() { - let pattern_index = key.find('*'); - if let Some(pattern_index) = pattern_index { - let key_sub = &key[0..=pattern_index]; - if package_subpath.starts_with(key_sub) { - // When this reaches EOL, this can throw at the top of the whole function: - // - // if (StringPrototypeEndsWith(packageSubpath, '/')) - // throwInvalidSubpath(packageSubpath) - // - // To match "imports" and the spec. - if package_subpath.ends_with('/') { - // TODO(bartlomieju): - // emitTrailingSlashPatternDeprecation(); - } - let pattern_trailer = &key[pattern_index + 1..]; - if package_subpath.len() > key.len() - && package_subpath.ends_with(&pattern_trailer) - && pattern_key_compare(best_match, key) == 1 - && key.rfind('*') == Some(pattern_index) - { - best_match = key; - best_match_subpath = Some( - package_subpath - [pattern_index..=(package_subpath.len() - pattern_trailer.len())] - .to_string(), - ); - } - } - } - } - - if !best_match.is_empty() { - let target = exports.get(best_match).unwrap().to_owned(); - let maybe_resolved = resolve_package_target( - package_json_url.clone(), - target, - best_match_subpath.unwrap(), - best_match.to_string(), - base, - true, - false, - conditions, - )?; - if let Some(resolved) = maybe_resolved { - return Ok(resolved); - } else { - return Err(throw_exports_not_found( - package_subpath, - &package_json_url, - base, - )); - } - } - - Err(throw_exports_not_found( - package_subpath, - &package_json_url, - base, - )) -} - -fn package_resolve( - specifier: &str, - base: &ModuleSpecifier, - conditions: &[&str], -) -> Result<ModuleSpecifier, AnyError> { - let (package_name, package_subpath, is_scoped) = - parse_package_name(specifier, base)?; - - // ResolveSelf - let package_config = get_package_scope_config(base)?; - if package_config.exists { - let package_json_url = - Url::from_file_path(&package_config.pjsonpath).unwrap(); - if package_config.name.as_ref() == Some(&package_name) { - if let Some(exports) = &package_config.exports { - if !exports.is_null() { - return package_exports_resolve( - package_json_url, - package_subpath, - package_config, - base, - conditions, - ); - } - } - } - } - - let mut package_json_url = - base.join(&format!("./node_modules/{}/package.json", package_name))?; - let mut package_json_path = to_file_path(&package_json_url); - let mut last_path; - loop { - let p_str = package_json_path.to_str().unwrap(); - let package_str_len = "/package.json".len(); - let p = p_str[0..=p_str.len() - package_str_len].to_string(); - let is_dir = if let Ok(stats) = std::fs::metadata(&p) { - stats.is_dir() - } else { - false - }; - if !is_dir { - last_path = package_json_path; - - let prefix = if is_scoped { - "../../../../node_modules/" - } else { - "../../../node_modules/" - }; - package_json_url = package_json_url - .join(&format!("{}{}/package.json", prefix, package_name))?; - package_json_path = to_file_path(&package_json_url); - if package_json_path.to_str().unwrap().len() - == last_path.to_str().unwrap().len() - { - break; - } else { - continue; - } - } - - // Package match. - let package_config = - get_package_config(package_json_path.clone(), specifier, Some(base))?; - if package_config.exports.is_some() { - return package_exports_resolve( - package_json_url, - package_subpath, - package_config, - base, - conditions, - ); - } - if package_subpath == "." { - return legacy_main_resolve(&package_json_url, &package_config, base); - } - - return package_json_url - .join(&package_subpath) - .map_err(AnyError::from); - } - - Err(errors::err_module_not_found( - &package_json_url - .join(".") - .unwrap() - .to_file_path() - .unwrap() - .display() - .to_string(), - &to_file_path_string(base), - "package", - )) -} - -fn parse_package_name( - specifier: &str, - base: &ModuleSpecifier, -) -> Result<(String, String, bool), AnyError> { - let mut separator_index = specifier.find('/'); - let mut valid_package_name = true; - let mut is_scoped = false; - if specifier.is_empty() { - valid_package_name = false; - } else if specifier.starts_with('@') { - is_scoped = true; - if let Some(index) = separator_index { - separator_index = specifier[index + 1..].find('/'); - } else { - valid_package_name = false; - } - } - - let package_name = if let Some(index) = separator_index { - specifier[0..index].to_string() - } else { - specifier.to_string() - }; - - // Package name cannot have leading . and cannot have percent-encoding or separators. - for ch in package_name.chars() { - if ch == '%' || ch == '\\' { - valid_package_name = false; - break; - } - } - - if !valid_package_name { - return Err(errors::err_invalid_module_specifier( - specifier, - "is not a valid package name", - Some(to_file_path_string(base)), - )); - } - - let package_subpath = if let Some(index) = separator_index { - format!(".{}", specifier.chars().skip(index).collect::<String>()) - } else { - ".".to_string() - }; - - Ok((package_name, package_subpath, is_scoped)) -} - -#[derive(Clone, Debug)] -struct PackageConfig { - exists: bool, - exports: Option<Value>, - imports: Option<Map<String, Value>>, - main: Option<String>, - name: Option<String>, - pjsonpath: PathBuf, - typ: String, -} - -pub fn check_if_should_use_esm_loader( - main_module: &ModuleSpecifier, -) -> Result<bool, AnyError> { - let s = main_module.as_str(); - if s.ends_with(".mjs") { - return Ok(true); - } - if s.ends_with(".cjs") { - return Ok(false); - } - let package_config = get_package_scope_config(main_module)?; - Ok(package_config.typ == "module") -} - -fn get_package_config( - path: PathBuf, - specifier: &str, - maybe_base: Option<&ModuleSpecifier>, -) -> Result<PackageConfig, AnyError> { - // TODO(bartlomieju): - // if let Some(existing) = package_json_cache.get(path) { - // return Ok(existing.clone()); - // } - - let result = std::fs::read_to_string(&path); - - let source = result.unwrap_or_else(|_| "".to_string()); - if source.is_empty() { - let package_config = PackageConfig { - pjsonpath: path, - exists: false, - main: None, - name: None, - typ: "none".to_string(), - exports: None, - imports: None, - }; - // TODO(bartlomieju): - // package_json_cache.set(package_json_path, package_config.clone()); - return Ok(package_config); - } - - let package_json: Value = serde_json::from_str(&source).map_err(|err| { - let base_msg = maybe_base.map(|base| { - format!("\"{}\" from {}", specifier, to_file_path(base).display()) - }); - errors::err_invalid_package_config( - &path.display().to_string(), - base_msg, - Some(err.to_string()), - ) - })?; - - let imports_val = package_json.get("imports"); - let main_val = package_json.get("main"); - let name_val = package_json.get("name"); - let typ_val = package_json.get("type"); - let exports = package_json.get("exports").map(|e| e.to_owned()); - - let imports = if let Some(imp) = imports_val { - imp.as_object().map(|imp| imp.to_owned()) - } else { - None - }; - let main = if let Some(m) = main_val { - m.as_str().map(|m| m.to_string()) - } else { - None - }; - let name = if let Some(n) = name_val { - n.as_str().map(|n| n.to_string()) - } else { - None - }; - - // Ignore unknown types for forwards compatibility - let typ = if let Some(t) = typ_val { - if let Some(t) = t.as_str() { - if t != "module" && t != "commonjs" { - "none".to_string() - } else { - t.to_string() - } - } else { - "none".to_string() - } - } else { - "none".to_string() - }; - - let package_config = PackageConfig { - pjsonpath: path, - exists: true, - main, - name, - typ, - exports, - imports, - }; - // TODO(bartlomieju): - // package_json_cache.set(package_json_path, package_config.clone()); - Ok(package_config) -} - -fn get_package_scope_config( - resolved: &ModuleSpecifier, -) -> Result<PackageConfig, AnyError> { - let mut package_json_url = resolved.join("./package.json")?; - - loop { - let package_json_path = package_json_url.path(); - - if package_json_path.ends_with("node_modules/package.json") { - break; - } - - let package_config = get_package_config( - to_file_path(&package_json_url), - resolved.as_str(), - None, - )?; - - if package_config.exists { - return Ok(package_config); - } - - let last_package_json_url = package_json_url.clone(); - package_json_url = package_json_url.join("../package.json")?; - - // TODO(bartlomieju): I'm not sure this will work properly - // Terminates at root where ../package.json equals ../../package.json - // (can't just check "/package.json" for Windows support) - if package_json_url.path() == last_package_json_url.path() { - break; - } - } - - let package_json_path = to_file_path(&package_json_url); - let package_config = PackageConfig { - pjsonpath: package_json_path, - exists: false, - main: None, - name: None, - typ: "none".to_string(), - exports: None, - imports: None, - }; - - // TODO(bartlomieju): - // package_json_cache.set(package_json_path, package_config.clone()); - - Ok(package_config) -} - -fn file_exists(path_url: &ModuleSpecifier) -> bool { - if let Ok(stats) = std::fs::metadata(to_file_path(path_url)) { - stats.is_file() - } else { - false - } -} - -fn legacy_main_resolve( - package_json_url: &ModuleSpecifier, - package_config: &PackageConfig, - _base: &ModuleSpecifier, -) -> Result<ModuleSpecifier, AnyError> { - let mut guess; - - if let Some(main) = &package_config.main { - guess = package_json_url.join(&format!("./{}", main))?; - if file_exists(&guess) { - return Ok(guess); - } - - let mut found = false; - for ext in [ - ".js", - ".json", - ".node", - "/index.js", - "/index.json", - "/index.node", - ] { - guess = package_json_url.join(&format!("./{}{}", main, ext))?; - if file_exists(&guess) { - found = true; - break; - } - } - - if found { - // TODO(bartlomieju): emitLegacyIndexDeprecation() - return Ok(guess); - } - } - - for p in ["./index.js", "./index.json", "./index.node"] { - guess = package_json_url.join(p)?; - if file_exists(&guess) { - // TODO(bartlomieju): emitLegacyIndexDeprecation() - return Ok(guess); - } - } - - Err(generic_error("not found")) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::deno_std::CURRENT_STD_URL; - - fn testdir(name: &str) -> PathBuf { - let c = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - c.join("compat/testdata/").join(name) - } - - #[test] - fn basic() { - let cwd = testdir("basic"); - let main = Url::from_file_path(cwd.join("main.js")).unwrap(); - let actual = node_resolve("foo", main.as_str(), &cwd).unwrap(); - let expected = - Url::from_file_path(cwd.join("node_modules/foo/index.js")).unwrap(); - assert!(matches!(actual, ResolveResponse::Esm(_))); - assert_eq!(actual.to_result().unwrap(), expected); - - let actual = node_resolve( - "data:application/javascript,console.log(\"Hello%20Deno\");", - main.as_str(), - &cwd, - ) - .unwrap(); - let expected = - Url::parse("data:application/javascript,console.log(\"Hello%20Deno\");") - .unwrap(); - assert!(matches!(actual, ResolveResponse::Specifier(_))); - assert_eq!(actual.to_result().unwrap(), expected); - } - - #[test] - fn deep() { - let cwd = testdir("deep"); - let main = Url::from_file_path(cwd.join("a/b/c/d/main.js")).unwrap(); - let actual = node_resolve("foo", main.as_str(), &cwd).unwrap(); - let expected = - Url::from_file_path(cwd.join("node_modules/foo/index.js")).unwrap(); - matches!(actual, ResolveResponse::Esm(_)); - assert_eq!(actual.to_result().unwrap(), expected); - } - - #[test] - fn package_subpath() { - let cwd = testdir("subpath"); - let main = Url::from_file_path(cwd.join("main.js")).unwrap(); - let actual = node_resolve("foo", main.as_str(), &cwd).unwrap(); - let expected = - Url::from_file_path(cwd.join("node_modules/foo/index.js")).unwrap(); - matches!(actual, ResolveResponse::CommonJs(_)); - assert_eq!(actual.to_result().unwrap(), expected); - let actual = node_resolve("foo/server.js", main.as_str(), &cwd).unwrap(); - let expected = - Url::from_file_path(cwd.join("node_modules/foo/server.js")).unwrap(); - matches!(actual, ResolveResponse::CommonJs(_)); - assert_eq!(actual.to_result().unwrap(), expected); - } - - #[test] - fn basic_deps() { - let cwd = testdir("basic_deps"); - let main = Url::from_file_path(cwd.join("main.js")).unwrap(); - let actual = node_resolve("foo", main.as_str(), &cwd).unwrap(); - let foo_js = - Url::from_file_path(cwd.join("node_modules/foo/foo.js")).unwrap(); - assert!(matches!(actual, ResolveResponse::Esm(_))); - assert_eq!(actual.to_result().unwrap(), foo_js); - - let actual = node_resolve("bar", foo_js.as_str(), &cwd).unwrap(); - - let bar_js = - Url::from_file_path(cwd.join("node_modules/bar/bar.js")).unwrap(); - assert!(matches!(actual, ResolveResponse::Esm(_))); - assert_eq!(actual.to_result().unwrap(), bar_js); - } - - #[test] - fn builtin_http() { - let cwd = testdir("basic"); - let main = Url::from_file_path(cwd.join("main.js")).unwrap(); - let expected = CURRENT_STD_URL.join("node/http.ts").unwrap(); - - let actual = node_resolve("http", main.as_str(), &cwd).unwrap(); - assert!(matches!(actual, ResolveResponse::Esm(_))); - assert_eq!(actual.to_result().unwrap(), expected); - - let actual = node_resolve("node:http", main.as_str(), &cwd).unwrap(); - assert!(matches!(actual, ResolveResponse::Esm(_))); - assert_eq!(actual.to_result().unwrap(), expected); - } - - #[test] - fn conditional_exports() { - // check that `exports` mapping works correctly - let cwd = testdir("conditions"); - let main = Url::from_file_path(cwd.join("main.js")).unwrap(); - let actual = node_resolve("imports_exports", main.as_str(), &cwd).unwrap(); - let expected = Url::from_file_path( - cwd.join("node_modules/imports_exports/import_export.js"), - ) - .unwrap(); - assert!(matches!(actual, ResolveResponse::CommonJs(_))); - assert_eq!(actual.to_result().unwrap(), expected); - - // check that `imports` mapping works correctly - let cwd = testdir("conditions/node_modules/imports_exports"); - let main = Url::from_file_path(cwd.join("import_export.js")).unwrap(); - let actual = node_resolve("#dep", main.as_str(), &cwd).unwrap(); - let expected = Url::from_file_path(cwd.join("import_polyfill.js")).unwrap(); - assert!(matches!(actual, ResolveResponse::CommonJs(_))); - assert_eq!(actual.to_result().unwrap(), expected); - } - - #[test] - fn test_is_relative_specifier() { - assert!(is_relative_specifier("./foo.js")); - assert!(!is_relative_specifier("https://deno.land/std/node/http.ts")); - } - - #[test] - fn test_check_if_should_use_esm_loader() { - let basic = testdir("basic"); - let main = Url::from_file_path(basic.join("main.js")).unwrap(); - assert!(check_if_should_use_esm_loader(&main).unwrap()); - - let cjs = Url::from_file_path(basic.join("main.cjs")).unwrap(); - assert!(!check_if_should_use_esm_loader(&cjs).unwrap()); - - let not_esm = testdir("not_esm"); - let main = Url::from_file_path(not_esm.join("main.js")).unwrap(); - assert!(!check_if_should_use_esm_loader(&main).unwrap()); - } -} diff --git a/cli/compat/mod.rs b/cli/compat/mod.rs deleted file mode 100644 index 0581f208f..000000000 --- a/cli/compat/mod.rs +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. - -mod esm_resolver; - -use crate::file_fetcher::FileFetcher; -use crate::node::NODE_COMPAT_URL; -use crate::node::SUPPORTED_MODULES; -use deno_ast::MediaType; -use deno_core::error::AnyError; -use deno_core::located_script_name; -use deno_core::url::Url; -use deno_core::JsRuntime; -use deno_core::ModuleSpecifier; -use once_cell::sync::Lazy; - -pub use esm_resolver::check_if_should_use_esm_loader; -pub use esm_resolver::NodeEsmResolver; - -pub static GLOBAL_URL: Lazy<Url> = - Lazy::new(|| NODE_COMPAT_URL.join("node/global.ts").unwrap()); - -pub static MODULE_URL: Lazy<Url> = - Lazy::new(|| NODE_COMPAT_URL.join("node/module.ts").unwrap()); - -static COMPAT_IMPORT_URL: Lazy<Url> = - Lazy::new(|| Url::parse("flags:compat").unwrap()); - -/// Provide imports into a module graph when the compat flag is true. -pub fn get_node_imports() -> Vec<(Url, Vec<String>)> { - vec![( - COMPAT_IMPORT_URL.clone(), - vec![GLOBAL_URL.as_str().to_owned()], - )] -} - -pub fn load_cjs_module( - js_runtime: &mut JsRuntime, - module: &str, - main: bool, -) -> Result<(), AnyError> { - let source_code = &format!( - r#"(async function loadCjsModule(module) {{ - const Module = await import("{module_loader}"); - Module.default._load(module, null, {main}); - }})('{module}');"#, - module_loader = MODULE_URL.as_str(), - main = main, - module = escape_for_single_quote_string(module), - ); - - js_runtime.execute_script(&located_script_name!(), source_code)?; - Ok(()) -} - -pub fn add_global_require( - js_runtime: &mut JsRuntime, - main_module: &str, -) -> Result<(), AnyError> { - let source_code = &format!( - r#"(async function setupGlobalRequire(main) {{ - const Module = await import("{}"); - const require = Module.createRequire(main); - globalThis.require = require; - }})('{}');"#, - MODULE_URL.as_str(), - escape_for_single_quote_string(main_module), - ); - - js_runtime.execute_script(&located_script_name!(), source_code)?; - Ok(()) -} - -fn escape_for_single_quote_string(text: &str) -> String { - text.replace('\\', r"\\").replace('\'', r"\'") -} - -pub fn setup_builtin_modules( - js_runtime: &mut JsRuntime, -) -> Result<(), AnyError> { - let mut script = String::new(); - for module in SUPPORTED_MODULES { - // skipping the modules that contains '/' as they are not available in NodeJS repl as well - if !module.name.contains('/') { - script = format!( - "{}const {MODULE_NAME} = require('{MODULE_NAME}');\n", - script, - MODULE_NAME = module.name - ); - } - } - - js_runtime.execute_script("setup_node_builtins.js", &script)?; - Ok(()) -} - -/// Translates given CJS module into ESM. This function will perform static -/// analysis on the file to find defined exports and reexports. -/// -/// For all discovered reexports the analysis will be performed recursively. -/// -/// If successful a source code for equivalent ES module is returned. -pub fn translate_cjs_to_esm( - file_fetcher: &FileFetcher, - specifier: &ModuleSpecifier, - code: String, - media_type: MediaType, -) -> Result<String, AnyError> { - let parsed_source = deno_ast::parse_script(deno_ast::ParseParams { - specifier: specifier.to_string(), - text_info: deno_ast::SourceTextInfo::new(code.into()), - media_type, - capture_tokens: true, - scope_analysis: false, - maybe_syntax: None, - })?; - let analysis = parsed_source.analyze_cjs(); - - let mut source = vec![ - r#"import { createRequire } from "node:module";"#.to_string(), - r#"const require = createRequire(import.meta.url);"#.to_string(), - ]; - - // if there are reexports, handle them first - for (idx, reexport) in analysis.reexports.iter().enumerate() { - // Firstly, resolve relate reexport specifier - let resolved_reexport = node_resolver::resolve( - reexport, - &specifier.to_file_path().unwrap(), - // FIXME(bartlomieju): check if these conditions are okay, probably - // should be `deno-require`, because `deno` is already used in `esm_resolver.rs` - &["deno", "require", "default"], - )?; - let reexport_specifier = - ModuleSpecifier::from_file_path(&resolved_reexport).unwrap(); - // Secondly, read the source code from disk - let reexport_file = file_fetcher.get_source(&reexport_specifier).unwrap(); - // Now perform analysis again - { - let parsed_source = deno_ast::parse_script(deno_ast::ParseParams { - specifier: reexport_specifier.to_string(), - text_info: deno_ast::SourceTextInfo::new(reexport_file.source), - media_type: reexport_file.media_type, - capture_tokens: true, - scope_analysis: false, - maybe_syntax: None, - })?; - let analysis = parsed_source.analyze_cjs(); - - source.push(format!( - "const reexport{} = require(\"{}\");", - idx, reexport - )); - - for export in analysis.exports.iter().filter(|e| e.as_str() != "default") - { - // TODO(bartlomieju): Node actually checks if a given export exists in `exports` object, - // but it might not be necessary here since our analysis is more detailed? - source.push(format!( - "export const {0} = Deno[Deno.internal].require.bindExport(reexport{1}.{2}, reexport{1});", - export, idx, export - )); - } - } - } - - source.push(format!( - "const mod = require(\"{}\");", - specifier - .to_file_path() - .unwrap() - .to_str() - .unwrap() - .replace('\\', "\\\\") - .replace('\'', "\\\'") - .replace('\"', "\\\"") - )); - source.push("export default mod;".to_string()); - - for export in analysis.exports.iter().filter(|e| e.as_str() != "default") { - // TODO(bartlomieju): Node actually checks if a given export exists in `exports` object, - // but it might not be necessary here since our analysis is more detailed? - source.push(format!( - "export const {} = Deno[Deno.internal].require.bindExport(mod.{}, mod);", - export, export - )); - } - - let translated_source = source.join("\n"); - Ok(translated_source) -} diff --git a/cli/compat/testdata/basic/main.js b/cli/compat/testdata/basic/main.js deleted file mode 100644 index c0748305d..000000000 --- a/cli/compat/testdata/basic/main.js +++ /dev/null @@ -1 +0,0 @@ -import "foo"; diff --git a/cli/compat/testdata/basic/node_modules/foo/index.js b/cli/compat/testdata/basic/node_modules/foo/index.js deleted file mode 100644 index e69de29bb..000000000 --- a/cli/compat/testdata/basic/node_modules/foo/index.js +++ /dev/null diff --git a/cli/compat/testdata/basic/node_modules/foo/package.json b/cli/compat/testdata/basic/node_modules/foo/package.json deleted file mode 100644 index a74d52fd3..000000000 --- a/cli/compat/testdata/basic/node_modules/foo/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "foo", - "type": "module", - "exports": "./index.js" -} diff --git a/cli/compat/testdata/basic/package.json b/cli/compat/testdata/basic/package.json deleted file mode 100644 index cc4ac5493..000000000 --- a/cli/compat/testdata/basic/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "bar", - "type": "module", - "dependencies": { - "foo": "1.0.0" - } -} diff --git a/cli/compat/testdata/basic_deps/main.js b/cli/compat/testdata/basic_deps/main.js deleted file mode 100644 index c0748305d..000000000 --- a/cli/compat/testdata/basic_deps/main.js +++ /dev/null @@ -1 +0,0 @@ -import "foo"; diff --git a/cli/compat/testdata/basic_deps/node_modules/bar/bar.js b/cli/compat/testdata/basic_deps/node_modules/bar/bar.js deleted file mode 100644 index 98e51675e..000000000 --- a/cli/compat/testdata/basic_deps/node_modules/bar/bar.js +++ /dev/null @@ -1 +0,0 @@ -export const BAR = 123; diff --git a/cli/compat/testdata/basic_deps/node_modules/bar/package.json b/cli/compat/testdata/basic_deps/node_modules/bar/package.json deleted file mode 100644 index c2043f610..000000000 --- a/cli/compat/testdata/basic_deps/node_modules/bar/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "bar", - "version": "0.1.2", - "type": "module", - "exports": "./bar.js" -} diff --git a/cli/compat/testdata/basic_deps/node_modules/foo/foo.js b/cli/compat/testdata/basic_deps/node_modules/foo/foo.js deleted file mode 100644 index 0026acc8e..000000000 --- a/cli/compat/testdata/basic_deps/node_modules/foo/foo.js +++ /dev/null @@ -1 +0,0 @@ -import "bar"; diff --git a/cli/compat/testdata/basic_deps/node_modules/foo/package.json b/cli/compat/testdata/basic_deps/node_modules/foo/package.json deleted file mode 100644 index 376dae81e..000000000 --- a/cli/compat/testdata/basic_deps/node_modules/foo/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "foo", - "type": "module", - "exports": "./foo.js", - "dependencies": { - "bar": "0.1.2" - } -} diff --git a/cli/compat/testdata/basic_deps/package.json b/cli/compat/testdata/basic_deps/package.json deleted file mode 100644 index 138d401ed..000000000 --- a/cli/compat/testdata/basic_deps/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "main_program", - "type": "module", - "dependencies": { - "foo": "1.0.0" - } -} diff --git a/cli/compat/testdata/conditions/main.js b/cli/compat/testdata/conditions/main.js deleted file mode 100644 index cafddb5d6..000000000 --- a/cli/compat/testdata/conditions/main.js +++ /dev/null @@ -1 +0,0 @@ -import "imports_exports"; diff --git a/cli/compat/testdata/conditions/node_modules/imports_exports/import_export.js b/cli/compat/testdata/conditions/node_modules/imports_exports/import_export.js deleted file mode 100644 index 3ebd222ea..000000000 --- a/cli/compat/testdata/conditions/node_modules/imports_exports/import_export.js +++ /dev/null @@ -1,6 +0,0 @@ -import dep from "#dep"; - -export default { - bar: "bar", - dep, -}; diff --git a/cli/compat/testdata/conditions/node_modules/imports_exports/import_polyfill.js b/cli/compat/testdata/conditions/node_modules/imports_exports/import_polyfill.js deleted file mode 100644 index 76716a3ef..000000000 --- a/cli/compat/testdata/conditions/node_modules/imports_exports/import_polyfill.js +++ /dev/null @@ -1,3 +0,0 @@ -export default { - polyfill: "import", -}; diff --git a/cli/compat/testdata/conditions/node_modules/imports_exports/package.json b/cli/compat/testdata/conditions/node_modules/imports_exports/package.json deleted file mode 100644 index 5d26359db..000000000 --- a/cli/compat/testdata/conditions/node_modules/imports_exports/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "version": "1.0.0", - "name": "imports_exports", - "main": "./require_export.cjs", - "imports": { - "#dep": { - "import": "./import_polyfill.js", - "require": "./require_polyfill.js" - } - }, - "exports": { - ".": { - "import": "./import_export.js", - "require": "./require_export.cjs" - } - } -} diff --git a/cli/compat/testdata/conditions/node_modules/imports_exports/require_export.cjs b/cli/compat/testdata/conditions/node_modules/imports_exports/require_export.cjs deleted file mode 100644 index 11648c0d7..000000000 --- a/cli/compat/testdata/conditions/node_modules/imports_exports/require_export.cjs +++ /dev/null @@ -1,6 +0,0 @@ -const dep = require("#dep"); - -module.exports = { - foo: "foo", - dep, -};
\ No newline at end of file diff --git a/cli/compat/testdata/conditions/node_modules/imports_exports/require_polyfill.js b/cli/compat/testdata/conditions/node_modules/imports_exports/require_polyfill.js deleted file mode 100644 index 1023fd65c..000000000 --- a/cli/compat/testdata/conditions/node_modules/imports_exports/require_polyfill.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - polyfill: "require", -}; diff --git a/cli/compat/testdata/conditions/package.json b/cli/compat/testdata/conditions/package.json deleted file mode 100644 index 4d6d004dd..000000000 --- a/cli/compat/testdata/conditions/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "conditions", - "type": "module", - "dependencies": { - "imports_exports": "1.0.0" - } -} diff --git a/cli/compat/testdata/deep/a/b/c/d/main.js b/cli/compat/testdata/deep/a/b/c/d/main.js deleted file mode 100644 index c0748305d..000000000 --- a/cli/compat/testdata/deep/a/b/c/d/main.js +++ /dev/null @@ -1 +0,0 @@ -import "foo"; diff --git a/cli/compat/testdata/deep/node_modules/foo/index.js b/cli/compat/testdata/deep/node_modules/foo/index.js deleted file mode 100644 index e69de29bb..000000000 --- a/cli/compat/testdata/deep/node_modules/foo/index.js +++ /dev/null diff --git a/cli/compat/testdata/deep/node_modules/foo/package.json b/cli/compat/testdata/deep/node_modules/foo/package.json deleted file mode 100644 index a74d52fd3..000000000 --- a/cli/compat/testdata/deep/node_modules/foo/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "foo", - "type": "module", - "exports": "./index.js" -} diff --git a/cli/compat/testdata/not_esm/main.js b/cli/compat/testdata/not_esm/main.js deleted file mode 100644 index 347e20832..000000000 --- a/cli/compat/testdata/not_esm/main.js +++ /dev/null @@ -1 +0,0 @@ -require("foo"); diff --git a/cli/compat/testdata/not_esm/node_modules/foo/index.js b/cli/compat/testdata/not_esm/node_modules/foo/index.js deleted file mode 100644 index e69de29bb..000000000 --- a/cli/compat/testdata/not_esm/node_modules/foo/index.js +++ /dev/null diff --git a/cli/compat/testdata/not_esm/node_modules/foo/package.json b/cli/compat/testdata/not_esm/node_modules/foo/package.json deleted file mode 100644 index a74d52fd3..000000000 --- a/cli/compat/testdata/not_esm/node_modules/foo/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "foo", - "type": "module", - "exports": "./index.js" -} diff --git a/cli/compat/testdata/not_esm/package.json b/cli/compat/testdata/not_esm/package.json deleted file mode 100644 index 4b03fc938..000000000 --- a/cli/compat/testdata/not_esm/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "bar", - "dependencies": { - "foo": "1.0.0" - } -} diff --git a/cli/compat/testdata/subpath/main.js b/cli/compat/testdata/subpath/main.js deleted file mode 100644 index ed1fe019e..000000000 --- a/cli/compat/testdata/subpath/main.js +++ /dev/null @@ -1,2 +0,0 @@ -import "foo"; -import "foo/server.js"; diff --git a/cli/compat/testdata/subpath/node_modules/foo/index.js b/cli/compat/testdata/subpath/node_modules/foo/index.js deleted file mode 100644 index e69de29bb..000000000 --- a/cli/compat/testdata/subpath/node_modules/foo/index.js +++ /dev/null diff --git a/cli/compat/testdata/subpath/node_modules/foo/package.json b/cli/compat/testdata/subpath/node_modules/foo/package.json deleted file mode 100644 index 26f2d565a..000000000 --- a/cli/compat/testdata/subpath/node_modules/foo/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "foo", - "main": "index.js" -}
\ No newline at end of file diff --git a/cli/compat/testdata/subpath/node_modules/foo/server.js b/cli/compat/testdata/subpath/node_modules/foo/server.js deleted file mode 100644 index e69de29bb..000000000 --- a/cli/compat/testdata/subpath/node_modules/foo/server.js +++ /dev/null diff --git a/cli/graph_util.rs b/cli/graph_util.rs index 1f49c22a3..f73fd5559 100644 --- a/cli/graph_util.rs +++ b/cli/graph_util.rs @@ -441,20 +441,6 @@ impl GraphData { None } - // TODO(bartlomieju): after saving translated source - // it's never removed, potentially leading to excessive - // memory consumption - pub fn add_cjs_esm_translation( - &mut self, - specifier: &ModuleSpecifier, - source: String, - ) { - let prev = self - .cjs_esm_translations - .insert(specifier.to_owned(), source); - assert!(prev.is_none()); - } - pub fn get_cjs_esm_translation<'a>( &'a self, specifier: &ModuleSpecifier, diff --git a/cli/main.rs b/cli/main.rs index f089eeed6..98b5325b0 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -5,7 +5,6 @@ mod auth_tokens; mod cache; mod cdp; mod checksum; -mod compat; mod deno_dir; mod deno_std; mod diagnostics; @@ -806,8 +805,6 @@ async fn run_command( return run_with_watch(flags, run_flags.script).await; } - // TODO(bartlomieju): it should not be resolved here if we're in compat mode - // because it might be a bare specifier // TODO(bartlomieju): actually I think it will also fail if there's an import // map specified and bare specifier is used on the command line - this should // probably call `ProcState::resolve` instead diff --git a/cli/node/errors.rs b/cli/node/errors.rs index d7d1bbd05..f14e6e92e 100644 --- a/cli/node/errors.rs +++ b/cli/node/errors.rs @@ -22,27 +22,6 @@ pub fn err_invalid_module_specifier( type_error(msg) } -pub fn err_invalid_package_config( - path: &str, - maybe_base: Option<String>, - maybe_message: Option<String>, -) -> AnyError { - let mut msg = format!( - "[ERR_INVALID_PACKAGE_CONFIG] Invalid package config {}", - path - ); - - if let Some(base) = maybe_base { - msg = format!("{} while importing {}", msg, base); - } - - if let Some(message) = maybe_message { - msg = format!("{}. {}", msg, message); - } - - generic_error(msg) -} - pub fn err_module_not_found(path: &str, base: &str, typ: &str) -> AnyError { generic_error(format!( "[ERR_MODULE_NOT_FOUND] Cannot find {} \"{}\" imported from \"{}\"", @@ -69,73 +48,3 @@ pub fn err_unsupported_esm_url_scheme(url: &Url) -> AnyError { msg = format!("{}. Received protocol '{}'", msg, url.scheme()); generic_error(msg) } - -pub fn err_invalid_package_target( - pkg_path: String, - key: String, - target: String, - is_import: bool, - maybe_base: Option<String>, -) -> AnyError { - let rel_error = !is_import && !target.is_empty() && !target.starts_with("./"); - let mut msg = "[ERR_INVALID_PACKAGE_TARGET]".to_string(); - - if key == "." { - assert!(!is_import); - msg = format!("{} Invalid \"exports\" main target {} defined in the package config {}package.json", msg, target, pkg_path) - } else { - let ie = if is_import { "imports" } else { "exports" }; - msg = format!("{} Invalid \"{}\" target {} defined for '{}' in the package config {}package.json", msg, ie, target, key, pkg_path) - }; - - if let Some(base) = maybe_base { - msg = format!("{} imported from {}", msg, base); - }; - if rel_error { - msg = format!("{}; target must start with \"./\"", msg); - } - - generic_error(msg) -} - -pub fn err_package_path_not_exported( - pkg_path: String, - subpath: String, - maybe_base: Option<String>, -) -> AnyError { - let mut msg = "[ERR_PACKAGE_PATH_NOT_EXPORTED]".to_string(); - - if subpath == "." { - msg = format!( - "{} No \"exports\" main defined in {}package.json", - msg, pkg_path - ); - } else { - msg = format!("{} Package subpath \'{}\' is not defined by \"exports\" in {}package.json", msg, subpath, pkg_path); - }; - - if let Some(base) = maybe_base { - msg = format!("{} imported from {}", msg, base); - } - - generic_error(msg) -} - -pub fn err_package_import_not_defined( - specifier: &str, - package_path: Option<String>, - base: &str, -) -> AnyError { - let mut msg = format!( - "[ERR_PACKAGE_IMPORT_NOT_DEFINED] Package import specifier \"{}\" is not defined in", - specifier - ); - - if let Some(package_path) = package_path { - msg = format!("{} in package {}package.json", msg, package_path); - } - - msg = format!("{} imported from {}", msg, base); - - type_error(msg) -} diff --git a/cli/proc_state.rs b/cli/proc_state.rs index 7d29cd89f..dc0072c4a 100644 --- a/cli/proc_state.rs +++ b/cli/proc_state.rs @@ -9,8 +9,6 @@ use crate::cache::EmitCache; use crate::cache::FastInsecureHasher; use crate::cache::ParsedSourceCache; use crate::cache::TypeCheckCache; -use crate::compat; -use crate::compat::NodeEsmResolver; use crate::deno_dir; use crate::emit::emit_parsed_source; use crate::emit::TsConfigType; @@ -186,9 +184,6 @@ impl ProcState { // FIXME(bartlomieju): `NodeEsmResolver` is not aware of JSX resolver // created below - let node_resolver = NodeEsmResolver::new( - maybe_import_map.clone().map(ImportMapResolver::new), - ); let maybe_import_map_resolver = maybe_import_map.clone().map(ImportMapResolver::new); let maybe_jsx_resolver = cli_options @@ -196,9 +191,7 @@ impl ProcState { .map(|cfg| JsxResolver::new(cfg, maybe_import_map_resolver.clone())); let maybe_resolver: Option< Arc<dyn deno_graph::source::Resolver + Send + Sync>, - > = if cli_options.compat() { - Some(Arc::new(node_resolver)) - } else if let Some(jsx_resolver) = maybe_jsx_resolver { + > = if let Some(jsx_resolver) = maybe_jsx_resolver { // the JSX resolver offloads to the import map if present, otherwise uses // the default Deno explicit import resolution. Some(Arc::new(jsx_resolver)) @@ -286,7 +279,7 @@ impl ProcState { // One might argue that this is a code smell, and I would agree. However // due to flux in "Node compatibility" it's not clear where it should be // decided what `ModuleKind` is decided for root specifier. - let roots = roots + let roots: Vec<(deno_core::url::Url, deno_graph::ModuleKind)> = roots .into_iter() .map(|r| { if let Some(resolver) = &maybe_resolver { @@ -306,13 +299,6 @@ impl ProcState { // TODO(bartlomieju): this is very make-shift, is there an existing API // that we could include it like with "maybe_imports"? - let roots = if self.options.compat() { - let mut r = vec![(compat::GLOBAL_URL.clone(), ModuleKind::Esm)]; - r.extend(roots); - r - } else { - roots - }; if !reload_on_watch { let graph_data = self.graph_data.read(); if self.options.type_check_mode() == TypeCheckMode::None @@ -389,32 +375,6 @@ impl ProcState { ) .await; - let needs_cjs_esm_translation = graph - .modules() - .iter() - .any(|m| m.kind == ModuleKind::CommonJs); - - if needs_cjs_esm_translation { - for module in graph.modules() { - // TODO(bartlomieju): this is overly simplistic heuristic, once we are - // in compat mode, all files ending with plain `.js` extension are - // considered CommonJs modules. Which leads to situation where valid - // ESM modules with `.js` extension might undergo translation (it won't - // work in this situation). - if module.kind == ModuleKind::CommonJs { - let translated_source = compat::translate_cjs_to_esm( - &self.file_fetcher, - &module.specifier, - module.maybe_source.as_ref().unwrap().to_string(), - module.media_type, - )?; - let mut graph_data = self.graph_data.write(); - graph_data - .add_cjs_esm_translation(&module.specifier, translated_source); - } - } - } - // If there was a locker, validate the integrity of all the modules in the // locker. graph_lock_or_exit(&graph); diff --git a/cli/tests/integration/compat_tests.rs b/cli/tests/integration/compat_tests.rs deleted file mode 100644 index 88514832f..000000000 --- a/cli/tests/integration/compat_tests.rs +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. - -use crate::itest; -use deno_core::url::Url; -use test_util as util; - -/// Tests in this file should use `std_file_url` to override `DENO_NODE_COMPAT_URL` -/// env variable. This speeds up tests significantly as they no longer -/// download contents of `deno_std` from `https://deno.land` in each test. - -/// Return a file URL pointing to "std" submodule -/// in "test_util" directory. It must have a trailing slash. -fn std_file_url() -> String { - let u = Url::from_directory_path(util::std_path()).unwrap(); - u.to_string() -} - -itest!(globals { - args: "run --compat --no-check --unstable --allow-read --allow-env compat/globals.ts", - output: "compat/globals.out", - envs: vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())], -}); - -itest!(fs_promises { - args: "run --compat --no-check --unstable -A compat/fs_promises.mjs", - output: "compat/fs_promises.out", - envs: vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())], -}); - -// https://github.com/denoland/deno/issues/12494 -itest_flaky!(node_prefix_fs_promises { - args: "run --compat --no-check --unstable -A compat/node_fs_promises.mjs", - output: "compat/fs_promises.out", - envs: vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())], -}); - -itest!(compat_with_import_map_and_https_imports { - args: "run --quiet --no-check --compat --unstable -A --import-map=compat/import_map.json compat/import_map_https_imports.mjs", - output: "compat/import_map_https_imports.out", - envs: vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())], -}); - -itest!(compat_dyn_import_rejects_with_node_compatible_error { - args: - "run --quiet --no-check --compat --unstable -A compat/dyn_import_reject.js", - output: "compat/dyn_import_reject.out", - envs: vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())], -}); - -itest!(import_esm_from_cjs { - args: - "run --compat --unstable -A --quiet compat/import_esm_from_cjs/index.js", - output_str: Some("function\n"), - envs: vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())], -}); - -itest!(test_runner_cjs { - args: "test --compat --unstable -A --quiet compat/test_runner/cjs.js", - exit_code: 1, - output: "compat/test_runner/cjs.out", - envs: vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())], -}); - -itest!(test_runner_esm { - args: "test --compat --unstable -A --quiet compat/test_runner/esm.mjs", - exit_code: 1, - output: "compat/test_runner/esm.out", - envs: vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())], -}); - -// Top level assertion test mostly just make sure that the test runner finishes correctly on compat mode -// when there is no tests -itest!(top_level_assertion_cjs { - args: "test --compat --unstable -A --quiet compat/test_runner/top_level_assertion_cjs.js", - exit_code: 0, - output: "compat/test_runner/top_level_assertion_cjs.out", - envs: vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())], -}); - -itest!(top_level_assertion_esm { - args: "test --compat --unstable -A --quiet compat/test_runner/top_level_assertion_esm.mjs", - exit_code: 0, - output: "compat/test_runner/top_level_assertion_esm.out", - envs: vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())], -}); - -itest!(top_level_fail_cjs { - args: "test --compat --unstable -A --quiet compat/test_runner/top_level_fail_cjs.js", - exit_code: 1, - output: "compat/test_runner/top_level_fail_cjs.out", - envs: vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())], -}); - -itest!(top_level_fail_esm { - args: "test --compat --unstable -A --quiet compat/test_runner/top_level_fail_esm.mjs", - exit_code: 1, - output: "compat/test_runner/top_level_fail_esm.out", - envs: vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())], -}); - -itest!(compat_worker { - args: "run --compat --unstable -A --quiet --no-check compat/worker/worker_test.mjs", - output: "compat/worker/worker_test.out", - envs: vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())], -}); - -itest!(cjs_esm_interop { - args: - "run --compat --unstable -A --quiet --no-check compat/import_cjs_from_esm/main.mjs", - output: "compat/import_cjs_from_esm.out", - envs: vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())], -}); - -itest!(cjs_esm_interop_dynamic { - args: - "run --compat --unstable -A --quiet --no-check compat/import_cjs_from_esm/main_dynamic.mjs", - output: "compat/import_cjs_from_esm.out", - envs: vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())], -}); - -#[test] -fn globals_in_repl() { - let (out, _err) = util::run_and_collect_output_with_args( - true, - vec!["repl", "--compat", "--unstable", "--no-check", "--quiet"], - Some(vec!["global.window == window"]), - Some(vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())]), - false, - ); - assert!(out.contains("true")); -} - -#[test] -fn require_in_repl() { - let (out, _err) = util::run_and_collect_output_with_args( - true, - vec!["repl", "--compat", "--unstable", "--quiet"], - Some(vec![ - "const foo = require('./compat/import_esm_from_cjs/index');", - ]), - Some(vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())]), - false, - ); - assert!(out.contains("function")); -} - -#[test] -fn node_compat_url() { - let (out, err) = util::run_and_collect_output_with_args( - false, - vec!["repl", "--compat", "--unstable", "--no-check", "--quiet"], - None, - Some(vec![( - "DENO_NODE_COMPAT_URL".to_string(), - "file:///non_existent/".to_string(), - )]), - false, - ); - assert!(out.is_empty()); - assert!(!err.is_empty()); - assert!(err.contains("file:///non_existent/node/global.ts")); -} - -#[test] -fn native_modules_as_global_vars() { - let (out, _err) = util::run_and_collect_output_with_args( - true, - vec!["repl", "--compat", "--unstable", "--quiet"], - Some(vec!["if(cluster && v8 && sys) { true } else { false }"]), - Some(vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())]), - false, - ); - assert!(out.contains("true")); -} - -#[ignore] // todo(dsherret): re-enable -#[test] -fn ext_node_cjs_execution() { - let (out, _err) = util::run_and_collect_output_with_args( - true, - vec![ - "run", - "-A", - "--unstable", - "--quiet", - "commonjs/init.js", - "./example.js", - ], - None, - Some(vec![("DENO_NODE_COMPAT_URL".to_string(), std_file_url())]), - false, - ); - assert!(out.contains("{ hello: \"world\" }")); -} diff --git a/cli/tests/integration/mod.rs b/cli/tests/integration/mod.rs index 742c0e3a7..84ec34f2b 100644 --- a/cli/tests/integration/mod.rs +++ b/cli/tests/integration/mod.rs @@ -60,8 +60,6 @@ mod bundle; mod cache; #[path = "check_tests.rs"] mod check; -#[path = "compat_tests.rs"] -mod compat; #[path = "compile_tests.rs"] mod compile; #[path = "coverage_tests.rs"] diff --git a/cli/tests/testdata/compat/dyn_import_reject.js b/cli/tests/testdata/compat/dyn_import_reject.js deleted file mode 100644 index f9a99f0da..000000000 --- a/cli/tests/testdata/compat/dyn_import_reject.js +++ /dev/null @@ -1,4 +0,0 @@ -import("./foobar.js").catch((e) => { - console.log(e); - console.log(e.code); -}); diff --git a/cli/tests/testdata/compat/dyn_import_reject.out b/cli/tests/testdata/compat/dyn_import_reject.out deleted file mode 100644 index 1324c8aeb..000000000 --- a/cli/tests/testdata/compat/dyn_import_reject.out +++ /dev/null @@ -1,2 +0,0 @@ -TypeError: [ERR_MODULE_NOT_FOUND] Cannot find module "file://[WILDCARD]/testdata/compat/foobar.js" imported from "file://[WILDCARD]/testdata/compat/dyn_import_reject.js" -ERR_MODULE_NOT_FOUND diff --git a/cli/tests/testdata/compat/fs_promises.mjs b/cli/tests/testdata/compat/fs_promises.mjs deleted file mode 100644 index 3f7b4c935..000000000 --- a/cli/tests/testdata/compat/fs_promises.mjs +++ /dev/null @@ -1,3 +0,0 @@ -import fs from "fs/promises"; -const data = await fs.readFile("compat/test.txt", "utf-8"); -console.log(data); diff --git a/cli/tests/testdata/compat/fs_promises.out b/cli/tests/testdata/compat/fs_promises.out deleted file mode 100644 index 368d06776..000000000 --- a/cli/tests/testdata/compat/fs_promises.out +++ /dev/null @@ -1,2 +0,0 @@ -[WILDCARD] -This is some example text that will be read using compatiblity mode. diff --git a/cli/tests/testdata/compat/globals.out b/cli/tests/testdata/compat/globals.out deleted file mode 100644 index 32230fda3..000000000 --- a/cli/tests/testdata/compat/globals.out +++ /dev/null @@ -1,9 +0,0 @@ -[WILDCARD] -process { -[WILDCARD] -} -[Function: Buffer] { -[WILDCARD] -} -[Function: setImmediate] -[Function: clearTimeout] diff --git a/cli/tests/testdata/compat/globals.ts b/cli/tests/testdata/compat/globals.ts deleted file mode 100644 index bd80fb3d7..000000000 --- a/cli/tests/testdata/compat/globals.ts +++ /dev/null @@ -1,4 +0,0 @@ -console.log(process); -console.log(Buffer); -console.log(setImmediate); -console.log(clearImmediate); diff --git a/cli/tests/testdata/compat/import_cjs_from_esm.out b/cli/tests/testdata/compat/import_cjs_from_esm.out deleted file mode 100644 index ffaa5e406..000000000 --- a/cli/tests/testdata/compat/import_cjs_from_esm.out +++ /dev/null @@ -1 +0,0 @@ -{ a: "A", b: "B", foo: "foo", bar: "bar", fizz: { buzz: "buzz", fizz: "FIZZ" } } diff --git a/cli/tests/testdata/compat/import_cjs_from_esm/imported.js b/cli/tests/testdata/compat/import_cjs_from_esm/imported.js deleted file mode 100644 index 49ab4c782..000000000 --- a/cli/tests/testdata/compat/import_cjs_from_esm/imported.js +++ /dev/null @@ -1,9 +0,0 @@ -exports = { - a: "A", - b: "B", -}; -exports.foo = "foo"; -exports.bar = "bar"; -exports.fizz = require("./reexports.js"); - -console.log(exports); diff --git a/cli/tests/testdata/compat/import_cjs_from_esm/main.mjs b/cli/tests/testdata/compat/import_cjs_from_esm/main.mjs deleted file mode 100644 index 6fbed1b7c..000000000 --- a/cli/tests/testdata/compat/import_cjs_from_esm/main.mjs +++ /dev/null @@ -1 +0,0 @@ -import "./imported.js"; diff --git a/cli/tests/testdata/compat/import_cjs_from_esm/main_dynamic.mjs b/cli/tests/testdata/compat/import_cjs_from_esm/main_dynamic.mjs deleted file mode 100644 index b94033268..000000000 --- a/cli/tests/testdata/compat/import_cjs_from_esm/main_dynamic.mjs +++ /dev/null @@ -1,2 +0,0 @@ -const url = import.meta.resolve("./imported.js"); -await import(url); diff --git a/cli/tests/testdata/compat/import_cjs_from_esm/reexports.js b/cli/tests/testdata/compat/import_cjs_from_esm/reexports.js deleted file mode 100644 index 62edb7708..000000000 --- a/cli/tests/testdata/compat/import_cjs_from_esm/reexports.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require("./reexports2.js"); diff --git a/cli/tests/testdata/compat/import_cjs_from_esm/reexports2.js b/cli/tests/testdata/compat/import_cjs_from_esm/reexports2.js deleted file mode 100644 index 183d833b0..000000000 --- a/cli/tests/testdata/compat/import_cjs_from_esm/reexports2.js +++ /dev/null @@ -1,2 +0,0 @@ -exports.buzz = "buzz"; -exports.fizz = "FIZZ"; diff --git a/cli/tests/testdata/compat/import_esm_from_cjs/index.js b/cli/tests/testdata/compat/import_esm_from_cjs/index.js deleted file mode 100644 index 4ba03e104..000000000 --- a/cli/tests/testdata/compat/import_esm_from_cjs/index.js +++ /dev/null @@ -1 +0,0 @@ -require("pure-cjs"); diff --git a/cli/tests/testdata/compat/import_esm_from_cjs/node_modules/pure-cjs/index.js b/cli/tests/testdata/compat/import_esm_from_cjs/node_modules/pure-cjs/index.js deleted file mode 100644 index 35f7c3774..000000000 --- a/cli/tests/testdata/compat/import_esm_from_cjs/node_modules/pure-cjs/index.js +++ /dev/null @@ -1,4 +0,0 @@ -async function run() { - const _result = await import('pure-esm'); -} -run() diff --git a/cli/tests/testdata/compat/import_esm_from_cjs/node_modules/pure-cjs/package.json b/cli/tests/testdata/compat/import_esm_from_cjs/node_modules/pure-cjs/package.json deleted file mode 100644 index e854fd992..000000000 --- a/cli/tests/testdata/compat/import_esm_from_cjs/node_modules/pure-cjs/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "pure-cjs", - "main": "./index.js" -} diff --git a/cli/tests/testdata/compat/import_esm_from_cjs/node_modules/pure-esm/index.js b/cli/tests/testdata/compat/import_esm_from_cjs/node_modules/pure-esm/index.js deleted file mode 100644 index 898097cb5..000000000 --- a/cli/tests/testdata/compat/import_esm_from_cjs/node_modules/pure-esm/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import fs from 'node:fs'; -console.log(typeof fs.chmod); diff --git a/cli/tests/testdata/compat/import_esm_from_cjs/node_modules/pure-esm/package.json b/cli/tests/testdata/compat/import_esm_from_cjs/node_modules/pure-esm/package.json deleted file mode 100644 index a373d3ad9..000000000 --- a/cli/tests/testdata/compat/import_esm_from_cjs/node_modules/pure-esm/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "pure-esm", - "type": "module", - "main": "./index.js" -} diff --git a/cli/tests/testdata/compat/import_map.json b/cli/tests/testdata/compat/import_map.json deleted file mode 100644 index 8488f0140..000000000 --- a/cli/tests/testdata/compat/import_map.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "imports": { - "std/": "https://deno.land/std@0.126.0/" - } -} diff --git a/cli/tests/testdata/compat/import_map_https_imports.mjs b/cli/tests/testdata/compat/import_map_https_imports.mjs deleted file mode 100644 index d8c2a89c2..000000000 --- a/cli/tests/testdata/compat/import_map_https_imports.mjs +++ /dev/null @@ -1,7 +0,0 @@ -import { sortBy } from "std/collections/sort_by.ts"; -import { findSingle } from "https://deno.land/std@0.126.0/collections/find_single.ts"; -import os from "node:os"; - -console.log(sortBy([2, 3, 1], (it) => it)); -console.log(findSingle([2, 3, 1], (it) => it == 2)); -console.log("arch", os.arch()); diff --git a/cli/tests/testdata/compat/import_map_https_imports.out b/cli/tests/testdata/compat/import_map_https_imports.out deleted file mode 100644 index 7ee30676e..000000000 --- a/cli/tests/testdata/compat/import_map_https_imports.out +++ /dev/null @@ -1,3 +0,0 @@ -[ 1, 2, 3 ] -2 -arch [WILDCARD] diff --git a/cli/tests/testdata/compat/node_fs_promises.mjs b/cli/tests/testdata/compat/node_fs_promises.mjs deleted file mode 100644 index b2174b22b..000000000 --- a/cli/tests/testdata/compat/node_fs_promises.mjs +++ /dev/null @@ -1,3 +0,0 @@ -import fs from "node:fs/promises"; -const data = await fs.readFile("compat/test.txt", "utf-8"); -console.log(data); diff --git a/cli/tests/testdata/compat/test.txt b/cli/tests/testdata/compat/test.txt deleted file mode 100644 index 422e7b0c0..000000000 --- a/cli/tests/testdata/compat/test.txt +++ /dev/null @@ -1 +0,0 @@ -This is some example text that will be read using compatiblity mode.
\ No newline at end of file diff --git a/cli/tests/testdata/compat/test_runner/cjs.js b/cli/tests/testdata/compat/test_runner/cjs.js deleted file mode 100644 index 96a1b5112..000000000 --- a/cli/tests/testdata/compat/test_runner/cjs.js +++ /dev/null @@ -1,9 +0,0 @@ -const { strictEqual } = require("assert"); - -Deno.test("Correct assertion", () => { - strictEqual(20, 20); -}); - -Deno.test("Failed assertion", () => { - strictEqual(10, 20); -}); diff --git a/cli/tests/testdata/compat/test_runner/cjs.out b/cli/tests/testdata/compat/test_runner/cjs.out deleted file mode 100644 index 2e1e29e61..000000000 --- a/cli/tests/testdata/compat/test_runner/cjs.out +++ /dev/null @@ -1,27 +0,0 @@ -running 2 tests from ./compat/test_runner/cjs.js -Correct assertion ... ok ([WILDCARD]) -Failed assertion ... FAILED ([WILDCARD]) - - ERRORS - -Failed assertion => ./compat/test_runner/cjs.js:[WILDCARD] -error: AssertionError: Values are not strictly equal: - - - [Diff] Actual / Expected - - -- 10 -+ 20 - - Error.captureStackTrace(this, stackStartFn || stackStartFunction); - ^ -[WILDCARD] - - FAILURES - -Failed assertion => ./compat/test_runner/cjs.js:[WILDCARD] - -FAILED | 1 passed | 1 failed ([WILDCARD]) - -error: Test failed diff --git a/cli/tests/testdata/compat/test_runner/esm.mjs b/cli/tests/testdata/compat/test_runner/esm.mjs deleted file mode 100644 index 54a9468a4..000000000 --- a/cli/tests/testdata/compat/test_runner/esm.mjs +++ /dev/null @@ -1,9 +0,0 @@ -import { strictEqual } from "assert"; - -Deno.test("Correct assertion", () => { - strictEqual(20, 20); -}); - -Deno.test("Failed assertion", () => { - strictEqual(10, 20); -}); diff --git a/cli/tests/testdata/compat/test_runner/esm.out b/cli/tests/testdata/compat/test_runner/esm.out deleted file mode 100644 index e69573da1..000000000 --- a/cli/tests/testdata/compat/test_runner/esm.out +++ /dev/null @@ -1,27 +0,0 @@ -running 2 tests from ./compat/test_runner/esm.mjs -Correct assertion ... ok ([WILDCARD]) -Failed assertion ... FAILED ([WILDCARD]) - - ERRORS - -Failed assertion => ./compat/test_runner/esm.mjs:[WILDCARD] -error: AssertionError: Values are not strictly equal: - - - [Diff] Actual / Expected - - -- 10 -+ 20 - - Error.captureStackTrace(this, stackStartFn || stackStartFunction); - ^ -[WILDCARD] - - FAILURES - -Failed assertion => ./compat/test_runner/esm.mjs:[WILDCARD] - -FAILED | 1 passed | 1 failed ([WILDCARD]) - -error: Test failed diff --git a/cli/tests/testdata/compat/test_runner/top_level_assertion_cjs.js b/cli/tests/testdata/compat/test_runner/top_level_assertion_cjs.js deleted file mode 100644 index 318e72d86..000000000 --- a/cli/tests/testdata/compat/test_runner/top_level_assertion_cjs.js +++ /dev/null @@ -1,4 +0,0 @@ -const { notStrictEqual, strictEqual } = require("assert"); - -notStrictEqual(require.main, module, "The module was loaded as a main module"); -strictEqual(20, 20); diff --git a/cli/tests/testdata/compat/test_runner/top_level_assertion_cjs.out b/cli/tests/testdata/compat/test_runner/top_level_assertion_cjs.out deleted file mode 100644 index f74853cfd..000000000 --- a/cli/tests/testdata/compat/test_runner/top_level_assertion_cjs.out +++ /dev/null @@ -1,4 +0,0 @@ -running 0 tests from [WILDCARD] - -ok | 0 passed | 0 failed ([WILDCARD]) - diff --git a/cli/tests/testdata/compat/test_runner/top_level_assertion_esm.mjs b/cli/tests/testdata/compat/test_runner/top_level_assertion_esm.mjs deleted file mode 100644 index 8c217fd55..000000000 --- a/cli/tests/testdata/compat/test_runner/top_level_assertion_esm.mjs +++ /dev/null @@ -1,4 +0,0 @@ -import assert, { strictEqual } from "assert"; - -assert(!import.meta.main, "The module was loaded as a main module"); -strictEqual(20, 20); diff --git a/cli/tests/testdata/compat/test_runner/top_level_assertion_esm.out b/cli/tests/testdata/compat/test_runner/top_level_assertion_esm.out deleted file mode 100644 index f74853cfd..000000000 --- a/cli/tests/testdata/compat/test_runner/top_level_assertion_esm.out +++ /dev/null @@ -1,4 +0,0 @@ -running 0 tests from [WILDCARD] - -ok | 0 passed | 0 failed ([WILDCARD]) - diff --git a/cli/tests/testdata/compat/test_runner/top_level_fail_cjs.js b/cli/tests/testdata/compat/test_runner/top_level_fail_cjs.js deleted file mode 100644 index 20f809794..000000000 --- a/cli/tests/testdata/compat/test_runner/top_level_fail_cjs.js +++ /dev/null @@ -1,4 +0,0 @@ -const { notStrictEqual, strictEqual } = require("assert"); - -notStrictEqual(require.main, module, "The module was loaded as a main module"); -strictEqual(10, 20); diff --git a/cli/tests/testdata/compat/test_runner/top_level_fail_cjs.out b/cli/tests/testdata/compat/test_runner/top_level_fail_cjs.out deleted file mode 100644 index e1777d98a..000000000 --- a/cli/tests/testdata/compat/test_runner/top_level_fail_cjs.out +++ /dev/null @@ -1,27 +0,0 @@ -Uncaught error from ./compat/test_runner/top_level_fail_cjs.js FAILED - - ERRORS - -./compat/test_runner/top_level_fail_cjs.js (uncaught error) -error: (in promise) AssertionError: Values are not strictly equal: - - - [Diff] Actual / Expected - - -- 10 -+ 20 - - Error.captureStackTrace(this, stackStartFn || stackStartFunction); - ^ - at [WILDCARD] -This error was not caught from a test and caused the test runner to fail on the referenced module. -It most likely originated from a dangling promise, event/timeout handler or top-level code. - - FAILURES - -./compat/test_runner/top_level_fail_cjs.js (uncaught error) - -FAILED | 0 passed | 1 failed ([WILDCARD]) - -error: Test failed diff --git a/cli/tests/testdata/compat/test_runner/top_level_fail_esm.mjs b/cli/tests/testdata/compat/test_runner/top_level_fail_esm.mjs deleted file mode 100644 index 918d8c6a8..000000000 --- a/cli/tests/testdata/compat/test_runner/top_level_fail_esm.mjs +++ /dev/null @@ -1,4 +0,0 @@ -import assert, { strictEqual } from "assert"; - -assert(!import.meta.main, "The module was loaded as a main module"); -strictEqual(10, 20); diff --git a/cli/tests/testdata/compat/test_runner/top_level_fail_esm.out b/cli/tests/testdata/compat/test_runner/top_level_fail_esm.out deleted file mode 100644 index d34de2c21..000000000 --- a/cli/tests/testdata/compat/test_runner/top_level_fail_esm.out +++ /dev/null @@ -1,27 +0,0 @@ -Uncaught error from ./compat/test_runner/top_level_fail_esm.mjs FAILED - - ERRORS - -./compat/test_runner/top_level_fail_esm.mjs (uncaught error) -error: AssertionError: Values are not strictly equal: - - - [Diff] Actual / Expected - - -- 10 -+ 20 - - Error.captureStackTrace(this, stackStartFn || stackStartFunction); - ^ - at [WILDCARD] -This error was not caught from a test and caused the test runner to fail on the referenced module. -It most likely originated from a dangling promise, event/timeout handler or top-level code. - - FAILURES - -./compat/test_runner/top_level_fail_esm.mjs (uncaught error) - -FAILED | 0 passed | 1 failed ([WILDCARD]) - -error: Test failed diff --git a/cli/tests/testdata/compat/worker/worker.mjs b/cli/tests/testdata/compat/worker/worker.mjs deleted file mode 100644 index eb7cfed19..000000000 --- a/cli/tests/testdata/compat/worker/worker.mjs +++ /dev/null @@ -1,9 +0,0 @@ -console.log("hello from worker"); - -self.onmessage = (e) => { - if (e.data != "hello") { - throw new Error("wrong message"); - } - - self.postMessage({ pid: process.pid }); -} diff --git a/cli/tests/testdata/compat/worker/worker_test.mjs b/cli/tests/testdata/compat/worker/worker_test.mjs deleted file mode 100644 index 8613dde0c..000000000 --- a/cli/tests/testdata/compat/worker/worker_test.mjs +++ /dev/null @@ -1,18 +0,0 @@ -import { deferred } from "../../../../../test_util/std/async/deferred.ts"; - -const promise = deferred(); -const url = import.meta.resolve("./worker.mjs"); -const worker = new Worker(url, { type: "module" }); - -worker.onmessage = (e) => { - const pid = e.data.pid; - if (typeof pid != "number") { - throw new Error("pid is not a number"); - } - console.log("process.pid from worker:", pid); - promise.resolve(); -}; - -worker.postMessage("hello"); -await promise; -worker.terminate(); diff --git a/cli/tests/testdata/compat/worker/worker_test.out b/cli/tests/testdata/compat/worker/worker_test.out deleted file mode 100644 index 373841945..000000000 --- a/cli/tests/testdata/compat/worker/worker_test.out +++ /dev/null @@ -1,2 +0,0 @@ -hello from worker -process.pid from worker: [WILDCARD] diff --git a/cli/tools/installer.rs b/cli/tools/installer.rs index df4b46332..6928624ea 100644 --- a/cli/tools/installer.rs +++ b/cli/tools/installer.rs @@ -333,10 +333,6 @@ fn resolve_shim_data( executable_args.push("--no-prompt".to_string()); } - if flags.compat { - executable_args.push("--compat".to_string()); - } - if !flags.v8_flags.is_empty() { executable_args.push(format!("--v8-flags={}", flags.v8_flags.join(","))); } @@ -592,7 +588,6 @@ mod tests { allow_read: Some(vec![]), type_check_mode: TypeCheckMode::None, log_level: Some(Level::Error), - compat: true, ..Flags::default() }, &InstallFlags { @@ -613,7 +608,6 @@ mod tests { "--allow-read", "--allow-net", "--quiet", - "--compat", "http://localhost:4545/echo_server.ts", "--foobar", ] diff --git a/cli/tools/standalone.rs b/cli/tools/standalone.rs index 99f2ce33d..6046654b9 100644 --- a/cli/tools/standalone.rs +++ b/cli/tools/standalone.rs @@ -275,7 +275,6 @@ pub fn compile_to_runtime_flags( lock: None, log_level: flags.log_level, type_check_mode: TypeCheckMode::Local, - compat: flags.compat, unsafely_ignore_certificate_errors: flags .unsafely_ignore_certificate_errors .clone(), diff --git a/cli/worker.rs b/cli/worker.rs index d36639821..22070fc18 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -23,7 +23,6 @@ use deno_runtime::BootstrapOptions; use crate::args::DenoSubcommand; use crate::checksum; -use crate::compat; use crate::errors; use crate::module_loader::CliModuleLoader; use crate::node; @@ -52,15 +51,6 @@ impl CliMainWorker { } pub async fn setup_repl(&mut self) -> Result<(), AnyError> { - if self.ps.options.compat() { - self.worker.execute_side_module(&compat::GLOBAL_URL).await?; - compat::add_global_require( - &mut self.worker.js_runtime, - self.main_module.as_str(), - )?; - self.worker.run_event_loop(false).await?; - compat::setup_builtin_modules(&mut self.worker.js_runtime)?; - } self.worker.run_event_loop(false).await?; Ok(()) } @@ -70,39 +60,7 @@ impl CliMainWorker { self.maybe_setup_coverage_collector().await?; log::debug!("main_module {}", self.main_module); - if self.ps.options.compat() { - // TODO(bartlomieju): fix me - assert_eq!(self.main_module.scheme(), "file"); - - // Set up Node globals - self.worker.execute_side_module(&compat::GLOBAL_URL).await?; - // And `module` module that we'll use for checking which - // loader to use and potentially load CJS module with. - // This allows to skip permission check for `--allow-net` - // which would otherwise be requested by dynamically importing - // this file. - self.worker.execute_side_module(&compat::MODULE_URL).await?; - - let use_esm_loader = - compat::check_if_should_use_esm_loader(&self.main_module)?; - - if use_esm_loader { - // ES module execution in Node compatiblity mode - self.worker.execute_main_module(&self.main_module).await?; - } else { - // CJS module execution in Node compatiblity mode - compat::load_cjs_module( - &mut self.worker.js_runtime, - &self - .main_module - .to_file_path() - .unwrap() - .display() - .to_string(), - true, - )?; - } - } else if self.is_main_cjs { + if self.is_main_cjs { self.initialize_main_module_for_node().await?; node::load_cjs_module_from_ext_node( &mut self.worker.js_runtime, @@ -160,13 +118,6 @@ impl CliMainWorker { /// Execute the given main module emitting load and unload events before and after execution /// respectively. pub async fn execute(&mut self) -> Result<(), AnyError> { - if self.inner.ps.options.compat() { - self - .inner - .worker - .execute_side_module(&compat::GLOBAL_URL) - .await?; - } self.inner.execute_main_module_possibly_with_npm().await?; self .inner @@ -240,32 +191,8 @@ impl CliMainWorker { // We only execute the specifier as a module if it is tagged with TestMode::Module or // TestMode::Both. if mode != TestMode::Documentation { - if self.ps.options.compat() { - self.worker.execute_side_module(&compat::GLOBAL_URL).await?; - self.worker.execute_side_module(&compat::MODULE_URL).await?; - - let use_esm_loader = - compat::check_if_should_use_esm_loader(&self.main_module)?; - - if use_esm_loader { - self.worker.execute_side_module(&self.main_module).await?; - } else { - compat::load_cjs_module( - &mut self.worker.js_runtime, - &self - .main_module - .to_file_path() - .unwrap() - .display() - .to_string(), - false, - )?; - self.worker.run_event_loop(false).await?; - } - } else { - // We execute the module module as a side module so that import.meta.main is not set. - self.execute_side_module_possibly_with_npm().await?; - } + // We execute the module module as a side module so that import.meta.main is not set. + self.execute_side_module_possibly_with_npm().await?; } self.worker.dispatch_load_event(&located_script_name!())?; @@ -331,32 +258,8 @@ impl CliMainWorker { pub async fn run_bench_specifier(&mut self) -> Result<(), AnyError> { self.worker.enable_bench(); - if self.ps.options.compat() { - self.worker.execute_side_module(&compat::GLOBAL_URL).await?; - self.worker.execute_side_module(&compat::MODULE_URL).await?; - - let use_esm_loader = - compat::check_if_should_use_esm_loader(&self.main_module)?; - - if use_esm_loader { - self.worker.execute_side_module(&self.main_module).await?; - } else { - compat::load_cjs_module( - &mut self.worker.js_runtime, - &self - .main_module - .to_file_path() - .unwrap() - .display() - .to_string(), - false, - )?; - self.worker.run_event_loop(false).await?; - } - } else { - // We execute the module module as a side module so that import.meta.main is not set. - self.execute_side_module_possibly_with_npm().await?; - } + // We execute the module module as a side module so that import.meta.main is not set. + self.execute_side_module_possibly_with_npm().await?; self.worker.dispatch_load_event(&located_script_name!())?; self.worker.run_benchmarks().await?; @@ -543,20 +446,13 @@ pub async fn create_main_worker( }) } +// TODO(bartlomieju): this callback could have default value +// and not be required fn create_web_worker_preload_module_callback( - ps: ProcState, + _ps: ProcState, ) -> Arc<WorkerEventCb> { - let compat = ps.options.compat(); - - Arc::new(move |mut worker| { - let fut = async move { - if compat { - worker.execute_side_module(&compat::GLOBAL_URL).await?; - worker.execute_side_module(&compat::MODULE_URL).await?; - } - - Ok(worker) - }; + Arc::new(move |worker| { + let fut = async move { Ok(worker) }; LocalFutureObj::new(Box::new(fut)) }) } diff --git a/ext/node/package_json.rs b/ext/node/package_json.rs index 15b5ab920..e5f9214fb 100644 --- a/ext/node/package_json.rs +++ b/ext/node/package_json.rs @@ -11,7 +11,6 @@ use serde::Serialize; use std::io::ErrorKind; use std::path::PathBuf; -// TODO(bartlomieju): deduplicate with cli/compat/esm_resolver.rs #[derive(Clone, Debug, Serialize)] pub struct PackageJson { pub exists: bool, |