mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
fix(cli): Don't strip shebangs from modules (#13220)
Deno's module loader currently strips a shebang if a module file starts with one. However, this is no longer necessary, since there is a stage-3 TC39 that adds support for shebangs (or "hashbangs") to the language (https://github.com/tc39/proposal-hashbang), and V8, `tsc` and `swc` all support it. Furthermore, stripping shebangs causes a correctness bug with JSON modules, since a JSON file with a shebang should not parse as a JSON module, yet it does with this stripping. This change fixes this.
This commit is contained in:
parent
ad224f53c7
commit
9def44979a
9 changed files with 44 additions and 27 deletions
|
@ -27,6 +27,7 @@
|
|||
"cli/tests/testdata/badly_formatted.json",
|
||||
"cli/tests/testdata/byte_order_mark.ts",
|
||||
"cli/tests/testdata/fmt/*",
|
||||
"cli/tests/testdata/import_assertions/json_with_shebang.json",
|
||||
"cli/tests/testdata/test/markdown_windows.md",
|
||||
"cli/tsc/*typescript.js",
|
||||
"test_util/std",
|
||||
|
|
|
@ -148,7 +148,7 @@ fn fetch_local(specifier: &ModuleSpecifier) -> Result<File, AnyError> {
|
|||
})?;
|
||||
let bytes = fs::read(local.clone())?;
|
||||
let charset = text_encoding::detect_charset(&bytes).to_string();
|
||||
let source = strip_shebang(get_source_from_bytes(bytes, Some(charset))?);
|
||||
let source = get_source_from_bytes(bytes, Some(charset))?;
|
||||
let media_type = MediaType::from(specifier);
|
||||
|
||||
Ok(File {
|
||||
|
@ -173,10 +173,7 @@ pub fn get_source_from_data_url(
|
|||
let (bytes, _) = data_url
|
||||
.decode_to_vec()
|
||||
.map_err(|e| uri_error(format!("{:?}", e)))?;
|
||||
Ok((
|
||||
strip_shebang(get_source_from_bytes(bytes, charset)?),
|
||||
format!("{}", mime),
|
||||
))
|
||||
Ok((get_source_from_bytes(bytes, charset)?, format!("{}", mime)))
|
||||
}
|
||||
|
||||
/// Given a vector of bytes and optionally a charset, decode the bytes to a
|
||||
|
@ -230,19 +227,6 @@ pub fn map_content_type(
|
|||
}
|
||||
}
|
||||
|
||||
/// Remove shebangs from the start of source code strings
|
||||
fn strip_shebang(mut value: String) -> String {
|
||||
if value.starts_with("#!") {
|
||||
if let Some(mid) = value.find('\n') {
|
||||
let (_, rest) = value.split_at(mid);
|
||||
value = rest.to_string()
|
||||
} else {
|
||||
value.clear()
|
||||
}
|
||||
}
|
||||
value
|
||||
}
|
||||
|
||||
/// A structure for resolving, fetching and caching source files.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FileFetcher {
|
||||
|
@ -306,7 +290,7 @@ impl FileFetcher {
|
|||
let maybe_content_type = headers.get("content-type").cloned();
|
||||
let (media_type, maybe_charset) =
|
||||
map_content_type(specifier, maybe_content_type);
|
||||
let source = strip_shebang(get_source_from_bytes(bytes, maybe_charset)?);
|
||||
let source = get_source_from_bytes(bytes, maybe_charset)?;
|
||||
let maybe_types = match media_type {
|
||||
MediaType::JavaScript
|
||||
| MediaType::Cjs
|
||||
|
@ -450,7 +434,7 @@ impl FileFetcher {
|
|||
|
||||
let (media_type, maybe_charset) =
|
||||
map_content_type(specifier, Some(content_type.clone()));
|
||||
let source = strip_shebang(get_source_from_bytes(bytes, maybe_charset)?);
|
||||
let source = get_source_from_bytes(bytes, maybe_charset)?;
|
||||
|
||||
let local =
|
||||
self
|
||||
|
@ -786,13 +770,6 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strip_shebang() {
|
||||
let value =
|
||||
"#!/usr/bin/env deno\n\nconsole.log(\"hello deno!\");\n".to_string();
|
||||
assert_eq!(strip_shebang(value), "\n\nconsole.log(\"hello deno!\");\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_map_content_type() {
|
||||
let fixtures = vec![
|
||||
|
|
|
@ -1600,6 +1600,28 @@ itest!(jsx_import_source_error {
|
|||
exit_code: 1,
|
||||
});
|
||||
|
||||
itest!(shebang_tsc {
|
||||
args: "run --quiet shebang.ts",
|
||||
output: "shebang.ts.out",
|
||||
});
|
||||
|
||||
itest!(shebang_swc {
|
||||
args: "run --quiet --no-check shebang.ts",
|
||||
output: "shebang.ts.out",
|
||||
});
|
||||
|
||||
itest!(shebang_with_json_imports_tsc {
|
||||
args: "run --quiet import_assertions/json_with_shebang.ts",
|
||||
output: "import_assertions/json_with_shebang.ts.out",
|
||||
exit_code: 1,
|
||||
});
|
||||
|
||||
itest!(shebang_with_json_imports_swc {
|
||||
args: "run --quiet --no-check import_assertions/json_with_shebang.ts",
|
||||
output: "import_assertions/json_with_shebang.ts.out",
|
||||
exit_code: 1,
|
||||
});
|
||||
|
||||
#[test]
|
||||
fn no_validate_asm() {
|
||||
let output = util::deno_cmd()
|
||||
|
|
4
cli/tests/testdata/import_assertions/json_with_shebang.json
vendored
Normal file
4
cli/tests/testdata/import_assertions/json_with_shebang.json
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
#!/usr/env -S deno run
|
||||
{
|
||||
"test": null
|
||||
}
|
3
cli/tests/testdata/import_assertions/json_with_shebang.ts
vendored
Normal file
3
cli/tests/testdata/import_assertions/json_with_shebang.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
import json from "./json_with_shebang.json" assert { type: "json" };
|
||||
|
||||
console.log(json);
|
1
cli/tests/testdata/import_assertions/json_with_shebang.ts.out
vendored
Normal file
1
cli/tests/testdata/import_assertions/json_with_shebang.ts.out
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
error: Uncaught SyntaxError: Unexpected token # in JSON at position 0
|
5
cli/tests/testdata/shebang.ts
vendored
Normal file
5
cli/tests/testdata/shebang.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env -S deno run
|
||||
|
||||
import test from "./shebang2.ts";
|
||||
|
||||
console.log(test as number);
|
1
cli/tests/testdata/shebang.ts.out
vendored
Normal file
1
cli/tests/testdata/shebang.ts.out
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
42
|
3
cli/tests/testdata/shebang2.ts
vendored
Normal file
3
cli/tests/testdata/shebang2.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env -S deno run
|
||||
|
||||
export default 42;
|
Loading…
Reference in a new issue