Skip to content

Commit 758d4e1

Browse files
committedSep 22, 2022
fix #2558: remove esbuild-wasm package nesting
1 parent a333130 commit 758d4e1

File tree

8 files changed

+42
-23
lines changed

8 files changed

+42
-23
lines changed
 

‎.gitignore

+8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@
66
/deno/
77
/esbuild
88
/github/
9+
/npm/@esbuild/android-arm/esbuild.wasm
10+
/npm/@esbuild/android-arm/exit0.js
11+
/npm/@esbuild/android-arm/wasm_exec_node.js
12+
/npm/@esbuild/android-arm/wasm_exec.js
13+
/npm/esbuild-android-64/esbuild.wasm
14+
/npm/esbuild-android-64/exit0.js
15+
/npm/esbuild-android-64/wasm_exec_node.js
16+
/npm/esbuild-android-64/wasm_exec.js
917
/npm/esbuild-wasm/browser.js
1018
/npm/esbuild-wasm/esbuild.wasm
1119
/npm/esbuild-wasm/esm/

‎CHANGELOG.md

+14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
* Fix an obscure npm package installation issue with `--omit=optional` ([#2558](https://github.com/evanw/esbuild/issues/2558))
6+
7+
The previous release introduced a regression with `npm install esbuild --omit=optional` where the file `node_modules/.bin/esbuild` would no longer be present after installation. That could cause any package scripts which used the `esbuild` command to no longer work. This release fixes the regression so `node_modules/.bin/esbuild` should now be present again after installation. This regression only affected people installing esbuild using `npm` with either the `--omit=optional` or `--no-optional` flag, which is a somewhat unusual situation.
8+
9+
More details:
10+
11+
The reason for this regression is due to some obscure npm implementation details. Since the Go compiler doesn't support trivial cross-compiling on certain Android platforms, esbuild's installer installs a WebAssembly shim on those platforms instead. In the previous release I attempted to simplify esbuild's WebAssembly shims to depend on the `esbuild-wasm` package instead of including another whole copy of the WebAssembly binary (to make publishing faster and to save on file system space after installation). However, both the `esbuild` package and the `esbuild-wasm` package provide a binary called `esbuild` and it turns out that adding `esbuild-wasm` as a nested dependency of the `esbuild` package (specifically `esbuild` optionally depends on `@esbuild/android-arm` which depends on `esbuild-wasm`) caused npm to be confused about what `node_modules/.bin/esbuild` is supposed to be.
12+
13+
It's pretty strange and unexpected that disabling the installation of optional dependencies altogether would suddenly cause an optional dependency's dependency to conflict with the top-level package. What happens under the hood is that if `--omit=optional` is present, npm attempts to uninstall the `esbuild-wasm` nested dependency at the end of `npm install` (even though the `esbuild-wasm` package was never installed due to `--omit=optional`). This uninstallation causes `node_modules/.bin/esbuild` to be deleted.
14+
15+
After doing a full investigation, I discovered that npm's handling of the `.bin` directory is deliberately very brittle. When multiple packages in the dependency tree put something in `.bin` with the same name, the end result is non-deterministic/random. What you get in `.bin` might be from one package, from the other package, or might be missing entirely. The workaround suggested by npm is to just avoid having two packages that put something in `.bin` with the same name. So this was fixed by making the `@esbuild/android-arm` and `esbuild-android-64` packages each include another whole copy of the WebAssembly binary, which works because these packages don't put anything in `.bin`.
16+
317
## 0.15.8
418

519
* Fix JSX name collision edge case ([#2534](https://github.com/evanw/esbuild/issues/2534))

‎Makefile

+7-3
Original file line numberDiff line numberDiff line change
@@ -299,10 +299,10 @@ platform-unixlike: version-go
299299
node scripts/esbuild.js "$(NPMDIR)/package.json" --version
300300
CGO_ENABLED=0 GOOS="$(GOOS)" GOARCH="$(GOARCH)" go build $(GO_FLAGS) -o "$(NPMDIR)/bin/esbuild" ./cmd/esbuild
301301

302-
platform-android-x64:
302+
platform-android-x64: platform-wasm
303303
node scripts/esbuild.js npm/esbuild-android-64/package.json --version
304304

305-
platform-android-arm:
305+
platform-android-arm: platform-wasm
306306
node scripts/esbuild.js npm/@esbuild/android-arm/package.json --version
307307

308308
platform-android-arm64:
@@ -533,7 +533,9 @@ validate-build:
533533
# This checks that the published binaries are bitwise-identical to the locally-build binaries
534534
validate-builds:
535535
git fetch --all --tags && git checkout "v$(ESBUILD_VERSION)"
536+
@$(MAKE) --no-print-directory TARGET=platform-android-arm SCOPE=@esbuild/ PACKAGE=android-arm SUBPATH=esbuild.wasm validate-build
536537
@$(MAKE) --no-print-directory TARGET=platform-android-arm64 PACKAGE=esbuild-android-arm64 SUBPATH=bin/esbuild validate-build
538+
@$(MAKE) --no-print-directory TARGET=platform-android-x64 PACKAGE=esbuild-android-64 SUBPATH=esbuild.wasm validate-build
537539
@$(MAKE) --no-print-directory TARGET=platform-darwin-arm64 PACKAGE=esbuild-darwin-arm64 SUBPATH=bin/esbuild validate-build
538540
@$(MAKE) --no-print-directory TARGET=platform-darwin-x64 PACKAGE=esbuild-darwin-64 SUBPATH=bin/esbuild validate-build
539541
@$(MAKE) --no-print-directory TARGET=platform-freebsd-arm64 PACKAGE=esbuild-freebsd-arm64 SUBPATH=bin/esbuild validate-build
@@ -557,12 +559,14 @@ validate-builds:
557559

558560
clean:
559561
rm -f esbuild
560-
rm -f npm/esbuild-wasm/esbuild.wasm npm/esbuild-wasm/wasm_exec.js npm/esbuild-wasm/wasm_exec_node.js npm/esbuild-wasm/exit0.js
562+
rm -f npm/esbuild-wasm/esbuild.wasm npm/esbuild-wasm/wasm_exec*.js npm/esbuild-wasm/exit0.js
561563
rm -f npm/esbuild-windows-32/esbuild.exe
562564
rm -f npm/esbuild-windows-64/esbuild.exe
563565
rm -f npm/esbuild-windows-arm64/esbuild.exe
564566
rm -f npm/esbuild/install.js
565567
rm -rf npm/@esbuild/linux-loong64/bin
568+
rm -rf npm/esbuild-android-64/bin npm/esbuild-android-64/esbuild.wasm npm/esbuild-android-64/wasm_exec*.js npm/esbuild-android-64/exit0.js
569+
rm -rf npm/esbuild-android-arm/bin npm/esbuild-android-arm/esbuild.wasm npm/esbuild-android-arm/wasm_exec*.js npm/esbuild-android-arm/exit0.js
566570
rm -rf npm/esbuild-android-arm64/bin
567571
rm -rf npm/esbuild-darwin-64/bin
568572
rm -rf npm/esbuild-darwin-arm64/bin

‎npm/@esbuild/android-arm/bin/esbuild

-2
This file was deleted.

‎npm/@esbuild/android-arm/package.json

-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
"engines": {
99
"node": ">=12"
1010
},
11-
"dependencies": {
12-
"esbuild-wasm": "0.15.8"
13-
},
1411
"os": [
1512
"android"
1613
],

‎npm/esbuild-android-64/bin/esbuild

-2
This file was deleted.

‎npm/esbuild-android-64/package.json

-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
"engines": {
99
"node": ">=12"
1010
},
11-
"dependencies": {
12-
"esbuild-wasm": "0.15.8"
13-
},
1411
"os": [
1512
"android"
1613
],

‎scripts/esbuild.js

+13-10
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,19 @@ module.exports = ${JSON.stringify(exit0Map, null, 2)};
208208

209209
// Join with the asynchronous WebAssembly build
210210
await goBuildPromise;
211+
212+
// Also copy this into the WebAssembly shim directories
213+
for (const dir of [
214+
path.join(repoDir, 'npm', '@esbuild', 'android-arm'),
215+
path.join(repoDir, 'npm', 'esbuild-android-64'),
216+
]) {
217+
fs.mkdirSync(path.join(dir, 'bin'), { recursive: true })
218+
fs.writeFileSync(path.join(dir, 'wasm_exec.js'), wasm_exec_js);
219+
fs.writeFileSync(path.join(dir, 'wasm_exec_node.js'), wasm_exec_node_js);
220+
fs.writeFileSync(path.join(dir, 'exit0.js'), exit0Code);
221+
fs.copyFileSync(path.join(npmWasmDir, 'bin', 'esbuild'), path.join(dir, 'bin', 'esbuild'));
222+
fs.copyFileSync(path.join(npmWasmDir, 'esbuild.wasm'), path.join(dir, 'esbuild.wasm'));
223+
}
211224
}
212225

213226
const buildDenoLib = (esbuildPath) => {
@@ -293,19 +306,9 @@ exports.removeRecursiveSync = path => {
293306
const updateVersionPackageJSON = pathToPackageJSON => {
294307
const version = fs.readFileSync(path.join(path.dirname(__dirname), 'version.txt'), 'utf8').trim()
295308
const json = JSON.parse(fs.readFileSync(pathToPackageJSON, 'utf8'))
296-
let changed = false
297309

298310
if (json.version !== version) {
299311
json.version = version
300-
changed = true
301-
}
302-
303-
if ('dependencies' in json && 'esbuild-wasm' in json.dependencies && json.dependencies['esbuild-wasm'] !== version) {
304-
json.dependencies['esbuild-wasm'] = version
305-
changed = true
306-
}
307-
308-
if (changed) {
309312
fs.writeFileSync(pathToPackageJSON, JSON.stringify(json, null, 2) + '\n')
310313
}
311314
}

0 commit comments

Comments
 (0)
Please sign in to comment.