summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2022-08-24 13:37:34 -0400
committerGitHub <noreply@github.com>2022-08-24 13:37:34 -0400
commit18fcef8b294f98df5eb555fb166afafebeaed71f (patch)
tree33f8378543538a5af1ffcad178b20482e3502d8d
parent33c4d45328166d103e99a8c243727eead626080c (diff)
fix(npm): cjs export analysis should take into consideration exports with dashes (#15582)
-rw-r--r--cli/node/mod.rs54
1 files changed, 39 insertions, 15 deletions
diff --git a/cli/node/mod.rs b/cli/node/mod.rs
index 9edd58bea..91dfd45f6 100644
--- a/cli/node/mod.rs
+++ b/cli/node/mod.rs
@@ -484,19 +484,33 @@ fn module_resolve(
})
}
-fn add_export(source: &mut Vec<String>, name: &str, initializer: &str) {
+fn add_export(
+ source: &mut Vec<String>,
+ name: &str,
+ initializer: &str,
+ temp_var_count: &mut usize,
+) {
+ fn is_valid_var_decl(name: &str) -> bool {
+ // it's ok to be super strict here
+ name
+ .chars()
+ .all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '$')
+ }
+
// 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?
- if RESERVED_WORDS.contains(name) {
- // we can't create an identifier with a reserved word, so assign it to a temporary
- // variable that won't have a conflict, then re-export it as a string
+ if RESERVED_WORDS.contains(name) || !is_valid_var_decl(name) {
+ *temp_var_count += 1;
+ // we can't create an identifier with a reserved word or invalid identifier name,
+ // so assign it to a temporary variable that won't have a conflict, then re-export
+ // it as a string
source.push(format!(
- "const __deno_reexport_temp__{} = {};",
- name, initializer
+ "const __deno_export_{}__ = {};",
+ temp_var_count, initializer
));
source.push(format!(
- "export {{ __deno_reexport_temp__{0} as \"{0}\" }};",
- name
+ "export {{ __deno_export_{}__ as \"{}\" }};",
+ temp_var_count, name
));
} else {
source.push(format!("export const {} = {};", name, initializer));
@@ -525,6 +539,7 @@ pub fn translate_cjs_to_esm(
maybe_syntax: None,
})?;
let analysis = parsed_source.analyze_cjs();
+ let mut temp_var_count = 0;
let mut source = vec![
r#"const require = Deno[Deno.internal].require.Module.createRequire(import.meta.url);"#.to_string(),
@@ -565,7 +580,12 @@ pub fn translate_cjs_to_esm(
for export in analysis.exports.iter().filter(|e| e.as_str() != "default")
{
- add_export(&mut source, export, &format!("Deno[Deno.internal].require.bindExport(reexport{0}.{1}, reexport{0})", idx, export));
+ add_export(
+ &mut source,
+ export,
+ &format!("Deno[Deno.internal].require.bindExport(reexport{0}[\"{1}\"], reexport{0})", idx, export),
+ &mut temp_var_count,
+ );
}
}
}
@@ -587,7 +607,7 @@ pub fn translate_cjs_to_esm(
if export.as_str() == "default" {
// todo(dsherret): we should only do this if there was a `_esModule: true` instead
source.push(format!(
- "export default Deno[Deno.internal].require.bindExport(mod.{}, mod);",
+ "export default Deno[Deno.internal].require.bindExport(mod[\"{}\"], mod);",
export,
));
had_default = true;
@@ -596,9 +616,10 @@ pub fn translate_cjs_to_esm(
&mut source,
export,
&format!(
- "Deno[Deno.internal].require.bindExport(mod.{}, mod)",
+ "Deno[Deno.internal].require.bindExport(mod[\"{}\"], mod)",
export
),
+ &mut temp_var_count,
);
}
}
@@ -856,19 +877,22 @@ mod tests {
#[test]
fn test_add_export() {
+ let mut temp_var_count = 0;
let mut source = vec![];
- let exports = vec!["static", "server", "app"];
+ let exports = vec!["static", "server", "app", "dashed-export"];
for export in exports {
- add_export(&mut source, export, "init");
+ add_export(&mut source, export, "init", &mut temp_var_count);
}
assert_eq!(
source,
vec![
- "const __deno_reexport_temp__static = init;".to_string(),
- "export { __deno_reexport_temp__static as \"static\" };".to_string(),
+ "const __deno_export_1__ = init;".to_string(),
+ "export { __deno_export_1__ as \"static\" };".to_string(),
"export const server = init;".to_string(),
"export const app = init;".to_string(),
+ "const __deno_export_2__ = init;".to_string(),
+ "export { __deno_export_2__ as \"dashed-export\" };".to_string(),
]
)
}