pnpm 11.26.0 → 11.27.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +176 -0
- package/dist/node_modules/.bin/node-gyp +17 -4
- package/dist/node_modules/.bin/node-which +17 -4
- package/dist/node_modules/.bin/nopt +17 -4
- package/dist/node_modules/.bin/semver +17 -4
- package/dist/node_modules/undici/lib/dispatcher/client-h1.js +12 -4
- package/dist/node_modules/undici/lib/handler/retry-handler.js +29 -3
- package/dist/node_modules/undici/lib/web/eventsource/eventsource-stream.js +245 -150
- package/dist/node_modules/undici/lib/web/websocket/connection.js +1 -1
- package/dist/node_modules/undici/lib/web/websocket/permessage-deflate.js +5 -0
- package/dist/node_modules/undici/package.json +1 -1
- package/dist/pnpm.mjs +155170 -154017
- package/dist/worker.js +6376 -3176
- package/package.json +1 -1
- package/dist/node_modules/.package-map.json +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,181 @@
|
|
|
1
1
|
# pnpm
|
|
2
2
|
|
|
3
|
+
## 11.27.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- `pn`, `pnpx`, and `pnx` now run the pnpm installed alongside them. They used to look pnpm up on `PATH`. That failed when the directory holding them was not on `PATH`, and it silently handed the call to an unrelated pnpm when one came first there [#14803](https://github.com/pnpm/pnpm/issues/14803).
|
|
8
|
+
|
|
9
|
+
- The `@zkochan/cmd-shim` package is now available as `@pnpm/bins.cmd-shim`.
|
|
10
|
+
|
|
11
|
+
- `pnpm cache list-registries` now prints the registry URL, matching `pnpm cache view`. It printed `https%3A+registry.npmjs.org` before and prints `https://registry.npmjs.org/` now [#15046](https://github.com/pnpm/pnpm/issues/15046).
|
|
12
|
+
|
|
13
|
+
- `pnpm deploy` no longer installs the dependencies of the workspace root project into the deploy directory [#6437](https://github.com/pnpm/pnpm/issues/6437).
|
|
14
|
+
|
|
15
|
+
- Install warnings no longer carry the text of a package's deprecation notice. The warning names the deprecated package and version, and the `pnpm:deprecation` event no longer carries the notice either. `pnpm view` still shows it on request.
|
|
16
|
+
|
|
17
|
+
A deprecation warning now names the newest version of the package that is not deprecated, and says when reaching it means widening the range you declared:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
WARN deprecated foo@1.0.0. 2.3.1 is not deprecated, outside the range you declared.
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
pnpm works this out from the metadata it already fetched, so it costs no extra request. An install that reuses the lockfile without fetching metadata names no version.
|
|
24
|
+
|
|
25
|
+
pnpm strips control characters from the package name and version in a deprecation warning, and from the notice `pnpm outdated --long` prints.
|
|
26
|
+
|
|
27
|
+
The text sanitizer now also strips the Unicode line and paragraph separators U+2028 and U+2029.
|
|
28
|
+
|
|
29
|
+
- `pnpm exec <command>` and `pnpm <command>` run from a subdirectory of a project now find the executables installed in the project's `node_modules/.bin`. The command still runs in the subdirectory. `PNPM_PACKAGE_NAME` names the project [#5068](https://github.com/pnpm/pnpm/issues/5068).
|
|
30
|
+
|
|
31
|
+
- `pnpm exec` and `pnpm dlx` now wait for the command to finish shutting down after `Ctrl+C`. A signal sent to pnpm alone now reaches the command, the way it does with `pnpm run`. pnpm used to exit on the interrupt and terminate the command while it was still shutting down [#7374](https://github.com/pnpm/pnpm/issues/7374).
|
|
32
|
+
|
|
33
|
+
- Warnings about ignored environment variables in project `.npmrc` credentials now link to the npmrc documentation [pnpm/pnpm#15051](https://github.com/pnpm/pnpm/issues/15051).
|
|
34
|
+
|
|
35
|
+
- `pnpm audit --interactive --fix=update` no longer opens a second prompt for selecting dependencies to update [#14927](https://github.com/pnpm/pnpm/issues/14927).
|
|
36
|
+
|
|
37
|
+
- Fixed `pnpm dedupe` requiring a second pass after bumping a direct dependency in `package.json` [pnpm/pnpm#14987](https://github.com/pnpm/pnpm/issues/14987).
|
|
38
|
+
|
|
39
|
+
- `pnpm deploy` now writes plain versions for registry dependencies with peer dependencies in the deployed `package.json`. The deployed lockfile retains the resolved peer bindings. npm aliases keep their target package names [#14873](https://github.com/pnpm/pnpm/issues/14873).
|
|
40
|
+
|
|
41
|
+
- `pnpm publish` now allows a detached Git HEAD in CI, including checkouts of release tags. The working tree must still be clean. Branch and remote-history checks still apply when HEAD is attached [pnpm/pnpm#5894](https://github.com/pnpm/pnpm/issues/5894).
|
|
42
|
+
|
|
43
|
+
- `pnpm dlx` and `pnx` now prompt to approve dependency build scripts in interactive terminals. Cached packages with pending builds also prompt for approval. Without an interactive terminal, use `--allow-build` to allow the required builds. Fixes [pnpm/pnpm#14943](https://github.com/pnpm/pnpm/issues/14943).
|
|
44
|
+
|
|
45
|
+
- `pnpm install --force` now removes obsolete dependency links inside virtual-store packages when their dependencies change. Invalid dependency names are ignored during obsolete-link cleanup [#15039](https://github.com/pnpm/pnpm/issues/15039).
|
|
46
|
+
|
|
47
|
+
- `pnpm add -g` and `pnpm update -g` now ignore incomplete unrelated global package groups when every command from the replaced group is retained. Operations that could remove a global command still require complete ownership information.
|
|
48
|
+
|
|
49
|
+
- Resolving a Node.js runtime now fails when unofficial-builds.nodejs.org cannot be reached. pnpm used to ignore that failure and leave the musl builds out of `pnpm-lock.yaml`. `pnpm update` then wrote a different lockfile on a machine whose network blocks the mirror [pnpm/pnpm#14813](https://github.com/pnpm/pnpm/issues/14813).
|
|
50
|
+
|
|
51
|
+
- pnpm now deduplicates a package whose child dependency resolved an optional peer in one workspace project but not in another. Two copies of `next` could appear when only some projects could reach `styled-jsx`'s optional `babel-plugin-macros` peer [#14800](https://github.com/pnpm/pnpm/issues/14800).
|
|
52
|
+
|
|
53
|
+
- Fixed shell completion of package scripts for `pnpm run` and `pnpm run-script` [pnpm/pnpm#15034](https://github.com/pnpm/pnpm/issues/15034).
|
|
54
|
+
|
|
55
|
+
Bash completion now preserves literal script names containing glob characters and shell punctuation in pnpm v11 and v12.
|
|
56
|
+
|
|
57
|
+
- `pnpm sbom` now publishes a valid URL in the CycloneDX `externalReferences[].url` and the SPDX `homepage`. An npm shorthand such as `vercel/ms` or `gitlab:group/subgroup/project` is expanded to the `git+https` URL npm derives for it. An scp-style remote such as `git@github.com:vercel/ms.git` is expanded the same way. Any other URL is published in its normalized form, without embedded credentials. A value that names no repository, an email address for example, is left out. pnpm used to publish the raw value, so a shorthand produced a URL that consumers such as Dependency-Track reject [pnpm/pnpm#14773](https://github.com/pnpm/pnpm/issues/14773).
|
|
58
|
+
|
|
59
|
+
- `pnpm setup` now describes the displayed configuration changes as "the following configuration changes."
|
|
60
|
+
|
|
61
|
+
- `pnpm --version` now reports why the pnpm version a project pins cannot be installed or recorded, then prints the version of the running CLI. It used to fail, which made the command unusable where the filesystem is read-only. `pnpm --version` also honors `--store-dir` and its `--store` alias now [#14831](https://github.com/pnpm/pnpm/issues/14831).
|
|
62
|
+
|
|
63
|
+
- `pnpm install --force` now reinstalls dependencies when the manifest and lockfile are unchanged. It previously reported "Already up to date" without reinstalling. Files changed in `node_modules` are restored when the store content is intact. Combining `--force` with `--frozen-store` now reports a configuration conflict on repeat installs [#919](https://github.com/pnpm/pnpm/issues/919).
|
|
64
|
+
|
|
65
|
+
- `pnpm install` now installs git-hosted dependencies without preparing them when their builds are explicitly denied by `allowBuilds`. Dependencies that require preparation still need an explicit allow or deny decision [pnpm/pnpm#10522](https://github.com/pnpm/pnpm/issues/10522).
|
|
66
|
+
|
|
67
|
+
- `pnpm runtime set` and `pnpm env use` now use the pnpm version that started the command. They could run a different installed pnpm when the command was started through Corepack or another wrapper.
|
|
68
|
+
|
|
69
|
+
- The install summary now names the version each dependency resolved to when `node-linker` is `hoisted`. It also lists what an install restores after `node_modules` is deleted, and both sides of a version change. The summary showed the range recorded in `package.json`, or nothing at all [#15161](https://github.com/pnpm/pnpm/issues/15161).
|
|
70
|
+
|
|
71
|
+
- The `@pnpm/npm-lifecycle` package is now available as `@pnpm/exec.npm-lifecycle`.
|
|
72
|
+
|
|
73
|
+
- Fixed `minimumReleaseAge` making pnpm download a package's full metadata again on every install. The cached copy carried a validator the registry could not match, so pnpm could never revalidate it [pnpm/pnpm#15103](https://github.com/pnpm/pnpm/issues/15103).
|
|
74
|
+
|
|
75
|
+
- pnpm now measures a `pnpm.overrides` entry written as a bare path, such as `./local-dep`, from the directory holding `pnpm-workspace.yaml`. It used to be measured from each package the override rewrote, so the dependency linked to a directory that does not exist [#11131](https://github.com/pnpm/pnpm/issues/11131).
|
|
76
|
+
|
|
77
|
+
- pnpm now preserves scalar YAML anchors and aliases when editing `pnpm-workspace.yaml`. Removing the entry that defines an anchor keeps surviving aliases valid. Entries updated to different values are written separately [#8245](https://github.com/pnpm/pnpm/issues/8245).
|
|
78
|
+
|
|
79
|
+
- pnpm now preserves comments and existing key order when updating `package.yaml`. New keys are appended to their mapping [pnpm/pnpm#2008](https://github.com/pnpm/pnpm/issues/2008).
|
|
80
|
+
|
|
81
|
+
- `pnpm install --prod` no longer downloads the registry packages that only a devDependency reaches [#881](https://github.com/pnpm/pnpm/issues/881).
|
|
82
|
+
|
|
83
|
+
- `pnpm update --global` no longer reinstalls a global package when its dependency graph resolves to what is already installed. It reports `Already up to date` [pnpm/pnpm#12002](https://github.com/pnpm/pnpm/issues/12002).
|
|
84
|
+
|
|
85
|
+
- The `minimumReleaseAge` approval prompt now counts and displays each package version once [pnpm/pnpm#15083](https://github.com/pnpm/pnpm/issues/15083).
|
|
86
|
+
|
|
87
|
+
- `pnpm run` no longer sends a script a second `SIGINT` when `Ctrl+C` is pressed in a terminal. A script that shuts down on the first `SIGINT` and exits at once on a second used to die before its shutdown finished [#7374](https://github.com/pnpm/pnpm/issues/7374).
|
|
88
|
+
|
|
89
|
+
- pnpm now reads a `pnpm-workspace.yaml` whose `tasks` section uses a setting only pnpm 12 acts on, such as `concurrencyGroup`. A task's unrecognized fields are ignored, unless the field only differs in case from `concurrency` or `dependsOn`, which pnpm reports as a typo.
|
|
90
|
+
|
|
91
|
+
The warning about unrecognized top-level settings now names `cargo`, `concurrencyGroups`, and `pipelines` as pnpm 12 settings.
|
|
92
|
+
|
|
93
|
+
- `pnpm -r list --json` now prints one JSON array. It printed a separate array for each project when `sharedWorkspaceLockfile` was `false`, so the output could not be parsed.
|
|
94
|
+
|
|
95
|
+
`pnpm -r list` now reads each project's own modules directory when the projects keep their own lockfiles, so `--long` and `--parseable` report the packages that project installed [#15011](https://github.com/pnpm/pnpm/issues/15011).
|
|
96
|
+
|
|
97
|
+
- A signal sent to pnpm while it runs without a terminal, as a container runtime or a service manager does, now reaches the script even when the shell running it stays the script's parent. pnpm then waits for the script to finish shutting down. Such a signal used to end the shell at once or stay with it, and the script was never told to stop [#7374](https://github.com/pnpm/pnpm/issues/7374).
|
|
98
|
+
|
|
99
|
+
- Fixed `minimumReleaseAge` being skipped for packages served by a registry that returns the same ETag for abbreviated and full package metadata [pnpm/pnpm#14925](https://github.com/pnpm/pnpm/issues/14925).
|
|
100
|
+
|
|
101
|
+
- `pnpm install` now returns "Already up to date" in a workspace where `dedupeDirectDeps` left a project without a `node_modules` directory of its own. Such a project forced a full install on every run.
|
|
102
|
+
|
|
103
|
+
- Installs in different projects that share a global virtual store no longer fail on Windows with `Access is denied` while repairing the same slot [#15114](https://github.com/pnpm/pnpm/issues/15114).
|
|
104
|
+
|
|
105
|
+
- `pnpm sbom` now emits a license value as a CycloneDX expression only when it is a valid SPDX license expression. Anything else is emitted as a CycloneDX license name [pnpm/pnpm#14786](https://github.com/pnpm/pnpm/issues/14786).
|
|
106
|
+
|
|
107
|
+
- A dependency's own bins can no longer take over another package's bin shim. The POSIX shims pnpm generates used to look up their shell helpers on `PATH`, where a dependency's bins come first [#14837](https://github.com/pnpm/pnpm/issues/14837). Reinstalling replaces the shims already in your `node_modules`. On Cygwin, MSYS2, and WSL the shims still take their Windows path conversion from `PATH`, so a dependency can still redirect them there.
|
|
108
|
+
|
|
109
|
+
- POSIX bin shims now convert a Windows-form path such as `C:\node_modules\.bin\tsc` correctly. The shim mangled the backslashes in such a path and could not reach the package it runs. Installing again replaces the shims already in `node_modules` [#14867](https://github.com/pnpm/pnpm/issues/14867).
|
|
110
|
+
|
|
111
|
+
- `pnpm pack` now writes tarball entries grouped by file extension and file name, the order npm uses. Packages that ship many same-named files, such as template collections, pack much smaller [#14766](https://github.com/pnpm/pnpm/issues/14766).
|
|
112
|
+
|
|
113
|
+
- A command run in a project that the workspace does not include now acts on that project alone. A project is outside the workspace when it has a manifest of its own and no pattern in the `packages` setting selects it, or when a `!` pattern excludes it. A directory with no manifest of its own, such as a package's source directory, still belongs to the workspace. `pnpm install` in an excluded project used to install every project in the workspace [#3561](https://github.com/pnpm/pnpm/issues/3561).
|
|
114
|
+
|
|
115
|
+
- POSIX bin shims now take `cygpath` and `wslpath` from the system default path on Cygwin, MSYS2, and WSL2. The shims looked both helpers up on `PATH`, where a dependency's own bins come first, so a dependency could redirect another package's shim. Installing again replaces the shims already in `node_modules` [#14866](https://github.com/pnpm/pnpm/issues/14866).
|
|
116
|
+
|
|
117
|
+
- `pnpm update` and `pnpm audit --fix=update` no longer copy dependencies added by `packageExtensions`, a `readPackage` hook, or an override into `package.json`. Those dependencies keep the specifier the hook or override gives them. `pnpm update --latest` no longer resolves past that specifier. `pnpm audit --fix=update` now warns when one of them pins a vulnerable version. The warning points at `pnpm audit --fix` [#14928](https://github.com/pnpm/pnpm/issues/14928).
|
|
118
|
+
|
|
119
|
+
## 11.27.0
|
|
120
|
+
|
|
121
|
+
### Minor Changes
|
|
122
|
+
|
|
123
|
+
- `nodeDownloadMirrors` can now be set in the global config file (`config.yaml`) and through the `PNPM_CONFIG_NODE_DOWNLOAD_MIRRORS` environment variable, so a Node.js download mirror can be configured once for a machine instead of in every workspace [#12124](https://github.com/pnpm/pnpm/issues/12124), [#13611](https://github.com/pnpm/pnpm/issues/13611).
|
|
124
|
+
|
|
125
|
+
```sh
|
|
126
|
+
PNPM_CONFIG_NODE_DOWNLOAD_MIRRORS='{"release":"https://npmmirror.com/mirrors/node/"}'
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
- Added a new setting `trustPolicyExcludePrune` (default: `false`). When enabled, `pnpm add`, `pnpm update`, and `pnpm remove` prune the entries of `trustPolicyExclude` in `pnpm-workspace.yaml` that the freshly written lockfile no longer resolves: versions that are gone are dropped (an entry is removed once none of its versions remain), and entries for packages that are no longer in the lockfile are removed too. Name patterns (`@scope/*`) are always kept. The cleanup is skipped when the install's lockfile does not cover the whole workspace (`sharedWorkspaceLockfile: false`), since entries another project still needs would look stale.
|
|
130
|
+
|
|
131
|
+
### Patch Changes
|
|
132
|
+
|
|
133
|
+
- pnpm now reads the `packageManager`, `devEngines.packageManager` and runtime pins from the workspace root's `package.json` when `lockfileDir` is set. A project that moved its lockfile lost the pins it declared there [#14633](https://github.com/pnpm/pnpm/issues/14633).
|
|
134
|
+
|
|
135
|
+
- Fixed `pnpm add -g`, `pnpm update -g`, and `pnpm remove -g` mutating global bins or install directories after only partially reading an installed package group. If any declared package manifest is missing, malformed, or unreadable, pnpm now fails before activation or removal and leaves the existing global installation intact [pnpm/pnpm#13796](https://github.com/pnpm/pnpm/issues/13796).
|
|
136
|
+
|
|
137
|
+
- `fetch-timeout` now limits how long a request may make no progress. The timer restarts on every chunk that arrives. A large download over a slow connection is no longer aborted while data is still coming in. A connection that stops delivering data still fails after `fetch-timeout` [#14604](https://github.com/pnpm/pnpm/issues/14604).
|
|
138
|
+
|
|
139
|
+
- `pnpm peers check` no longer reports a peer dependency declared as `workspace:^`, `workspace:~`, or a bare `workspace:` as unmet. pnpm reported these as unmet whatever version the linked workspace project supplied [#14770](https://github.com/pnpm/pnpm/issues/14770).
|
|
140
|
+
|
|
141
|
+
- A `readPackage` hook that edits its argument in place no longer changes what a later install in the same command resolves. A `deprecated` notice read from the lockfile no longer carries over to another install either [#13988](https://github.com/pnpm/pnpm/issues/13988).
|
|
142
|
+
|
|
143
|
+
- `pnpm install` now auto-installs missing transitive peers when workspace projects share a dependency at different depths. This also removes incomplete duplicate peer contexts from the lockfile. Fixes [pnpm/pnpm#14840](https://github.com/pnpm/pnpm/issues/14840).
|
|
144
|
+
|
|
145
|
+
- GitHub Actions updates now stop if an action reference changes while its versions are being resolved. Unrelated workflow edits are preserved.
|
|
146
|
+
|
|
147
|
+
GitHub Actions homepage links no longer expose server credentials. GitHub server URLs now require HTTPS, with HTTP allowed only for loopback hosts.
|
|
148
|
+
|
|
149
|
+
- `pnpm licenses list` now reports the runtime downloaded through `devEngines.runtime` with `onFail: "download"`. The command previously failed with `ERR_PNPM_UNSUPPORTED_PACKAGE_TYPE` [#14172](https://github.com/pnpm/pnpm/issues/14172).
|
|
150
|
+
|
|
151
|
+
- pnpm no longer creates a project `pnpm-lock.yaml` when `devEngines.packageManager.onFail` is `download` and lockfile writing is turned off with `lockfile: false` or `--no-lockfile`. pnpm still switches to the pinned version [#14728](https://github.com/pnpm/pnpm/issues/14728).
|
|
152
|
+
|
|
153
|
+
- A `registry` or `@scope:registry` set in an `.npmrc` now wins over the registry a `pnpm login` credential stored in the global `config.yaml` points at. Previously, after logging in to one registry, installs in a project whose `.npmrc` named a private registry went to the logged-in registry instead. They now go to the registry the `.npmrc` names [#14614](https://github.com/pnpm/pnpm/issues/14614).
|
|
154
|
+
|
|
155
|
+
- A patch that gives a dependency a `preinstall`, `install`, or `postinstall` script, or a `binding.gyp`, now runs that build. pnpm asks for build approval first, so the package is listed under "Ignored build scripts" until it is allowed to build. pnpm 12 ran nothing, and pnpm 11 ran it without asking [#14648](https://github.com/pnpm/pnpm/issues/14648).
|
|
156
|
+
|
|
157
|
+
- Registries that share a host but differ by URL path — one JFrog Artifactory, Nexus, AWS CodeArtifact or GitLab Packages instance serving several repositories — now get a metadata cache directory each. Previously they shared one, so resolving a package from one of them could answer with another's versions, integrity hashes and tarball URLs and fail with `ERR_PNPM_TARBALL_URL_MISMATCH` [#13558](https://github.com/pnpm/pnpm/issues/13558).
|
|
158
|
+
|
|
159
|
+
The URL scheme is part of the cache directory name too, so an `http` registry can no longer hand its metadata — which can be rewritten in transit — to a resolution configured for `https` at the same host.
|
|
160
|
+
|
|
161
|
+
The first install after upgrading refetches registry metadata once. The package store is untouched.
|
|
162
|
+
|
|
163
|
+
`pnpm cache view` now labels each entry with the full registry URL. It printed `registry.npmjs.org` before and prints `https://registry.npmjs.org/` now.
|
|
164
|
+
|
|
165
|
+
`pnpm cache list-registries` and `pnpm cache list` print the new directory names. Scripts that parse either command need updating.
|
|
166
|
+
|
|
167
|
+
- Updated the embedded Node.js release keys to the current canonical `nodejs/release-keys` list.
|
|
168
|
+
|
|
169
|
+
- `pnpm sbom` now omits package author fields when the manifest author name is empty or contains only whitespace [pnpm/pnpm#14685](https://github.com/pnpm/pnpm/issues/14685). In a filtered or split workspace run, only a project with no `author` field inherits the workspace root's author.
|
|
170
|
+
|
|
171
|
+
- `pnpm sbom --sbom-format spdx` now writes `creationInfo.created` with whole seconds, such as `2026-09-08T10:38:21Z`. The timestamp carried fractional seconds, which strict SPDX consumers rejected [#14684](https://github.com/pnpm/pnpm/issues/14684).
|
|
172
|
+
|
|
173
|
+
- Windows filesystem operations now retry permission errors for up to one second. Permanent permission errors previously delayed failure by a minute. Sharing and lock violations retain their one-minute retry budget [pnpm/pnpm#14682](https://github.com/pnpm/pnpm/issues/14682).
|
|
174
|
+
|
|
175
|
+
- pnpm now writes `node_modules/.package-map.json` only when `nodeExperimentalPackageMap` is enabled. Nothing reads the file without that setting. An install that stops writing the map removes the one a previous install left.
|
|
176
|
+
|
|
177
|
+
- pnpm now unpacks a downloaded runtime archive into a randomly named directory inside the store. It previously used a predictable path, where another user of a shared store could plant a symlink and redirect the write outside the store ([GHSA-vwc7-r8mq-g2x9](https://github.com/advisories/GHSA-vwc7-r8mq-g2x9)).
|
|
178
|
+
|
|
3
179
|
## 11.26.0
|
|
4
180
|
|
|
5
181
|
### Minor Changes
|
|
@@ -1,22 +1,35 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
2
|
# Resolve $0 through symlinks so basedir is the shim's real directory.
|
|
3
3
|
# Cap hops at the kernel's ELOOP limit so a cycle cannot hang the shim.
|
|
4
|
+
#
|
|
5
|
+
# A shim runs with node_modules/.bin at the front of PATH, so readlink, sed,
|
|
6
|
+
# uname, and printf go through `command -p`, which searches the system default
|
|
7
|
+
# path instead. A dependency's bin cannot stand in for one of them and take over
|
|
8
|
+
# the shim before it reaches its target. Directories come from `${link%/*}`,
|
|
9
|
+
# which needs no helper at all.
|
|
4
10
|
link="$0"
|
|
11
|
+
# `${link%/*}` needs a separator to strip. A bare name came from a PATH lookup
|
|
12
|
+
# and stands for a file in the current directory.
|
|
13
|
+
case "$link" in
|
|
14
|
+
*/*|*\\*) ;;
|
|
15
|
+
*) link="./$link" ;;
|
|
16
|
+
esac
|
|
5
17
|
hops=0
|
|
6
18
|
while [ -L "$link" ] && [ "$hops" -lt 40 ]; do
|
|
7
19
|
hops=$((hops+1))
|
|
8
|
-
target=$(readlink "$link")
|
|
20
|
+
target=$(command -p readlink "$link")
|
|
9
21
|
case "$target" in
|
|
10
22
|
/*) link="$target" ;;
|
|
11
|
-
*) link="$
|
|
23
|
+
*) link="${link%/*}/$target" ;;
|
|
12
24
|
esac
|
|
13
25
|
done
|
|
14
|
-
basedir=$(
|
|
26
|
+
basedir=$(command -p printf '%s\n' "$link" | command -p sed -e 's,\\,/,g')
|
|
27
|
+
basedir="${basedir%/*}"
|
|
15
28
|
basedir_win="$basedir"
|
|
16
29
|
exe=""
|
|
17
30
|
msys=""
|
|
18
31
|
|
|
19
|
-
case `uname -a` in
|
|
32
|
+
case `command -p uname -a` in
|
|
20
33
|
*CYGWIN*|*MINGW*|*MSYS*)
|
|
21
34
|
if command -v cygpath > /dev/null 2>&1; then
|
|
22
35
|
basedir_win=`cygpath -w "$basedir"`
|
|
@@ -1,22 +1,35 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
2
|
# Resolve $0 through symlinks so basedir is the shim's real directory.
|
|
3
3
|
# Cap hops at the kernel's ELOOP limit so a cycle cannot hang the shim.
|
|
4
|
+
#
|
|
5
|
+
# A shim runs with node_modules/.bin at the front of PATH, so readlink, sed,
|
|
6
|
+
# uname, and printf go through `command -p`, which searches the system default
|
|
7
|
+
# path instead. A dependency's bin cannot stand in for one of them and take over
|
|
8
|
+
# the shim before it reaches its target. Directories come from `${link%/*}`,
|
|
9
|
+
# which needs no helper at all.
|
|
4
10
|
link="$0"
|
|
11
|
+
# `${link%/*}` needs a separator to strip. A bare name came from a PATH lookup
|
|
12
|
+
# and stands for a file in the current directory.
|
|
13
|
+
case "$link" in
|
|
14
|
+
*/*|*\\*) ;;
|
|
15
|
+
*) link="./$link" ;;
|
|
16
|
+
esac
|
|
5
17
|
hops=0
|
|
6
18
|
while [ -L "$link" ] && [ "$hops" -lt 40 ]; do
|
|
7
19
|
hops=$((hops+1))
|
|
8
|
-
target=$(readlink "$link")
|
|
20
|
+
target=$(command -p readlink "$link")
|
|
9
21
|
case "$target" in
|
|
10
22
|
/*) link="$target" ;;
|
|
11
|
-
*) link="$
|
|
23
|
+
*) link="${link%/*}/$target" ;;
|
|
12
24
|
esac
|
|
13
25
|
done
|
|
14
|
-
basedir=$(
|
|
26
|
+
basedir=$(command -p printf '%s\n' "$link" | command -p sed -e 's,\\,/,g')
|
|
27
|
+
basedir="${basedir%/*}"
|
|
15
28
|
basedir_win="$basedir"
|
|
16
29
|
exe=""
|
|
17
30
|
msys=""
|
|
18
31
|
|
|
19
|
-
case `uname -a` in
|
|
32
|
+
case `command -p uname -a` in
|
|
20
33
|
*CYGWIN*|*MINGW*|*MSYS*)
|
|
21
34
|
if command -v cygpath > /dev/null 2>&1; then
|
|
22
35
|
basedir_win=`cygpath -w "$basedir"`
|
|
@@ -1,22 +1,35 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
2
|
# Resolve $0 through symlinks so basedir is the shim's real directory.
|
|
3
3
|
# Cap hops at the kernel's ELOOP limit so a cycle cannot hang the shim.
|
|
4
|
+
#
|
|
5
|
+
# A shim runs with node_modules/.bin at the front of PATH, so readlink, sed,
|
|
6
|
+
# uname, and printf go through `command -p`, which searches the system default
|
|
7
|
+
# path instead. A dependency's bin cannot stand in for one of them and take over
|
|
8
|
+
# the shim before it reaches its target. Directories come from `${link%/*}`,
|
|
9
|
+
# which needs no helper at all.
|
|
4
10
|
link="$0"
|
|
11
|
+
# `${link%/*}` needs a separator to strip. A bare name came from a PATH lookup
|
|
12
|
+
# and stands for a file in the current directory.
|
|
13
|
+
case "$link" in
|
|
14
|
+
*/*|*\\*) ;;
|
|
15
|
+
*) link="./$link" ;;
|
|
16
|
+
esac
|
|
5
17
|
hops=0
|
|
6
18
|
while [ -L "$link" ] && [ "$hops" -lt 40 ]; do
|
|
7
19
|
hops=$((hops+1))
|
|
8
|
-
target=$(readlink "$link")
|
|
20
|
+
target=$(command -p readlink "$link")
|
|
9
21
|
case "$target" in
|
|
10
22
|
/*) link="$target" ;;
|
|
11
|
-
*) link="$
|
|
23
|
+
*) link="${link%/*}/$target" ;;
|
|
12
24
|
esac
|
|
13
25
|
done
|
|
14
|
-
basedir=$(
|
|
26
|
+
basedir=$(command -p printf '%s\n' "$link" | command -p sed -e 's,\\,/,g')
|
|
27
|
+
basedir="${basedir%/*}"
|
|
15
28
|
basedir_win="$basedir"
|
|
16
29
|
exe=""
|
|
17
30
|
msys=""
|
|
18
31
|
|
|
19
|
-
case `uname -a` in
|
|
32
|
+
case `command -p uname -a` in
|
|
20
33
|
*CYGWIN*|*MINGW*|*MSYS*)
|
|
21
34
|
if command -v cygpath > /dev/null 2>&1; then
|
|
22
35
|
basedir_win=`cygpath -w "$basedir"`
|
|
@@ -1,22 +1,35 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
2
|
# Resolve $0 through symlinks so basedir is the shim's real directory.
|
|
3
3
|
# Cap hops at the kernel's ELOOP limit so a cycle cannot hang the shim.
|
|
4
|
+
#
|
|
5
|
+
# A shim runs with node_modules/.bin at the front of PATH, so readlink, sed,
|
|
6
|
+
# uname, and printf go through `command -p`, which searches the system default
|
|
7
|
+
# path instead. A dependency's bin cannot stand in for one of them and take over
|
|
8
|
+
# the shim before it reaches its target. Directories come from `${link%/*}`,
|
|
9
|
+
# which needs no helper at all.
|
|
4
10
|
link="$0"
|
|
11
|
+
# `${link%/*}` needs a separator to strip. A bare name came from a PATH lookup
|
|
12
|
+
# and stands for a file in the current directory.
|
|
13
|
+
case "$link" in
|
|
14
|
+
*/*|*\\*) ;;
|
|
15
|
+
*) link="./$link" ;;
|
|
16
|
+
esac
|
|
5
17
|
hops=0
|
|
6
18
|
while [ -L "$link" ] && [ "$hops" -lt 40 ]; do
|
|
7
19
|
hops=$((hops+1))
|
|
8
|
-
target=$(readlink "$link")
|
|
20
|
+
target=$(command -p readlink "$link")
|
|
9
21
|
case "$target" in
|
|
10
22
|
/*) link="$target" ;;
|
|
11
|
-
*) link="$
|
|
23
|
+
*) link="${link%/*}/$target" ;;
|
|
12
24
|
esac
|
|
13
25
|
done
|
|
14
|
-
basedir=$(
|
|
26
|
+
basedir=$(command -p printf '%s\n' "$link" | command -p sed -e 's,\\,/,g')
|
|
27
|
+
basedir="${basedir%/*}"
|
|
15
28
|
basedir_win="$basedir"
|
|
16
29
|
exe=""
|
|
17
30
|
msys=""
|
|
18
31
|
|
|
19
|
-
case `uname -a` in
|
|
32
|
+
case `command -p uname -a` in
|
|
20
33
|
*CYGWIN*|*MINGW*|*MSYS*)
|
|
21
34
|
if command -v cygpath > /dev/null 2>&1; then
|
|
22
35
|
basedir_win=`cygpath -w "$basedir"`
|
|
@@ -876,7 +876,7 @@ async function connectH1 (client, socket) {
|
|
|
876
876
|
|
|
877
877
|
function clearIdleSocketValidation (socket) {
|
|
878
878
|
if (socket[kIdleSocketValidationTimeout]) {
|
|
879
|
-
|
|
879
|
+
clearImmediate(socket[kIdleSocketValidationTimeout])
|
|
880
880
|
socket[kIdleSocketValidationTimeout] = null
|
|
881
881
|
}
|
|
882
882
|
|
|
@@ -885,15 +885,23 @@ function clearIdleSocketValidation (socket) {
|
|
|
885
885
|
|
|
886
886
|
function scheduleIdleSocketValidation (client, socket) {
|
|
887
887
|
socket[kIdleSocketValidation] = 1
|
|
888
|
-
|
|
888
|
+
// Yield to the check phase (after poll) so unsolicited bytes / FIN / RST
|
|
889
|
+
// already pending on this idle keep-alive socket are processed before the
|
|
890
|
+
// next request is written (GHSA-35p6-xmwp-9g52).
|
|
891
|
+
//
|
|
892
|
+
// setTimeout(0) pays Node's ~1ms timer floor on every sequential reuse
|
|
893
|
+
// (#5493). setImmediate avoids that, but an *unref'd* Immediate lets poll
|
|
894
|
+
// block for ~500ms when the event loop is otherwise idle (#5600 / #5606).
|
|
895
|
+
// A ref'd Immediate both keeps the pending request alive and makes poll
|
|
896
|
+
// return immediately — the hybrid those issues asked for.
|
|
897
|
+
socket[kIdleSocketValidationTimeout] = setImmediate(() => {
|
|
889
898
|
socket[kIdleSocketValidationTimeout] = null
|
|
890
899
|
socket[kIdleSocketValidation] = 2
|
|
891
900
|
|
|
892
901
|
if (client[kSocket] === socket && !socket.destroyed) {
|
|
893
902
|
client[kResume]()
|
|
894
903
|
}
|
|
895
|
-
}
|
|
896
|
-
socket[kIdleSocketValidationTimeout].unref?.()
|
|
904
|
+
})
|
|
897
905
|
}
|
|
898
906
|
|
|
899
907
|
/**
|
|
@@ -90,6 +90,7 @@ class RetryHandler {
|
|
|
90
90
|
this.end = null
|
|
91
91
|
this.etag = null
|
|
92
92
|
this.resume = null
|
|
93
|
+
this.headersSent = false
|
|
93
94
|
|
|
94
95
|
// Handle possible onConnect duplication
|
|
95
96
|
this.handler.onConnect(reason => {
|
|
@@ -102,6 +103,20 @@ class RetryHandler {
|
|
|
102
103
|
})
|
|
103
104
|
}
|
|
104
105
|
|
|
106
|
+
checkpointResponseEnd (headers, resume) {
|
|
107
|
+
if (this.end == null && this.opts.method !== 'HEAD') {
|
|
108
|
+
const contentLength = headers['content-length']
|
|
109
|
+
this.end = contentLength != null ? Number(contentLength) - 1 : null
|
|
110
|
+
|
|
111
|
+
assert(
|
|
112
|
+
this.end == null || Number.isFinite(this.end),
|
|
113
|
+
'invalid content-length'
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
this.resume = this.end != null ? resume : null
|
|
118
|
+
}
|
|
119
|
+
|
|
105
120
|
onRequestSent () {
|
|
106
121
|
if (this.handler.onRequestSent) {
|
|
107
122
|
this.handler.onRequestSent()
|
|
@@ -191,6 +206,8 @@ class RetryHandler {
|
|
|
191
206
|
|
|
192
207
|
if (statusCode >= 300) {
|
|
193
208
|
if (this.retryOpts.statusCodes.includes(statusCode) === false) {
|
|
209
|
+
this.headersSent = true
|
|
210
|
+
this.checkpointResponseEnd(headers, resume)
|
|
194
211
|
return this.handler.onHeaders(
|
|
195
212
|
statusCode,
|
|
196
213
|
rawHeaders,
|
|
@@ -259,8 +276,15 @@ class RetryHandler {
|
|
|
259
276
|
|
|
260
277
|
const { start, size, end = size - 1 } = contentRange
|
|
261
278
|
|
|
262
|
-
|
|
263
|
-
|
|
279
|
+
if (this.start !== start || (this.end != null && this.end !== end)) {
|
|
280
|
+
this.abort(
|
|
281
|
+
new RequestRetryError('Content-Range mismatch', statusCode, {
|
|
282
|
+
headers,
|
|
283
|
+
data: { count: this.retryCount }
|
|
284
|
+
})
|
|
285
|
+
)
|
|
286
|
+
return false
|
|
287
|
+
}
|
|
264
288
|
|
|
265
289
|
this.resume = resume
|
|
266
290
|
return true
|
|
@@ -272,6 +296,7 @@ class RetryHandler {
|
|
|
272
296
|
const range = parseRangeHeader(headers['content-range'])
|
|
273
297
|
|
|
274
298
|
if (range == null) {
|
|
299
|
+
this.headersSent = true
|
|
275
300
|
return this.handler.onHeaders(
|
|
276
301
|
statusCode,
|
|
277
302
|
rawHeaders,
|
|
@@ -310,6 +335,7 @@ class RetryHandler {
|
|
|
310
335
|
)
|
|
311
336
|
|
|
312
337
|
this.resume = resume
|
|
338
|
+
this.headersSent = true
|
|
313
339
|
this.etag = headers.etag != null ? headers.etag : null
|
|
314
340
|
|
|
315
341
|
// Weak etags are not useful for comparison nor cache
|
|
@@ -349,7 +375,7 @@ class RetryHandler {
|
|
|
349
375
|
}
|
|
350
376
|
|
|
351
377
|
onError (err) {
|
|
352
|
-
if (this.aborted || isDisturbed(this.opts.body)) {
|
|
378
|
+
if (this.aborted || isDisturbed(this.opts.body) || (this.headersSent && this.resume == null)) {
|
|
353
379
|
return this.handler.onError(err)
|
|
354
380
|
}
|
|
355
381
|
|