Skip to content

Commit a18c9fa

Browse files
committed
fix #2495: strip non-go ignorePatternData stuff
1 parent 8fc9476 commit a18c9fa

File tree

7 files changed

+47
-3
lines changed

7 files changed

+47
-3
lines changed

CHANGELOG.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,20 @@
2626

2727
So instead of publishing a native esbuild binary executable to npm, this release publishes a WebAssembly fallback build. This is essentially the same as the `esbuild-wasm` package but it's installed automatically when you install the `esbuild` package on Android ARM. So packages that depend on the `esbuild` package should now work on Android ARM. This change has not yet been tested end-to-end because I don't have a 32-bit Android ARM device myself, but in theory it should work.
2828

29-
This inherits the drawbacks of WebAssembly including significantly slower performance than native as well as potentially also more severe memory usage limitations. If you want to use a native binary executable of esbuild on Android ARM, you may be able to build it yourself from source after installing the Android build tools.
29+
This inherits the drawbacks of WebAssembly including significantly slower performance than native as well as potentially also more severe memory usage limitations and lack of certain features (e.g. `--serve`). If you want to use a native binary executable of esbuild on Android ARM, you may be able to build it yourself from source after installing the Android build tools.
30+
31+
* Attempt to better support Yarn's `ignorePatternData` feature ([#2495](https://github.com/evanw/esbuild/issues/2495))
32+
33+
Part of resolving paths in a project using Yarn's Plug'n'Play feature involves evaluating a regular expression in the `ignorePatternData` property of `.pnp.data.json`. However, it turns out that the particular regular expressions generated by Yarn use some syntax that works with JavaScript regular expressions but that does not work with Go regular expressions.
34+
35+
In this release, esbuild will now strip some of the the problematic syntax from the regular expression before compiling it, which should hopefully allow it to be compiled by Go's regular expression engine. The specific character sequences that esbuild currently strips are as follows:
36+
37+
* `(?!\.)`
38+
* `(?!(?:^|\/)\.)`
39+
* `(?!\.{1,2}(?:\/|$))`
40+
* `(?!(?:^|\/)\.{1,2}(?:\/|$))`
41+
42+
These seem to be used by Yarn to avoid the `.` and `..` path segments in the middle of relative paths. The removal of these character sequences seems relatively harmless in this case since esbuild shouldn't ever generate such path segments. This change should add support to esbuild for Yarn's [`pnpIgnorePatterns`](https://yarnpkg.com/configuration/yarnrc/#pnpIgnorePatterns) feature.
3043

3144
## 0.15.7
3245

internal/resolver/resolver.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,9 @@ func (rr *resolver) Resolve(sourceDir string, importPath string, kind ast.Import
445445
r.pnpManifest = compileYarnPnPData(absPath, r.fs.Dir(absPath), json)
446446
}
447447
}
448+
if r.debugLogs != nil && r.pnpManifest != nil && r.pnpManifest.invalidIgnorePatternData != "" {
449+
r.debugLogs.addNote(" Invalid Go regular expression for \"ignorePatternData\": " + r.pnpManifest.invalidIgnorePatternData)
450+
}
448451
break
449452
}
450453
}

internal/resolver/yarnpnp.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ type pnpData struct {
2828
// the classic Node.js resolution algorithm rather than the Plug'n'Play one.
2929
// Note that unlike other paths in the manifest, the one checked against this
3030
// regexp won't begin by `./`.
31-
ignorePatternData *regexp.Regexp
31+
ignorePatternData *regexp.Regexp
32+
invalidIgnorePatternData string
3233

3334
// This is the main part of the PnP data file. This table contains the list
3435
// of all packages, first keyed by package ident then by package reference.
@@ -438,7 +439,26 @@ func compileYarnPnPData(absPath string, absDirPath string, json js_ast.Expr) *pn
438439

439440
if value, _, ok := getProperty(json, "ignorePatternData"); ok {
440441
if ignorePatternData, ok := getString(value); ok {
441-
data.ignorePatternData, _ = regexp.Compile(ignorePatternData)
442+
// The Go regular expression engine doesn't support some of the features
443+
// that JavaScript regular expressions support, including "(?!" negative
444+
// lookaheads which Yarn uses. This is deliberate on Go's part. See this:
445+
// https://github.com/golang/go/issues/18868.
446+
//
447+
// Yarn uses this feature to exclude the "." and ".." path segments in
448+
// the middle of a relative path. However, we shouldn't ever generate
449+
// such path segments in the first place. So as a hack, we just remove
450+
// the specific character sequences used by Yarn for this so that the
451+
// regular expression is more likely to be able to be compiled.
452+
ignorePatternData = strings.ReplaceAll(ignorePatternData, `(?!\.)`, "")
453+
ignorePatternData = strings.ReplaceAll(ignorePatternData, `(?!(?:^|\/)\.)`, "")
454+
ignorePatternData = strings.ReplaceAll(ignorePatternData, `(?!\.{1,2}(?:\/|$))`, "")
455+
ignorePatternData = strings.ReplaceAll(ignorePatternData, `(?!(?:^|\/)\.{1,2}(?:\/|$))`, "")
456+
457+
if reg, err := regexp.Compile(ignorePatternData); err == nil {
458+
data.ignorePatternData = reg
459+
} else {
460+
data.invalidIgnorePatternData = ignorePatternData
461+
}
442462
}
443463
}
444464

require/yarnpnp/bar/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
exports.bar = require('bar-pkg').bar

require/yarnpnp/bar/node_modules/bar-pkg/index.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

require/yarnpnp/in.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,7 @@ if (mm.default.getType('txt') !== 'text/plain') throw '❌ mime'
1717
import * as foo from 'foo'
1818
if (foo.default !== 'foo') throw '❌ foo'
1919

20+
import * as bar from './bar/index.js'
21+
if (bar.bar !== 'bar') throw '❌ bar'
22+
2023
console.log('✅ Yarn PnP tests passed')

scripts/test-yarnpnp.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ function reinstallYarnIfNeeded() {
3737
run('yarn set version 3.2.3')
3838
}
3939

40+
const rc = fs.readFileSync(path.join(rootDir, '.yarnrc.yml'), 'utf8')
41+
fs.writeFileSync(path.join(rootDir, '.yarnrc.yml'), `pnpIgnorePatterns: ["./bar/**"]\n` + rc)
42+
4043
run('yarn install')
4144
}
4245

0 commit comments

Comments
 (0)