Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: improved support for cjs and cts modules #26558

Merged
merged 56 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
c11079d
refactor: prefer parsing as `Program` over `Module`
dsherret Oct 22, 2024
904c316
more updates
dsherret Oct 22, 2024
4335aa0
Starting on this, but going to revert.
dsherret Oct 22, 2024
29876a5
Merge branch 'main' into refactor_handle_program_more
dsherret Oct 25, 2024
7410544
compiling
dsherret Oct 25, 2024
34b1a88
working
dsherret Oct 25, 2024
873da6b
Start on translating code
dsherret Oct 25, 2024
342c81c
perf: pass transpiled modules to deno_core as a string
dsherret Oct 25, 2024
3cd7c94
update
dsherret Oct 25, 2024
eedcdca
Merge branch 'main' into perf_pass_transpiled_modules_to_deno_core_as…
dsherret Oct 25, 2024
d1d7b36
Merge branch 'main' into refactor_handle_program_more
dsherret Oct 25, 2024
8540344
update
dsherret Oct 25, 2024
3a83933
Merge branch 'perf_pass_transpiled_modules_to_deno_core_as_string' in…
dsherret Oct 25, 2024
af06589
better cts support
dsherret Oct 25, 2024
21b5d06
Merge branch 'main' into refactor_handle_program_more
dsherret Oct 26, 2024
eb9f9ff
fix(check): expose more globals from @types/node
dsherret Oct 28, 2024
eaa4ea7
Merge branch 'fix_expose_types_node_globals' into refactor_handle_pro…
dsherret Oct 28, 2024
941eefd
Merge branch 'main' into refactor_handle_program_more
dsherret Oct 28, 2024
9e7ad6f
support in deno compile
dsherret Oct 28, 2024
39e928f
working test
dsherret Oct 28, 2024
bd824a6
updates to pass around the module kind
dsherret Oct 29, 2024
01c773f
Create PackageJsonResolver
dsherret Oct 29, 2024
63acd1a
Use fs more
dsherret Oct 29, 2024
84f1f70
better cjs/esm tracking
dsherret Oct 29, 2024
ebaa01f
compiling large refactor
dsherret Oct 29, 2024
cf9fd71
fix bug
dsherret Oct 29, 2024
e0b0fb5
passing tests
dsherret Oct 29, 2024
c8361e8
Start working on removing `NodeResolution`
dsherret Oct 29, 2024
e513f6a
commit and going to revert to simplify
dsherret Oct 29, 2024
e7e1299
More passing tests
dsherret Oct 29, 2024
fd26e78
going to revert
dsherret Oct 29, 2024
d23a91a
Add LspCjsTracker
dsherret Oct 29, 2024
d56c766
remove resolving media type in lsp based on node resolution
dsherret Oct 29, 2024
9e7d896
fix json imports
dsherret Oct 29, 2024
4d3097a
Remove url_to_node_resolution
dsherret Oct 30, 2024
157dfd5
update test
dsherret Oct 30, 2024
eb2a381
Merge branch 'main' into refactor_handle_program_more
dsherret Oct 30, 2024
41b7742
lint
dsherret Oct 30, 2024
5582eda
bump deno_ast
dsherret Oct 30, 2024
fc4ff68
Fix node compat tests
dsherret Oct 30, 2024
220e782
do not require --allow-read if requiring modules found in the module …
dsherret Oct 30, 2024
9aaa4d7
more tests
dsherret Oct 30, 2024
1e28b03
Merge branch 'main' into refactor_handle_program_more
dsherret Oct 30, 2024
5049c3c
fix small issues and add jsx tests
dsherret Oct 30, 2024
ecde7bd
Merge branch 'main' into refactor_handle_program_more
dsherret Oct 30, 2024
adcf6d3
Bump ci
dsherret Oct 30, 2024
2636535
mark main CJS module
bartlomieju Oct 31, 2024
d47411b
add a test for main cjs module
bartlomieju Oct 31, 2024
0693427
Merge branch 'main' into refactor_handle_program_more
dsherret Oct 31, 2024
66c139d
Update
dsherret Oct 31, 2024
b2500dd
Support TsImportEquals
dsherret Oct 31, 2024
5e86e00
Merge branch 'refactor_handle_program_more' of https://github.com/dsh…
dsherret Oct 31, 2024
ef85fc3
Merge branch 'main' into refactor_handle_program_more
dsherret Oct 31, 2024
c21c283
proper support for ts import equals and export equals
dsherret Oct 31, 2024
0411a73
Add some more import equals tests
dsherret Oct 31, 2024
a471da0
Merge branch 'main' into refactor_handle_program_more
dsherret Nov 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .dprint.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"third_party"
],
"plugins": [
"https://plugins.dprint.dev/typescript-0.93.0.wasm",
"https://plugins.dprint.dev/typescript-0.93.1.wasm",
"https://plugins.dprint.dev/json-0.19.4.wasm",
"https://plugins.dprint.dev/markdown-0.17.8.wasm",
"https://plugins.dprint.dev/toml-0.6.3.wasm",
Expand Down
28 changes: 14 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry, this PR is hard to split up into multiple smaller ones. There's so much stuff that's intertwined.

The main themes are using "program" more and determining if a js, jsx, ts, or tsx file is cjs or esm always only happens after loading it now.

Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ license = "MIT"
repository = "https://github.com/denoland/deno"

[workspace.dependencies]
deno_ast = { version = "=0.42.2", features = ["transpiling"] }
deno_ast = { version = "=0.43.1", features = ["transpiling"] }
deno_core = { version = "0.314.2" }

deno_bench_util = { version = "0.168.0", path = "./bench_util" }
deno_lockfile = "=0.23.1"
deno_media_type = { version = "0.1.4", features = ["module_specifier"] }
deno_media_type = { version = "0.2.0", features = ["module_specifier"] }
deno_npm = "=0.25.4"
deno_path_util = "=0.2.1"
deno_permissions = { version = "0.34.0", path = "./runtime/permissions" }
Expand Down Expand Up @@ -111,7 +111,7 @@ console_static_text = "=0.8.1"
dashmap = "5.5.3"
data-encoding = "2.3.3"
data-url = "=0.3.0"
deno_cache_dir = "=0.13.1"
deno_cache_dir = "=0.13.2"
deno_package_json = { version = "0.1.2", default-features = false }
dlopen2 = "0.6.1"
ecb = "=0.1.2"
Expand Down
8 changes: 4 additions & 4 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "proposa
deno_cache_dir = { workspace = true }
deno_config = { version = "=0.37.2", features = ["workspace", "sync"] }
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
deno_doc = { version = "0.154.0", default-features = false, features = ["rust", "html", "syntect"] }
deno_graph = { version = "=0.83.4" }
deno_lint = { version = "=0.67.0", features = ["docs"] }
deno_doc = { version = "0.156.0", default-features = false, features = ["rust", "html", "syntect"] }
deno_graph = { version = "=0.84.0" }
deno_lint = { version = "=0.68.0", features = ["docs"] }
deno_lockfile.workspace = true
deno_npm.workspace = true
deno_package_json.workspace = true
Expand Down Expand Up @@ -107,7 +107,7 @@ dotenvy = "0.15.7"
dprint-plugin-json = "=0.19.4"
dprint-plugin-jupyter = "=0.1.5"
dprint-plugin-markdown = "=0.17.8"
dprint-plugin-typescript = "=0.93.0"
dprint-plugin-typescript = "=0.93.1"
env_logger = "=0.10.0"
fancy-regex = "=0.10.0"
faster-hex.workspace = true
Expand Down
11 changes: 11 additions & 0 deletions cli/args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ pub fn ts_config_to_transpile_and_emit_options(
precompile_jsx_dynamic_props: None,
transform_jsx,
var_decl_imports: false,
// todo(dsherret): support verbatim_module_syntax here properly
bartlomieju marked this conversation as resolved.
Show resolved Hide resolved
verbatim_module_syntax: false,
},
deno_ast::EmitOptions {
inline_sources: options.inline_sources,
Expand Down Expand Up @@ -1595,6 +1597,15 @@ impl CliOptions {
}

pub fn use_byonm(&self) -> bool {
if matches!(
self.sub_command(),
DenoSubcommand::Install(_)
| DenoSubcommand::Add(_)
| DenoSubcommand::Remove(_)
) {
// For `deno install/add/remove` we want to force the managed resolver so it can set up `node_modules/` directory.
return false;
}
if self.node_modules_dir().ok().flatten().is_none()
&& self.maybe_node_modules_folder.is_some()
&& self
Expand Down
6 changes: 4 additions & 2 deletions cli/cache/cache_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl rusqlite::types::FromSql for CacheDBHash {
}

/// What should the cache should do on failure?
#[derive(Default)]
#[derive(Debug, Default)]
pub enum CacheFailure {
/// Return errors if failure mode otherwise unspecified.
#[default]
Expand All @@ -69,6 +69,7 @@ pub enum CacheFailure {
}

/// Configuration SQL and other parameters for a [`CacheDB`].
#[derive(Debug)]
pub struct CacheDBConfiguration {
/// SQL to run for a new database.
pub table_initializer: &'static str,
Expand Down Expand Up @@ -98,6 +99,7 @@ impl CacheDBConfiguration {
}
}

#[derive(Debug)]
enum ConnectionState {
Connected(Connection),
Blackhole,
Expand All @@ -106,7 +108,7 @@ enum ConnectionState {

/// A cache database that eagerly initializes itself off-thread, preventing initialization operations
/// from blocking the main thread.
#[derive(Clone)]
#[derive(Debug, Clone)]
pub struct CacheDB {
// TODO(mmastrac): We can probably simplify our thread-safe implementation here
conn: Arc<Mutex<OnceCell<ConnectionState>>>,
Expand Down
2 changes: 2 additions & 0 deletions cli/cache/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use deno_core::unsync::sync::AtomicFlag;
use super::DiskCache;

/// The cache that stores previously emitted files.
#[derive(Debug)]
pub struct EmitCache {
disk_cache: DiskCache,
emit_failed_flag: AtomicFlag,
Expand Down Expand Up @@ -91,6 +92,7 @@ impl EmitCache {

const LAST_LINE_PREFIX: &str = "\n// denoCacheMetadata=";

#[derive(Debug)]
struct EmitFileSerializer {
cli_version: &'static str,
}
Expand Down
101 changes: 22 additions & 79 deletions cli/cache/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,9 @@ use crate::file_fetcher::FetchOptions;
use crate::file_fetcher::FetchPermissionsOptionRef;
use crate::file_fetcher::FileFetcher;
use crate::file_fetcher::FileOrRedirect;
use crate::npm::CliNpmResolver;
use crate::resolver::CliNodeResolver;
use crate::util::fs::atomic_write_file_with_retries;
use crate::util::fs::atomic_write_file_with_retries_and_fs;
use crate::util::fs::AtomicWriteFileFsAdapter;
use crate::util::path::specifier_has_extension;
use crate::util::text_encoding::arc_str_to_bytes;
use crate::util::text_encoding::from_utf8_lossy_owned;

use deno_ast::MediaType;
use deno_core::futures;
Expand All @@ -25,7 +20,9 @@ use deno_graph::source::CacheInfo;
use deno_graph::source::LoadFuture;
use deno_graph::source::LoadResponse;
use deno_graph::source::Loader;
use deno_runtime::deno_fs;
use deno_runtime::deno_permissions::PermissionsContainer;
use node_resolver::InNpmPackageChecker;
use std::collections::HashMap;
use std::path::Path;
use std::path::PathBuf;
Expand Down Expand Up @@ -60,7 +57,6 @@ pub use fast_check::FastCheckCache;
pub use incremental::IncrementalCache;
pub use module_info::ModuleInfoCache;
pub use node::NodeAnalysisCache;
pub use parsed_source::EsmOrCjsChecker;
pub use parsed_source::LazyGraphSourceParser;
pub use parsed_source::ParsedSourceCache;

Expand Down Expand Up @@ -181,46 +177,40 @@ pub struct FetchCacherOptions {
pub permissions: PermissionsContainer,
/// If we're publishing for `deno publish`.
pub is_deno_publish: bool,
pub unstable_detect_cjs: bool,
}

/// A "wrapper" for the FileFetcher and DiskCache for the Deno CLI that provides
/// a concise interface to the DENO_DIR when building module graphs.
pub struct FetchCacher {
pub file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
esm_or_cjs_checker: Arc<EsmOrCjsChecker>,
file_fetcher: Arc<FileFetcher>,
fs: Arc<dyn deno_fs::FileSystem>,
global_http_cache: Arc<GlobalHttpCache>,
node_resolver: Arc<CliNodeResolver>,
npm_resolver: Arc<dyn CliNpmResolver>,
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
module_info_cache: Arc<ModuleInfoCache>,
permissions: PermissionsContainer,
is_deno_publish: bool,
unstable_detect_cjs: bool,
cache_info_enabled: bool,
}

impl FetchCacher {
pub fn new(
esm_or_cjs_checker: Arc<EsmOrCjsChecker>,
file_fetcher: Arc<FileFetcher>,
fs: Arc<dyn deno_fs::FileSystem>,
global_http_cache: Arc<GlobalHttpCache>,
node_resolver: Arc<CliNodeResolver>,
npm_resolver: Arc<dyn CliNpmResolver>,
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
module_info_cache: Arc<ModuleInfoCache>,
options: FetchCacherOptions,
) -> Self {
Self {
file_fetcher,
esm_or_cjs_checker,
fs,
global_http_cache,
node_resolver,
npm_resolver,
in_npm_pkg_checker,
module_info_cache,
file_header_overrides: options.file_header_overrides,
permissions: options.permissions,
is_deno_publish: options.is_deno_publish,
unstable_detect_cjs: options.unstable_detect_cjs,
cache_info_enabled: false,
}
}
Expand Down Expand Up @@ -271,70 +261,23 @@ impl Loader for FetchCacher {
) -> LoadFuture {
use deno_graph::source::CacheSetting as LoaderCacheSetting;

if specifier.scheme() == "file" {
if specifier.path().contains("/node_modules/") {
// The specifier might be in a completely different symlinked tree than
// what the node_modules url is in (ex. `/my-project-1/node_modules`
// symlinked to `/my-project-2/node_modules`), so first we checked if the path
// is in a node_modules dir to avoid needlessly canonicalizing, then now compare
// against the canonicalized specifier.
let specifier =
crate::node::resolve_specifier_into_node_modules(specifier);
if self.npm_resolver.in_npm_package(&specifier) {
return Box::pin(futures::future::ready(Ok(Some(
LoadResponse::External { specifier },
))));
}
}

// make local CJS modules external to the graph
if specifier_has_extension(specifier, "cjs") {
if specifier.scheme() == "file"
&& specifier.path().contains("/node_modules/")
{
// The specifier might be in a completely different symlinked tree than
// what the node_modules url is in (ex. `/my-project-1/node_modules`
// symlinked to `/my-project-2/node_modules`), so first we checked if the path
// is in a node_modules dir to avoid needlessly canonicalizing, then now compare
// against the canonicalized specifier.
let specifier = crate::node::resolve_specifier_into_node_modules(
specifier,
self.fs.as_ref(),
);
if self.in_npm_pkg_checker.in_npm_package(&specifier) {
return Box::pin(futures::future::ready(Ok(Some(
LoadResponse::External {
specifier: specifier.clone(),
},
LoadResponse::External { specifier },
))));
}

if self.unstable_detect_cjs && specifier_has_extension(specifier, "js") {
if let Ok(Some(pkg_json)) =
self.node_resolver.get_closest_package_json(specifier)
{
if pkg_json.typ == "commonjs" {
if let Ok(path) = specifier.to_file_path() {
if let Ok(bytes) = std::fs::read(&path) {
let text: Arc<str> = from_utf8_lossy_owned(bytes).into();
let is_es_module = match self.esm_or_cjs_checker.is_esm(
specifier,
text.clone(),
MediaType::JavaScript,
) {
Ok(value) => value,
Err(err) => {
return Box::pin(futures::future::ready(Err(err.into())));
}
};
if !is_es_module {
self.node_resolver.mark_cjs_resolution(specifier.clone());
return Box::pin(futures::future::ready(Ok(Some(
LoadResponse::External {
specifier: specifier.clone(),
},
))));
} else {
return Box::pin(futures::future::ready(Ok(Some(
LoadResponse::Module {
specifier: specifier.clone(),
content: arc_str_to_bytes(text),
maybe_headers: None,
},
))));
}
}
}
}
}
}
}

if self.is_deno_publish
Expand Down
Loading
Loading