diff options
author | mash-graz <mash-graz@users.noreply.github.com> | 2024-03-20 04:42:22 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-20 09:12:22 +0530 |
commit | 0d43a63636c97886c10c6b8ce05fdb67cd2d8b91 (patch) | |
tree | c1bde8b36ec1d317f0d85ee7f40243169a2f4e2f /ext/node/ops/worker_threads.rs | |
parent | b9f8562754f14aecfd87acdecfe8d8c966ccbe4d (diff) |
fix(ext/node): worker_threads ESM handling (#22841)
Fixes #22840
Fixes #22964
Diffstat (limited to 'ext/node/ops/worker_threads.rs')
-rw-r--r-- | ext/node/ops/worker_threads.rs | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/ext/node/ops/worker_threads.rs b/ext/node/ops/worker_threads.rs new file mode 100644 index 000000000..18a4157d4 --- /dev/null +++ b/ext/node/ops/worker_threads.rs @@ -0,0 +1,87 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +use deno_core::error::generic_error; +use deno_core::error::AnyError; +use deno_core::op2; +use deno_core::url::Url; +use deno_core::OpState; +use deno_fs::FileSystemRc; +use std::path::Path; +use std::path::PathBuf; +use std::rc::Rc; + +use crate::resolution; +use crate::NodePermissions; +use crate::NodeResolver; +use crate::NpmResolverRc; + +fn ensure_read_permission<P>( + state: &mut OpState, + file_path: &Path, +) -> Result<(), AnyError> +where + P: NodePermissions + 'static, +{ + let resolver = state.borrow::<NpmResolverRc>(); + let permissions = state.borrow::<P>(); + resolver.ensure_read_permission(permissions, file_path) +} + +#[op2] +#[string] +pub fn op_worker_threads_filename<P>( + state: &mut OpState, + #[string] specifier: String, +) -> Result<String, AnyError> +where + P: NodePermissions + 'static, +{ + if specifier.starts_with("data:") { + return Ok(specifier); + } + let url: Url = if specifier.starts_with("file:") { + Url::parse(&specifier)? + } else { + let path = PathBuf::from(&specifier); + if path.is_relative() && !specifier.starts_with('.') { + return Err(generic_error( + "Relative path entries must start with '.' or '..'", + )); + } + ensure_read_permission::<P>(state, &path)?; + let fs = state.borrow::<FileSystemRc>(); + let canonicalized_path = + deno_core::strip_unc_prefix(fs.realpath_sync(&path)?); + Url::from_file_path(canonicalized_path) + .map_err(|e| generic_error(format!("URL from Path-String: {:#?}", e)))? + }; + let url_path = url + .to_file_path() + .map_err(|e| generic_error(format!("URL to Path-String: {:#?}", e)))?; + ensure_read_permission::<P>(state, &url_path)?; + let fs = state.borrow::<FileSystemRc>(); + if !fs.exists_sync(&url_path) { + return Err(generic_error(format!("File not found [{:?}]", url_path))); + } + let node_resolver = state.borrow::<Rc<NodeResolver>>(); + match node_resolver.url_to_node_resolution(url)? { + resolution::NodeResolution::Esm(u) => Ok(u.to_string()), + resolution::NodeResolution::CommonJs(u) => wrap_cjs(u), + _ => Err(generic_error("Neither ESM nor CJS")), + } +} + +/// +/// Wrap a CJS file-URL and the required setup in a stringified `data:`-URL +/// +fn wrap_cjs(url: Url) -> Result<String, AnyError> { + let path = url + .to_file_path() + .map_err(|e| generic_error(format!("URL to Path: {:#?}", e)))?; + let filename = path.file_name().unwrap().to_string_lossy(); + Ok(format!( + "data:text/javascript,import {{ createRequire }} from \"node:module\";\ + const require = createRequire(\"{}\"); require(\"./{}\");", + url, filename, + )) +} |