Skip to content
This repository was archived by the owner on Jan 20, 2022. It is now read-only.

Commit 5b46b8b

Browse files
committed
fix: use Intl.Collator for string sorting when available
Credit: @killagu Close: #317 PR-URL: #324 Credit: @isaacs Close: #324 Reviewed-by: @isaacs
1 parent cb91e3e commit 5b46b8b

File tree

13 files changed

+428
-668
lines changed

13 files changed

+428
-668
lines changed

lib/add-rm-pkg-deps.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// add and remove dependency specs to/from pkg manifest
22

3+
const localeCompare = require('@isaacs/string-locale-compare')('en')
4+
35
const add = ({pkg, add, saveBundle, saveType, log}) => {
46
for (const spec of add) {
57
addSingle({pkg, spec, saveBundle, saveType, log})
@@ -79,7 +81,7 @@ const addSingle = ({pkg, spec, saveBundle, saveType, log}) => {
7981
// keep it sorted, keep it unique
8082
const bd = new Set(pkg.bundleDependencies || [])
8183
bd.add(spec.name)
82-
pkg.bundleDependencies = [...bd].sort((a, b) => a.localeCompare(b, 'en'))
84+
pkg.bundleDependencies = [...bd].sort(localeCompare)
8385
}
8486
}
8587

lib/arborist/build-ideal-tree.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// mixin implementing the buildIdealTree method
2+
const localeCompare = require('@isaacs/string-locale-compare')('en')
23
const rpj = require('read-package-json-fast')
34
const npa = require('npm-package-arg')
45
const pacote = require('pacote')
@@ -771,7 +772,7 @@ This is a one-time fix-up, please be patient...
771772
// sort physically shallower deps up to the front of the queue,
772773
// because they'll affect things deeper in, then alphabetical
773774
this[_depsQueue].sort((a, b) =>
774-
(a.depth - b.depth) || a.path.localeCompare(b.path, 'en'))
775+
(a.depth - b.depth) || localeCompare(a.path, b.path))
775776

776777
const node = this[_depsQueue].shift()
777778
const bd = node.package.bundleDependencies
@@ -916,7 +917,7 @@ This is a one-time fix-up, please be patient...
916917
}
917918

918919
const placeDeps = tasks
919-
.sort((a, b) => a.edge.name.localeCompare(b.edge.name, 'en'))
920+
.sort((a, b) => localeCompare(a.edge.name, b.edge.name))
920921
.map(({ edge, dep }) => new PlaceDep({
921922
edge,
922923
dep,
@@ -1247,7 +1248,7 @@ This is a one-time fix-up, please be patient...
12471248
// we typically only install non-optional peers, but we have to
12481249
// factor them into the peerSet so that we can avoid conflicts
12491250
.filter(e => e.peer && !(e.valid && e.to))
1250-
.sort(({name: a}, {name: b}) => a.localeCompare(b, 'en'))
1251+
.sort(({name: a}, {name: b}) => localeCompare(a, b))
12511252

12521253
for (const edge of peerEdges) {
12531254
// already placed this one, and we're happy with it.

lib/arborist/load-virtual.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// mixin providing the loadVirtual method
2+
const localeCompare = require('@isaacs/string-locale-compare')('en')
23

34
const {resolve} = require('path')
45

@@ -167,12 +168,12 @@ module.exports = cls => class VirtualLoader extends cls {
167168
...depsToEdges('peerOptional', peerOptional),
168169
...lockWS,
169170
].sort(([atype, aname], [btype, bname]) =>
170-
atype.localeCompare(btype, 'en') || aname.localeCompare(bname, 'en'))
171+
localeCompare(atype, btype) || localeCompare(aname, bname))
171172

172173
const rootEdges = [...root.edgesOut.values()]
173174
.map(e => [e.type, e.name, e.spec])
174175
.sort(([atype, aname], [btype, bname]) =>
175-
atype.localeCompare(btype, 'en') || aname.localeCompare(bname, 'en'))
176+
localeCompare(atype, btype) || localeCompare(aname, bname))
176177

177178
if (rootEdges.length !== lockEdges.length) {
178179
// something added or removed

lib/arborist/rebuild.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Arborist.rebuild({path = this.path}) will do all the binlinks and
22
// bundle building needed. Called by reify, and by `npm rebuild`.
33

4+
const localeCompare = require('@isaacs/string-locale-compare')('en')
45
const {depth: dfwalk} = require('treeverse')
56
const promiseAllRejectLate = require('promise-all-reject-late')
67
const rpj = require('read-package-json-fast')
@@ -14,7 +15,8 @@ const {
1415
} = require('@npmcli/node-gyp')
1516

1617
const boolEnv = b => b ? '1' : ''
17-
const sortNodes = (a, b) => (a.depth - b.depth) || a.path.localeCompare(b.path, 'en')
18+
const sortNodes = (a, b) =>
19+
(a.depth - b.depth) || localeCompare(a.path, b.path)
1820

1921
const _workspaces = Symbol.for('workspaces')
2022
const _build = Symbol('build')

lib/audit-report.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// an object representing the set of vulnerabilities in a tree
22
/* eslint camelcase: "off" */
33

4+
const localeCompare = require('@isaacs/string-locale-compare')('en')
45
const npa = require('npm-package-arg')
56
const pickManifest = require('npm-pick-manifest')
67

@@ -79,7 +80,7 @@ class AuditReport extends Map {
7980
}
8081

8182
obj.vulnerabilities = vulnerabilities
82-
.sort(([a], [b]) => a.localeCompare(b, 'en'))
83+
.sort(([a], [b]) => localeCompare(a, b))
8384
.reduce((set, [name, vuln]) => {
8485
set[name] = vuln
8586
return set

lib/can-place-dep.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
// then we will return REPLACE rather than CONFLICT, and Arborist will queue
3636
// the replaced node for resolution elsewhere.
3737

38+
const localeCompare = require('@isaacs/string-locale-compare')('en')
3839
const semver = require('semver')
3940
const debug = require('./debug.js')
4041
const peerEntrySets = require('./peer-entry-sets.js')
@@ -79,7 +80,7 @@ class CanPlaceDep {
7980
this._treeSnapshot = JSON.stringify([...target.root.inventory.entries()]
8081
.map(([loc, {packageName, version, resolved}]) => {
8182
return [loc, packageName, version, resolved]
82-
}).sort(([a], [b]) => a.localeCompare(b, 'en')))
83+
}).sort(([a], [b]) => localeCompare(a, b)))
8384
})
8485

8586
// the result of whether we can place it or not
@@ -119,7 +120,7 @@ class CanPlaceDep {
119120
const treeSnapshot = JSON.stringify([...target.root.inventory.entries()]
120121
.map(([loc, {packageName, version, resolved}]) => {
121122
return [loc, packageName, version, resolved]
122-
}).sort(([a], [b]) => a.localeCompare(b, 'en')))
123+
}).sort(([a], [b]) => localeCompare(a, b)))
123124
/* istanbul ignore if */
124125
if (this._treeSnapshot !== treeSnapshot) {
125126
throw Object.assign(new Error('tree changed in CanPlaceDep'), {

lib/place-dep.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
// and saves a set of what was placed and what needs re-evaluation as
88
// a result.
99

10+
const localeCompare = require('@isaacs/string-locale-compare')('en')
1011
const log = require('proc-log')
1112
const deepestNestingTarget = require('./deepest-nesting-target.js')
1213
const CanPlaceDep = require('./can-place-dep.js')
@@ -473,7 +474,7 @@ class PlaceDep {
473474
// sort these so that they're deterministically ordered
474475
// otherwise, resulting tree shape is dependent on the order
475476
// in which they happened to be resolved.
476-
const nodeSort = (a, b) => a.location.localeCompare(b.location, 'en')
477+
const nodeSort = (a, b) => localeCompare(a.location, b.location)
477478

478479
const children = [...node.children.values()].sort(nodeSort)
479480
for (const child of children) {

lib/printable.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// helper function to output a clearer visualization
22
// of the current node and its descendents
33

4+
const localeCompare = require('@isaacs/string-locale-compare')('en')
45
const util = require('util')
56
const relpath = require('./relpath.js')
67

@@ -67,14 +68,14 @@ class ArboristNode {
6768
// edgesOut sorted by name
6869
if (tree.edgesOut.size) {
6970
this.edgesOut = new Map([...tree.edgesOut.entries()]
70-
.sort(([a], [b]) => a.localeCompare(b, 'en'))
71+
.sort(([a], [b]) => localeCompare(a, b))
7172
.map(([name, edge]) => [name, new EdgeOut(edge)]))
7273
}
7374

7475
// edgesIn sorted by location
7576
if (tree.edgesIn.size) {
7677
this.edgesIn = new Set([...tree.edgesIn]
77-
.sort((a, b) => a.from.location.localeCompare(b.from.location, 'en'))
78+
.sort((a, b) => localeCompare(a.from.location, b.from.location))
7879
.map(edge => new EdgeIn(edge)))
7980
}
8081

@@ -86,14 +87,14 @@ class ArboristNode {
8687
// fsChildren sorted by path
8788
if (tree.fsChildren.size) {
8889
this.fsChildren = new Set([...tree.fsChildren]
89-
.sort(({path: a}, {path: b}) => a.localeCompare(b, 'en'))
90+
.sort(({path: a}, {path: b}) => localeCompare(a, b))
9091
.map(tree => printableTree(tree, path)))
9192
}
9293

9394
// children sorted by name
9495
if (tree.children.size) {
9596
this.children = new Map([...tree.children.entries()]
96-
.sort(([a], [b]) => a.localeCompare(b, 'en'))
97+
.sort(([a], [b]) => localeCompare(a, b))
9798
.map(([name, tree]) => [name, printableTree(tree, path)]))
9899
}
99100
}

lib/shrinkwrap.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// We cannot bump to v3 until npm v6 is out of common usage, and
1010
// definitely not before npm v8.
1111

12+
const localeCompare = require('@isaacs/string-locale-compare')('en')
1213
const lockfileVersion = 2
1314

1415
// for comparing nodes to yarn.lock entries
@@ -911,7 +912,7 @@ class Shrinkwrap {
911912
/* istanbul ignore next - sort calling order is indeterminate */
912913
return aloc.length > bloc.length ? 1
913914
: bloc.length > aloc.length ? -1
914-
: aloc[aloc.length - 1].localeCompare(bloc[bloc.length - 1], 'en')
915+
: localeCompare(aloc[aloc.length - 1], bloc[bloc.length - 1])
915916
})[0]
916917

917918
const res = consistentResolve(node.resolved, this.path, this.path, true)

lib/vuln.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
const {satisfies, simplifyRange} = require('semver')
1515
const semverOpt = { loose: true, includePrerelease: true }
1616

17+
const localeCompare = require('@isaacs/string-locale-compare')('en')
1718
const npa = require('npm-package-arg')
1819
const _range = Symbol('_range')
1920
const _simpleRange = Symbol('_simpleRange')
@@ -112,12 +113,10 @@ class Vuln {
112113
vulnerableVersions: undefined,
113114
id: undefined,
114115
}).sort((a, b) =>
115-
String(a.source || a).localeCompare(String(b.source || b, 'en'))),
116-
effects: [...this.effects].map(v => v.name)
117-
.sort(/* istanbul ignore next */(a, b) => a.localeCompare(b, 'en')),
116+
localeCompare(String(a.source || a), String(b.source || b))),
117+
effects: [...this.effects].map(v => v.name).sort(localeCompare),
118118
range: this.simpleRange,
119-
nodes: [...this.nodes].map(n => n.location)
120-
.sort(/* istanbul ignore next */(a, b) => a.localeCompare(b, 'en')),
119+
nodes: [...this.nodes].map(n => n.location).sort(localeCompare),
121120
fixAvailable: this[_fixAvailable],
122121
}
123122
}

0 commit comments

Comments
 (0)