diff --git a/package.json b/package.json index 5c3ccecc0..22da71982 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,9 @@ "transform": { "^.+\\.tsx?$": "ts-jest" }, + "setupFilesAfterEnv": [ + "./src/jest-setup.js" + ], "testRegex": "\\.test\\.tsx?$", "collectCoverageFrom": [ "**/*.{ts,tsx}", @@ -73,4 +76,4 @@ "dependencies": { "opn": "5.3.0" } -} +} \ No newline at end of file diff --git a/src/jest-setup.js b/src/jest-setup.js new file mode 100644 index 000000000..0e30f43fa --- /dev/null +++ b/src/jest-setup.js @@ -0,0 +1,50 @@ +// Versions of node before 10 had an unstable sort. This isn't really an issue in browsers +// that speedscope supports, but for the purposes of supporting node 10, we'll polyfill +// a stable sort to make the tests pass. +// +// See: +// - https://v8.dev/features/stable-sort +// - https://v8.dev/blog/array-sort +// - https://github.com/jlfwong/speedscope/pull/254#issuecomment-575116995 +// +// Once we stop supporting node 10, this can be removed. +// +// An alternative would be to change our sort implementation to be stable by definition +// rather than relying upon native sort being stable. I don't want to do that because +// we'd take a perf hit. +// +// Because we're not going to use this in our actual build, it's okay for this +// to be inefficient. + +(function () { + const nodeVersion = process.versions.node + const versionParts = nodeVersion.split('.') + const majorVersion = parseInt(versionParts[0], 10) + + if (isNaN(majorVersion)) { + console.warn(`Couldn't determine node major: ${nodeVersion}`) + return + } + + if (majorVersion > 10) { + // Don't need to do the patch for newer node versions + return + } + + const originalSort = Array.prototype.sort + Array.prototype.sort = function (compareFunction) { + const arrayWithIndices = this.map((x, i) => [x, i]) + originalSort.call(arrayWithIndices, (a, b) => { + if (compareFunction) { + const res = compareFunction(a[0], b[0]) + if (res !== 0) return res + } else { + if (a[0] < b[0]) return -1 + if (a[0] > b[0]) return 1 + } + return a[1] < b[1] ? -1 : 1 + }) + this.splice(0, this.length, ...arrayWithIndices.map(x => x[0])) + return this + } +})() \ No newline at end of file