From cffa8449422d62c8fa3cb4985131bc50814d1479 Mon Sep 17 00:00:00 2001 From: X Date: Tue, 18 Apr 2023 16:34:36 +0800 Subject: [PATCH] Remove shebang (close #596) --- server/build.go | 23 +++++++++++++---------- server/utils.go | 4 ++++ test/issue-596/issue-596.test.ts | 7 +++++++ 3 files changed, 24 insertions(+), 10 deletions(-) create mode 100644 test/issue-596/issue-596.test.ts diff --git a/server/build.go b/server/build.go index 332b69500..0d2db34a3 100644 --- a/server/build.go +++ b/server/build.go @@ -559,6 +559,7 @@ rebuild: for _, file := range result.OutputFiles { outputContent := file.Contents + if strings.HasSuffix(file.Path, ".js") { buf := bytes.NewBufferString(fmt.Sprintf( "/* esm.sh - esbuild bundle(%s) %s %s */\n", @@ -571,6 +572,11 @@ rebuild: eol = "" } + // remove shebang + if bytes.HasPrefix(outputContent, []byte("#!/")) { + outputContent = outputContent[bytes.IndexByte(outputContent, '\n')+1:] + } + // replace external imports/requires for depIndex, name := range externalDeps.Values() { var importPath string @@ -754,12 +760,10 @@ rebuild: // right shift to strip the object `key` shift := 0 for i, l := 1, len(p); i < l; i++ { - c := p[i] - if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '$' { - shift++ - } else { + if !isJSIdentChar(p[i]) { break } + shift++ } importName := string(p[1 : shift+1]) if includes(depESM.NamedExports, importName) { @@ -788,7 +792,7 @@ rebuild: } } if !marked { - cjsImportNames.Add("lazy") + cjsImportNames.Add("default?") } } cjsContext = bytes.HasSuffix(p, []byte{'('}) && !bytes.HasSuffix(p, []byte("import(")) @@ -796,8 +800,7 @@ rebuild: // left shift to strip the `require` ident generated by esbuild shift := 0 for i := len(p) - 2; i >= 0; i-- { - c := p[i] - if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '$' { + if isJSIdentChar(p[i]) { shift++ } else { break @@ -832,14 +835,14 @@ rebuild: fmt.Fprintf(buf, `const __%s$ = ()=>!0;%s`, identifier, eol) } else { switch importName { - case "default": - fmt.Fprintf(buf, `import __%s$ from "%s";%s`, identifier, importPath, eol) case "*": fmt.Fprintf(buf, `import * as __%s$ from "%s";%s`, identifier, importPath, eol) case "*?": fmt.Fprintf(buf, `import * as _%s$ from "%s";%s`, identifier, importPath, eol) fmt.Fprintf(buf, `const __%s$ = Object.assign({__esModule:!0},_%s$);%s`, identifier, identifier, eol) - case "lazy": + case "default": + fmt.Fprintf(buf, `import __%s$ from "%s";%s`, identifier, importPath, eol) + case "default?": fmt.Fprintf(buf, `import * as _%s$ from "%s";%s`, identifier, importPath, eol) if task.Target == "deno" || task.Target == "denonext" || task.Target == "node" || task.Target >= "es2020" { fmt.Fprintf(buf, `const __%s$ = _%s$.default??_%s$;%s`, identifier, identifier, identifier, eol) diff --git a/server/utils.go b/server/utils.go index d398d4a96..c3efaf6d9 100644 --- a/server/utils.go +++ b/server/utils.go @@ -187,6 +187,10 @@ func kill(pidFile string) (err error) { return process.Kill() } +func isJSIdentChar(c byte) bool { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '$' +} + func validateJS(filename string) (isESM bool, namedExports []string, err error) { data, err := os.ReadFile(filename) if err != nil { diff --git a/test/issue-596/issue-596.test.ts b/test/issue-596/issue-596.test.ts new file mode 100644 index 000000000..3cd62d819 --- /dev/null +++ b/test/issue-596/issue-596.test.ts @@ -0,0 +1,7 @@ +import { assert } from "https://deno.land/std@0.178.0/testing/asserts.ts"; + + +Deno.test("issue #596", async () => { + const code = await fetch("http://localhost:8080/v115/reejs@0.9.0/deno/src/cli/index.js").then(res=>res.text()) + assert(!code.includes("#!/usr/bin/env node")) +});