From 6266ae2c0b856036482ce425b224ddc2b4b49793 Mon Sep 17 00:00:00 2001 From: Andrew Bradley Date: Tue, 8 Jun 2021 15:28:32 -0400 Subject: [PATCH] Fix #1282: correct globals in [stdin], [eval], and contexts (#1333) * add failing tests * remove log statement from test * add detailed tests for globals in , [stdin], and [eval] * WIP fixing * more WIP * update tests * WIP * update packagelock * fix tests * Fix and tests * fix test failure on windows * fix programmatic test to cleanup potentially-polluted env prior * modifying programmatic repl test to call out that `module` is unavailable before repl is started * Update tests for Windows env * Fix tests * add retries around npm install in tests on windows * lintfix --- dist-raw/node-cjs-helpers.d.ts | 1 + dist-raw/node-cjs-helpers.js | 51 ++ dist-raw/node-primordials.js | 4 +- package-lock.json | 1169 ++++++++++++++++---------------- package.json | 3 +- src/bin.ts | 175 +++-- src/repl.ts | 63 +- src/test/index.spec.ts | 532 ++++++++++++++- src/util.ts | 8 + tests/repl/script.js | 7 + 10 files changed, 1347 insertions(+), 666 deletions(-) create mode 100644 dist-raw/node-cjs-helpers.d.ts create mode 100644 dist-raw/node-cjs-helpers.js create mode 100644 tests/repl/script.js diff --git a/dist-raw/node-cjs-helpers.d.ts b/dist-raw/node-cjs-helpers.d.ts new file mode 100644 index 000000000..a57c2f831 --- /dev/null +++ b/dist-raw/node-cjs-helpers.d.ts @@ -0,0 +1 @@ +export function addBuiltinLibsToObject(object: any): void; diff --git a/dist-raw/node-cjs-helpers.js b/dist-raw/node-cjs-helpers.js new file mode 100644 index 000000000..20bfb44f8 --- /dev/null +++ b/dist-raw/node-cjs-helpers.js @@ -0,0 +1,51 @@ +const {ArrayPrototypeForEach, StringPrototypeStartsWith, ObjectPrototypeHasOwnProperty, StringPrototypeIncludes, ObjectDefineProperty} = require('./node-primordials'); + +exports.addBuiltinLibsToObject = addBuiltinLibsToObject; + +// Copied from https://github.com/nodejs/node/blob/21f5a56914a3b24ad77535ef369b93c6b1c11d18/lib/internal/modules/cjs/helpers.js#L133-L178 +function addBuiltinLibsToObject(object) { + // Make built-in modules available directly (loaded lazily). + const { builtinModules } = require('module').Module; + ArrayPrototypeForEach(builtinModules, (name) => { + // Neither add underscored modules, nor ones that contain slashes (e.g., + // 'fs/promises') or ones that are already defined. + if (StringPrototypeStartsWith(name, '_') || + StringPrototypeIncludes(name, '/') || + ObjectPrototypeHasOwnProperty(object, name)) { + return; + } + // Goals of this mechanism are: + // - Lazy loading of built-in modules + // - Having all built-in modules available as non-enumerable properties + // - Allowing the user to re-assign these variables as if there were no + // pre-existing globals with the same name. + + const setReal = (val) => { + // Deleting the property before re-assigning it disables the + // getter/setter mechanism. + delete object[name]; + object[name] = val; + }; + + ObjectDefineProperty(object, name, { + get: () => { + const lib = require(name); + + // Disable the current getter/setter and set up a new + // non-enumerable property. + delete object[name]; + ObjectDefineProperty(object, name, { + get: () => lib, + set: setReal, + configurable: true, + enumerable: false + }); + + return lib; + }, + set: setReal, + configurable: true, + enumerable: false + }); + }); +} diff --git a/dist-raw/node-primordials.js b/dist-raw/node-primordials.js index eb4972d4d..d92b499ac 100644 --- a/dist-raw/node-primordials.js +++ b/dist-raw/node-primordials.js @@ -2,10 +2,12 @@ module.exports = { ArrayIsArray: Array.isArray, ArrayPrototypeJoin: (obj, separator) => Array.prototype.join.call(obj, separator), ArrayPrototypeShift: (obj) => Array.prototype.shift.call(obj), + ArrayPrototypeForEach: (arr, ...rest) => Array.prototype.forEach.apply(arr, rest), JSONParse: JSON.parse, JSONStringify: JSON.stringify, ObjectFreeze: Object.freeze, ObjectGetOwnPropertyNames: Object.getOwnPropertyNames, + ObjectDefineProperty: Object.defineProperty, ObjectPrototypeHasOwnProperty: (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop), RegExpPrototypeTest: (obj, string) => RegExp.prototype.test.call(obj, string), SafeMap: Map, @@ -18,5 +20,5 @@ module.exports = { StringPrototypeSlice: (str, ...rest) => String.prototype.slice.apply(str, rest), StringPrototypeSplit: (str, ...rest) => String.prototype.split.apply(str, rest), StringPrototypeStartsWith: (str, ...rest) => String.prototype.startsWith.apply(str, rest), - StringPrototypeSubstr: (str, ...rest) => String.prototype.substr.apply(str, rest) + StringPrototypeSubstr: (str, ...rest) => String.prototype.substr.apply(str, rest), }; diff --git a/package-lock.json b/package-lock.json index 394a9d93a..d85dcdaab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,6 +44,7 @@ "ava": "^3.15.0", "axios": "^0.21.1", "chai": "^4.0.1", + "expect": "^27.0.2", "get-stream": "^6.0.0", "lodash": "^4.17.15", "ntypescript": "^1.201507091536.1", @@ -78,12 +79,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha1-M+JZA9dIEYFTThLsCiXxa2/PQZ4=", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", "dev": true, "dependencies": { - "@babel/highlight": "^7.8.3" + "@babel/highlight": "^7.12.13" } }, "node_modules/@babel/core": { @@ -264,9 +265,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz", - "integrity": "sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", "dev": true }, "node_modules/@babel/helpers": { @@ -281,21 +282,50 @@ } }, "node_modules/@babel/highlight": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", - "integrity": "sha1-TptFzLgreWBycbKXmtgse2gWMHk=", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.9.0", + "@babel/helper-validator-identifier": "^7.14.0", "chalk": "^2.0.0", "js-tokens": "^4.0.0" } }, - "node_modules/@babel/highlight/node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } }, "node_modules/@babel/parser": { "version": "7.9.6", @@ -357,12 +387,6 @@ "to-fast-properties": "^2.0.0" } }, - "node_modules/@babel/types/node_modules/@babel/helper-validator-identifier": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", - "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", - "dev": true - }, "node_modules/@concordance/react": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@concordance/react/-/react-2.0.0.tgz", @@ -467,6 +491,22 @@ "node": ">=8" } }, + "node_modules/@jest/types": { + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", + "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, "node_modules/@microsoft/api-extractor": { "version": "7.15.2", "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.15.2.tgz", @@ -1079,6 +1119,30 @@ "@types/node": "*" } }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, "node_modules/@types/json-schema": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", @@ -1149,6 +1213,27 @@ "@types/node": "*" } }, + "node_modules/@types/stack-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz", + "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", + "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", + "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==", + "dev": true + }, "node_modules/@yarnpkg/fslib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@yarnpkg/fslib/-/fslib-2.4.0.tgz", @@ -1265,6 +1350,15 @@ "node": ">=6" } }, + "node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -1455,15 +1549,6 @@ "node": ">=10.18.0 <11 || >=12.14.0 <12.17.0 || >=12.17.0 <13 || >=14.0.0 <15 || >=15" } }, - "node_modules/ava/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/ava/node_modules/ansi-styles": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.1.0.tgz", @@ -1473,31 +1558,6 @@ "node": ">=10" } }, - "node_modules/ava/node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ava/node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ava/node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -1551,15 +1611,6 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/ava/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/ava/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -1629,18 +1680,6 @@ "node": ">=8" } }, - "node_modules/ava/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ava/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -1775,15 +1814,6 @@ "node": ">=10" } }, - "node_modules/boxen/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/boxen/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -1805,19 +1835,6 @@ "node": ">=10" } }, - "node_modules/boxen/node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/boxen/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1842,15 +1859,6 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/boxen/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/boxen/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -1886,18 +1894,6 @@ "node": ">=8" } }, - "node_modules/boxen/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/boxen/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -2048,31 +2044,54 @@ } }, "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=", + "node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/chalk/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, + "node_modules/chalk/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", @@ -2182,15 +2201,6 @@ "node": ">=8" } }, - "node_modules/cli-truncate/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/cli-truncate/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -2643,6 +2653,15 @@ "node": ">=0.3.1" } }, + "node_modules/diff-sequences": { + "version": "27.0.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.1.tgz", + "integrity": "sha512-XPLijkfJUh/PIBnfkcSHgvD6tlYixmcMAn3osTk6jt+H0v/mgURto1XUiD9DKuGX5NDoVS6dSlA23gd9FUaCFg==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -2806,6 +2825,35 @@ "node": ">=0.10.0" } }, + "node_modules/expect": { + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.0.2.tgz", + "integrity": "sha512-YJFNJe2+P2DqH+ZrXy+ydRQYO87oxRUonZImpDodR1G7qo3NYd3pL+NQ9Keqpez3cehczYwZDBC3A7xk3n7M/w==", + "dev": true, + "dependencies": { + "@jest/types": "^27.0.2", + "ansi-styles": "^5.0.0", + "jest-get-type": "^27.0.1", + "jest-matcher-utils": "^27.0.2", + "jest-message-util": "^27.0.2", + "jest-regex-util": "^27.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/expect/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3158,12 +3206,12 @@ } }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/has-symbols": { @@ -3643,27 +3691,6 @@ "node": ">=8" } }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", @@ -3700,6 +3727,74 @@ "node": ">=8" } }, + "node_modules/jest-diff": { + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.2.tgz", + "integrity": "sha512-BFIdRb0LqfV1hBt8crQmw6gGQHVDhM87SpMIZ45FPYKReZYG5er1+5pIn2zKqvrJp6WNox0ylR8571Iwk2Dmgw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.0.1", + "jest-get-type": "^27.0.1", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "27.0.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.0.1.tgz", + "integrity": "sha512-9Tggo9zZbu0sHKebiAijyt1NM77Z0uO4tuWOxUCujAiSeXv30Vb5D4xVF4UR4YWNapcftj+PbByU54lKD7/xMg==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.0.2.tgz", + "integrity": "sha512-Qczi5xnTNjkhcIB0Yy75Txt+Ez51xdhOxsukN7awzq2auZQGPHcQrJ623PZj0ECDEMOk2soxWx05EXdXGd1CbA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.0.2", + "jest-get-type": "^27.0.1", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.2.tgz", + "integrity": "sha512-rTqWUX42ec2LdMkoUPOzrEd1Tcm+R1KfLOmFK+OVNo4MnLsEaxO5zPDb2BbdSmthdM/IfXxOZU60P/WbWF8BTw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.0.2", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "pretty-format": "^27.0.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-regex-util": { + "version": "27.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.1.tgz", + "integrity": "sha512-6nY6QVcpTgEKQy1L41P4pr3aOddneK17kn3HJw6SdwGiKfgCGTvH02hVXL0GU8GEKtPH83eD2DIDgxHXOxVohQ==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, "node_modules/jju": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", @@ -4058,16 +4153,16 @@ } }, "node_modules/micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", "dev": true, "dependencies": { "braces": "^3.0.1", - "picomatch": "^2.0.5" + "picomatch": "^2.2.3" }, "engines": { - "node": ">=8" + "node": ">=8.6" } }, "node_modules/mimic-fn": { @@ -4234,15 +4329,6 @@ "node": ">=8.9" } }, - "node_modules/nyc/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/nyc/node_modules/ansi-styles": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", @@ -4539,67 +4625,6 @@ "node": ">=10" } }, - "node_modules/ora/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ora/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ora/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/ora/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/ora/node_modules/log-symbols": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", @@ -4624,18 +4649,6 @@ "node": ">=8" } }, - "node_modules/ora/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/p-cancelable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", @@ -4845,12 +4858,15 @@ } }, "node_modules/picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", "dev": true, "engines": { "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/pify": { @@ -4966,6 +4982,39 @@ "node": ">=10.13.0" } }, + "node_modules/pretty-format": { + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.2.tgz", + "integrity": "sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig==", + "dev": true, + "dependencies": { + "@jest/types": "^27.0.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, "node_modules/pretty-ms": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", @@ -5698,15 +5747,6 @@ "node": ">=10" } }, - "node_modules/supertap/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/supertap/node_modules/js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", @@ -5732,6 +5772,18 @@ "node": ">=8" } }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/temp-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", @@ -6087,58 +6139,6 @@ "node": ">=10" } }, - "node_modules/update-notifier/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/update-notifier/node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/update-notifier/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/update-notifier/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/update-notifier/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/update-notifier/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -6166,18 +6166,6 @@ "node": ">=10" } }, - "node_modules/update-notifier/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/update-notifier/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -6293,15 +6281,6 @@ "node": ">=8" } }, - "node_modules/widest-line/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/widest-line/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -6465,12 +6444,12 @@ }, "dependencies": { "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha1-M+JZA9dIEYFTThLsCiXxa2/PQZ4=", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", "dev": true, "requires": { - "@babel/highlight": "^7.8.3" + "@babel/highlight": "^7.12.13" } }, "@babel/core": { @@ -6643,9 +6622,9 @@ } }, "@babel/helper-validator-identifier": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz", - "integrity": "sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", "dev": true }, "@babel/helpers": { @@ -6660,21 +6639,41 @@ } }, "@babel/highlight": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", - "integrity": "sha1-TptFzLgreWBycbKXmtgse2gWMHk=", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.9.0", + "@babel/helper-validator-identifier": "^7.14.0", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, "dependencies": { - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -6732,14 +6731,6 @@ "@babel/helper-validator-identifier": "^7.9.5", "lodash": "^4.17.13", "to-fast-properties": "^2.0.0" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", - "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", - "dev": true - } } }, "@concordance/react": { @@ -6823,6 +6814,19 @@ "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", "dev": true }, + "@jest/types": { + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", + "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, "@microsoft/api-extractor": { "version": "7.15.2", "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.15.2.tgz", @@ -7293,6 +7297,30 @@ "@types/node": "*" } }, + "@types/istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, "@types/json-schema": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", @@ -7363,6 +7391,27 @@ "@types/node": "*" } }, + "@types/stack-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz", + "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==", + "dev": true + }, + "@types/yargs": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", + "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", + "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==", + "dev": true + }, "@yarnpkg/fslib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@yarnpkg/fslib/-/fslib-2.4.0.tgz", @@ -7454,6 +7503,12 @@ } } }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -7608,39 +7663,12 @@ "yargs": "^16.2.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "ansi-styles": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.1.0.tgz", "integrity": "sha512-osxifZo3ar56+e8tdYreU6p8FZGciBHo5O0JoDAxMUqZuyNUb+yHEwYtJZ+Z32R459jEgtwVf1u8D7qYwU0l6w==", "dev": true }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - } - } - }, "cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -7690,12 +7718,6 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -7753,15 +7775,6 @@ "ansi-regex": "^5.0.0" } }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -7881,12 +7894,6 @@ "wrap-ansi": "^7.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -7902,16 +7909,6 @@ "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", "dev": true }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -7933,12 +7930,6 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -7965,15 +7956,6 @@ "ansi-regex": "^5.0.0" } }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -8098,24 +8080,38 @@ } }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true } } }, @@ -8202,12 +8198,6 @@ "string-width": "^4.2.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -8577,6 +8567,12 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==" }, + "diff-sequences": { + "version": "27.0.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.1.tgz", + "integrity": "sha512-XPLijkfJUh/PIBnfkcSHgvD6tlYixmcMAn3osTk6jt+H0v/mgURto1XUiD9DKuGX5NDoVS6dSlA23gd9FUaCFg==", + "dev": true + }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -8703,6 +8699,28 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "expect": { + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.0.2.tgz", + "integrity": "sha512-YJFNJe2+P2DqH+ZrXy+ydRQYO87oxRUonZImpDodR1G7qo3NYd3pL+NQ9Keqpez3cehczYwZDBC3A7xk3n7M/w==", + "dev": true, + "requires": { + "@jest/types": "^27.0.2", + "ansi-styles": "^5.0.0", + "jest-get-type": "^27.0.1", + "jest-matcher-utils": "^27.0.2", + "jest-message-util": "^27.0.2", + "jest-regex-util": "^27.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -8980,9 +8998,9 @@ } }, "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, "has-symbols": { @@ -9350,23 +9368,6 @@ "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", "supports-color": "^7.1.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "istanbul-lib-source-maps": { @@ -9401,6 +9402,59 @@ "istanbul-lib-report": "^3.0.0" } }, + "jest-diff": { + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.2.tgz", + "integrity": "sha512-BFIdRb0LqfV1hBt8crQmw6gGQHVDhM87SpMIZ45FPYKReZYG5er1+5pIn2zKqvrJp6WNox0ylR8571Iwk2Dmgw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.0.1", + "jest-get-type": "^27.0.1", + "pretty-format": "^27.0.2" + } + }, + "jest-get-type": { + "version": "27.0.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.0.1.tgz", + "integrity": "sha512-9Tggo9zZbu0sHKebiAijyt1NM77Z0uO4tuWOxUCujAiSeXv30Vb5D4xVF4UR4YWNapcftj+PbByU54lKD7/xMg==", + "dev": true + }, + "jest-matcher-utils": { + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.0.2.tgz", + "integrity": "sha512-Qczi5xnTNjkhcIB0Yy75Txt+Ez51xdhOxsukN7awzq2auZQGPHcQrJ623PZj0ECDEMOk2soxWx05EXdXGd1CbA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^27.0.2", + "jest-get-type": "^27.0.1", + "pretty-format": "^27.0.2" + } + }, + "jest-message-util": { + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.2.tgz", + "integrity": "sha512-rTqWUX42ec2LdMkoUPOzrEd1Tcm+R1KfLOmFK+OVNo4MnLsEaxO5zPDb2BbdSmthdM/IfXxOZU60P/WbWF8BTw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.0.2", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "pretty-format": "^27.0.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-regex-util": { + "version": "27.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.1.tgz", + "integrity": "sha512-6nY6QVcpTgEKQy1L41P4pr3aOddneK17kn3HJw6SdwGiKfgCGTvH02hVXL0GU8GEKtPH83eD2DIDgxHXOxVohQ==", + "dev": true + }, "jju": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", @@ -9700,13 +9754,13 @@ "dev": true }, "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", "dev": true, "requires": { "braces": "^3.0.1", - "picomatch": "^2.0.5" + "picomatch": "^2.2.3" } }, "mimic-fn": { @@ -9845,12 +9899,6 @@ "yargs": "^15.0.2" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "ansi-styles": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", @@ -10092,52 +10140,6 @@ "wcwidth": "^1.0.1" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, "log-symbols": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", @@ -10155,15 +10157,6 @@ "requires": { "ansi-regex": "^5.0.0" } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } } } }, @@ -10321,9 +10314,9 @@ "dev": true }, "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", "dev": true }, "pify": { @@ -10408,6 +10401,32 @@ "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", "dev": true }, + "pretty-format": { + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.2.tgz", + "integrity": "sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig==", + "dev": true, + "requires": { + "@jest/types": "^27.0.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + } + } + }, "pretty-ms": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", @@ -11007,12 +11026,6 @@ "strip-ansi": "^6.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", @@ -11034,6 +11047,15 @@ } } }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, "temp-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", @@ -11312,46 +11334,6 @@ "xdg-basedir": "^4.0.0" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -11370,15 +11352,6 @@ "lru-cache": "^6.0.0" } }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -11481,12 +11454,6 @@ "string-width": "^4.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", diff --git a/package.json b/package.json index 76dbbe56f..0769c6e2f 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "/transpilers/", "/dist/", "!/dist/test", - "/dist-raw/", + "/dist-raw/**.js", "/register/", "/esm/", "/esm.mjs", @@ -127,6 +127,7 @@ "ava": "^3.15.0", "axios": "^0.21.1", "chai": "^4.0.1", + "expect": "^27.0.2", "get-stream": "^6.0.0", "lodash": "^4.17.15", "ntypescript": "^1.201507091536.1", diff --git a/src/bin.ts b/src/bin.ts index 811f942be..3bd35921f 100644 --- a/src/bin.ts +++ b/src/bin.ts @@ -4,10 +4,22 @@ import { join, resolve, dirname, parse as parsePath } from 'path'; import { inspect } from 'util'; import Module = require('module'); import arg = require('arg'); -import { parse, createRequire } from './util'; -import { EVAL_FILENAME, EvalState, createRepl, ReplService } from './repl'; +import { parse, createRequire, hasOwnProperty } from './util'; +import { + EVAL_FILENAME, + EvalState, + createRepl, + ReplService, + setContext, + STDIN_FILENAME, + EvalAwarePartialHost, + EVAL_NAME, + STDIN_NAME, + REPL_FILENAME, +} from './repl'; import { VERSION, TSError, register } from './index'; import type { TSInternal } from './ts-compiler-types'; +import { addBuiltinLibsToObject } from '../dist-raw/node-cjs-helpers'; /** * Main `bin` functionality. @@ -159,12 +171,79 @@ export function main( process.exit(0); } + // Figure out which we are executing: piped stdin, --eval, REPL, and/or entrypoint + // This is complicated because node's behavior is complicated + // `node -e code -i ./script.js` ignores -e + const executeEval = code != null && !(interactive && args._.length); + const executeEntrypoint = !executeEval && args._.length > 0; + const executeRepl = + !executeEntrypoint && + (interactive || (process.stdin.isTTY && !executeEval)); + const executeStdin = !executeEval && !executeRepl && !executeEntrypoint; + const cwd = cwdArg || process.cwd(); /** Unresolved. May point to a symlink, not realpath. May be missing file extension */ - const scriptPath = args._.length ? resolve(cwd, args._[0]) : undefined; - const state = new EvalState(scriptPath || join(cwd, EVAL_FILENAME)); - const replService = createRepl({ state }); - const { evalAwarePartialHost } = replService; + const scriptPath = executeEntrypoint ? resolve(cwd, args._[0]) : undefined; + + /** + * , [stdin], and [eval] are all essentially virtual files that do not exist on disc and are backed by a REPL + * service to handle eval-ing of code. + */ + interface VirtualFileState { + state: EvalState; + repl: ReplService; + module?: Module; + } + let evalStuff: VirtualFileState | undefined; + let replStuff: VirtualFileState | undefined; + let stdinStuff: VirtualFileState | undefined; + // let evalService: ReplService | undefined; + // let replState: EvalState | undefined; + // let replService: ReplService | undefined; + // let stdinState: EvalState | undefined; + // let stdinService: ReplService | undefined; + let evalAwarePartialHost: EvalAwarePartialHost | undefined = undefined; + if (executeEval) { + const state = new EvalState(join(cwd, EVAL_FILENAME)); + evalStuff = { + state, + repl: createRepl({ + state, + composeWithEvalAwarePartialHost: evalAwarePartialHost, + }), + }; + ({ evalAwarePartialHost } = evalStuff.repl); + // Create a local module instance based on `cwd`. + const module = (evalStuff.module = new Module(EVAL_NAME)); + module.filename = evalStuff.state.path; + module.paths = (Module as any)._nodeModulePaths(cwd); + } + if (executeStdin) { + const state = new EvalState(join(cwd, STDIN_FILENAME)); + stdinStuff = { + state, + repl: createRepl({ + state, + composeWithEvalAwarePartialHost: evalAwarePartialHost, + }), + }; + ({ evalAwarePartialHost } = stdinStuff.repl); + // Create a local module instance based on `cwd`. + const module = (stdinStuff.module = new Module(STDIN_NAME)); + module.filename = stdinStuff.state.path; + module.paths = (Module as any)._nodeModulePaths(cwd); + } + if (executeRepl) { + const state = new EvalState(join(cwd, REPL_FILENAME)); + replStuff = { + state, + repl: createRepl({ + state, + composeWithEvalAwarePartialHost: evalAwarePartialHost, + }), + }; + ({ evalAwarePartialHost } = replStuff.repl); + } // Register the TypeScript compiler instance. const service = register({ @@ -187,15 +266,16 @@ export function main( ignoreDiagnostics, compilerOptions, require: argsRequire, - readFile: code !== undefined ? evalAwarePartialHost.readFile : undefined, - fileExists: - code !== undefined ? evalAwarePartialHost.fileExists : undefined, + readFile: evalAwarePartialHost?.readFile ?? undefined, + fileExists: evalAwarePartialHost?.fileExists ?? undefined, scope, scopeDir, }); // Bind REPL service to ts-node compiler service (chicken-and-egg problem) - replService.setService(service); + replStuff?.repl.setService(service); + evalStuff?.repl.setService(service); + stdinStuff?.repl.setService(service); // Output project information. if (version >= 2) { @@ -235,38 +315,45 @@ export function main( process.exit(0); } - // Create a local module instance based on `cwd`. - const module = new Module(state.path); - module.filename = state.path; - module.paths = (Module as any)._nodeModulePaths(cwd); - // Prepend `ts-node` arguments to CLI for child processes. process.execArgv.unshift( __filename, ...process.argv.slice(2, process.argv.length - args._.length) ); process.argv = [process.argv[1]] - .concat(scriptPath || []) - .concat(args._.slice(1)); + .concat(executeEntrypoint ? ([scriptPath] as string[]) : []) + .concat(args._.slice(executeEntrypoint ? 1 : 0)); // Execute the main contents (either eval, script or piped). - if (code !== undefined && !interactive) { - evalAndExit(replService, module, code, print); + if (executeEntrypoint) { + Module.runMain(); } else { - if (args._.length) { - Module.runMain(); - } else { - // Piping of execution _only_ occurs when no other script is specified. - // --interactive flag forces REPL - if (interactive || process.stdin.isTTY) { - replService.start(code); - } else { - let buffer = code || ''; - process.stdin.on('data', (chunk: Buffer) => (buffer += chunk)); - process.stdin.on('end', () => - evalAndExit(replService, module, buffer, print) + if (executeEval) { + addBuiltinLibsToObject(global); + evalAndExitOnTsError( + evalStuff!.repl, + evalStuff!.module!, + code!, + print, + 'eval' + ); + } + if (executeRepl) { + replStuff!.repl.start(); + } + if (executeStdin) { + let buffer = code || ''; + process.stdin.on('data', (chunk: Buffer) => (buffer += chunk)); + process.stdin.on('end', () => { + evalAndExitOnTsError( + stdinStuff!.repl, + stdinStuff!.module!, + buffer, + // `echo 123 | node -p` still prints 123 + print, + 'stdin' ); - } + }); } } } @@ -353,20 +440,17 @@ function requireResolveNonCached(absoluteModuleSpecifier: string) { } /** - * Evaluate a script. + * Evaluate an [eval] or [stdin] script */ -function evalAndExit( +function evalAndExitOnTsError( replService: ReplService, module: Module, code: string, - isPrinted: boolean + isPrinted: boolean, + filenameAndDirname: 'eval' | 'stdin' ) { let result: any; - (global as any).__filename = module.filename; - (global as any).__dirname = dirname(module.filename); - (global as any).exports = module.exports; - (global as any).module = module; - (global as any).require = module.require.bind(module); + setContext(global, module, filenameAndDirname); try { result = replService.evalCode(code); @@ -380,15 +464,14 @@ function evalAndExit( } if (isPrinted) { - console.log(typeof result === 'string' ? result : inspect(result)); + console.log( + typeof result === 'string' + ? result + : inspect(result, { colors: process.stdout.isTTY }) + ); } } -/** Safe `hasOwnProperty` */ -function hasOwnProperty(object: any, property: string): boolean { - return Object.prototype.hasOwnProperty.call(object, property); -} - if (require.main === module) { main(); } diff --git a/src/repl.ts b/src/repl.ts index 18acb516e..45957f8d0 100644 --- a/src/repl.ts +++ b/src/repl.ts @@ -1,18 +1,26 @@ import { diffLines } from 'diff'; import { homedir } from 'os'; -import { join } from 'path'; +import { dirname, join } from 'path'; import { Recoverable, start } from 'repl'; import { Script } from 'vm'; import { Service, CreateOptions, TSError, env } from './index'; import { readFileSync, statSync } from 'fs'; import { Console } from 'console'; import type * as tty from 'tty'; +import Module = require('module'); -/** - * Eval filename for REPL/debug. - * @internal - */ +/** @internal */ export const EVAL_FILENAME = `[eval].ts`; +/** @internal */ +export const EVAL_NAME = `[eval]`; +/** @internal */ +export const STDIN_FILENAME = `[stdin].ts`; +/** @internal */ +export const STDIN_NAME = `[stdin]`; +/** @internal */ +export const REPL_FILENAME = '.ts'; +/** @internal */ +export const REPL_NAME = ''; export interface ReplService { readonly state: EvalState; @@ -49,6 +57,8 @@ export interface CreateReplOptions { stdin?: NodeJS.ReadableStream; stdout?: NodeJS.WritableStream; stderr?: NodeJS.WritableStream; + /** @internal */ + composeWithEvalAwarePartialHost?: EvalAwarePartialHost; } /** @@ -64,8 +74,11 @@ export interface CreateReplOptions { export function createRepl(options: CreateReplOptions = {}) { let service = options.service; const state = - options.state ?? new EvalState(join(process.cwd(), EVAL_FILENAME)); - const evalAwarePartialHost = createEvalAwarePartialHost(state); + options.state ?? new EvalState(join(process.cwd(), REPL_FILENAME)); + const evalAwarePartialHost = createEvalAwarePartialHost( + state, + options.composeWithEvalAwarePartialHost + ); const stdin = options.stdin ?? process.stdin; const stdout = options.stdout ?? process.stdout; const stderr = options.stderr ?? process.stderr; @@ -163,11 +176,14 @@ export type EvalAwarePartialHost = Pick< >; export function createEvalAwarePartialHost( - state: EvalState + state: EvalState, + composeWith?: EvalAwarePartialHost ): EvalAwarePartialHost { function readFile(path: string) { if (path === state.path) return state.input; + if (composeWith?.readFile) return composeWith.readFile(path); + try { return readFileSync(path, 'utf8'); } catch (err) { @@ -177,6 +193,8 @@ export function createEvalAwarePartialHost( function fileExists(path: string) { if (path === state.path) return true; + if (composeWith?.fileExists) return composeWith.fileExists(path); + try { const stats = statSync(path); return stats.isFile() || stats.isFIFO(); @@ -221,7 +239,7 @@ function _eval(service: Service, state: EvalState, input: string) { * Execute some code. */ function exec(code: string, filename: string) { - const script = new Script(code, { filename: filename }); + const script = new Script(code, { filename }); return script.runInThisContext(); } @@ -368,3 +386,30 @@ const RECOVERY_CODES: Set = new Set([ function isRecoverable(error: TSError) { return error.diagnosticCodes.every((code) => RECOVERY_CODES.has(code)); } + +/** @internal */ +export function setContext( + context: any, + module: Module, + filenameAndDirname: 'eval' | 'stdin' | null +) { + if (filenameAndDirname) { + context.__dirname = '.'; + context.__filename = `[${filenameAndDirname}]`; + } + context.module = module; + context.exports = module.exports; + context.require = module.require.bind(module); +} + +/** @internal */ +export function createNodeModuleForContext( + type: 'eval' | 'stdin', + cwd: string +) { + // Create a local module instance based on `cwd`. + const module = new Module(`[${type}]`); + module.filename = join(cwd, module.id) + '.ts'; + module.paths = (Module as any)._nodeModulePaths(cwd); + return module; +} diff --git a/src/test/index.spec.ts b/src/test/index.spec.ts index 049b0481c..b7263fa0d 100644 --- a/src/test/index.spec.ts +++ b/src/test/index.spec.ts @@ -1,13 +1,14 @@ import { test, TestInterface } from './testlib'; import { expect } from 'chai'; +import * as exp from 'expect'; import { ChildProcess, exec as childProcessExec, ExecException, ExecOptions, } from 'child_process'; -import { join, resolve, sep as pathSep } from 'path'; -import { tmpdir } from 'os'; +import { dirname, join, resolve, sep as pathSep } from 'path'; +import { homedir, tmpdir } from 'os'; import semver = require('semver'); import ts = require('typescript'); import proxyquire = require('proxyquire'); @@ -82,10 +83,20 @@ let { register, create, VERSION, createRepl }: typeof tsNodeTypes = {} as any; // Pack and install ts-node locally, necessary to test package "exports" test.beforeAll(async () => { - rimrafSync(join(TEST_DIR, 'node_modules')); - await promisify(childProcessExec)(`npm install`, { cwd: TEST_DIR }); - const packageLockPath = join(TEST_DIR, 'package-lock.json'); - existsSync(packageLockPath) && unlinkSync(packageLockPath); + const totalTries = process.platform === 'win32' ? 5 : 1; + let tries = 0; + while (true) { + try { + rimrafSync(join(TEST_DIR, 'node_modules')); + await promisify(childProcessExec)(`npm install`, { cwd: TEST_DIR }); + const packageLockPath = join(TEST_DIR, 'package-lock.json'); + existsSync(packageLockPath) && unlinkSync(packageLockPath); + break; + } catch (e) { + tries++; + if (tries >= totalTries) throw e; + } + } ({ register, create, VERSION, createRepl } = testsDirRequire('ts-node')); }); @@ -400,8 +411,7 @@ test.suite('ts-node', (test) => { ); }); - // Serial because it's timing-sensitive - test.serial('REPL can be created via API', async () => { + function createReplViaApi() { const stdin = new PassThrough(); const stdout = new PassThrough(); const stderr = new PassThrough(); @@ -415,6 +425,12 @@ test.suite('ts-node', (test) => { project: `${TEST_DIR}/tsconfig.json`, }); replService.setService(service); + return { stdin, stdout, stderr, replService, service }; + } + + // Serial because it's timing-sensitive + test.serial('REPL can be created via API', async () => { + const { stdin, stdout, stderr, replService } = createReplViaApi(); replService.start(); stdin.write('\nconst a = 123\n.type a\n'); stdin.end(); @@ -427,6 +443,506 @@ test.suite('ts-node', (test) => { ); }); + test.suite( + '[eval], , and [stdin] execute with correct globals', + (test) => { + const cliTest = test.macro( + ( + { + flags, + stdin, + allowError = false, + }: { + flags: string; + stdin: string; + allowError?: boolean; + }, + assertions: ( + stdout: string, + stderr: string, + err: ExecException | null + ) => Promise | void + ) => async (t) => { + const execPromise = exec(`${cmd} ${flags}`); + // Uncomment to run against vanilla node, useful to verify that these test cases match vanilla node + // const execPromise = exec(`node ${flags}`); + execPromise.child.stdin!.end(stdin); + const { err, stdout, stderr } = await execPromise; + if (!allowError) expect(err).to.equal(null); + await assertions(stdout, stderr, err); + } + ); + interface GlobalInRepl extends NodeJS.Global { + testReport: any; + replReport: any; + stdinReport: any; + evalReport: any; + module: any; + exports: any; + fs: any; + __filename: any; + __dirname: any; + } + const globalInRepl = global as GlobalInRepl; + const programmaticTest = test.macro( + ( + { + evalCodeBefore, + stdinCode, + }: { + evalCodeBefore: string | null; + stdinCode: string; + }, + assertions: (stdout: string) => Promise | void + ) => async (t) => { + delete globalInRepl.testReport; + delete globalInRepl.replReport; + delete globalInRepl.stdinReport; + delete globalInRepl.evalReport; + delete globalInRepl.module; + delete globalInRepl.exports; + delete globalInRepl.fs; + delete globalInRepl.__filename; + delete globalInRepl.__dirname; + const { stdin, stderr, stdout, replService } = createReplViaApi(); + if (typeof evalCodeBefore === 'string') { + replService.evalCode(evalCodeBefore); + } + replService.start(); + stdin.write(stdinCode); + stdin.end(); + await promisify(setTimeout)(1e3); + stdout.end(); + stderr.end(); + expect(await getStream(stderr)).to.equal(''); + await assertions(await getStream(stdout)); + } + ); + + const declareGlobals = `declare var replReport: any, stdinReport: any, evalReport: any, restReport: any, global: any, __filename: any, __dirname: any, module: any, exports: any, fs: any;`; + function setReportGlobal(type: 'repl' | 'stdin' | 'eval') { + return ` + ${declareGlobals} + global.${type}Report = { + __filename: typeof __filename !== 'undefined' && __filename, + __dirname: typeof __dirname !== 'undefined' && __dirname, + moduleId: typeof module !== 'undefined' && module.id, + modulePath: typeof module !== 'undefined' && module.path, + moduleFilename: typeof module !== 'undefined' && module.filename, + modulePaths: typeof module !== 'undefined' && [...module.paths], + exportsTest: typeof exports !== 'undefined' ? module.exports === exports : null, + stackTest: new Error().stack!.split('\\n')[1], + moduleAccessorsTest: typeof fs === 'undefined' ? null : fs === require('fs'), + argv: [...process.argv] + }; + `.replace(/\n/g, ''); + } + const reportsObject = ` + { + stdinReport: typeof stdinReport !== 'undefined' && stdinReport, + evalReport: typeof evalReport !== 'undefined' && evalReport, + replReport: typeof replReport !== 'undefined' && replReport + } + `; + const printReports = ` + ${declareGlobals} + console.log(JSON.stringify(${reportsObject})); + `.replace(/\n/g, ''); + const saveReportsAsGlobal = ` + ${declareGlobals} + global.testReport = ${reportsObject}; + `.replace(/\n/g, ''); + + function parseStdoutStripReplPrompt(stdout: string) { + // Strip node's welcome header, only uncomment if running these tests manually against vanilla node + // stdout = stdout.replace(/^Welcome to.*\nType "\.help" .*\n/, ''); + expect(stdout.slice(0, 2)).to.equal('> '); + expect(stdout.slice(-12)).to.equal('undefined\n> '); + return parseStdout(stdout.slice(2, -12)); + } + function parseStdout(stdout: string) { + return JSON.parse(stdout); + } + + /** Every possible ./node_modules directory ascending upwards starting with ./tests/node_modules */ + const modulePaths = createModulePaths(TEST_DIR); + const rootModulePaths = createModulePaths(ROOT_DIR); + function createModulePaths(dir: string) { + const modulePaths: string[] = []; + for (let path = dir; ; path = dirname(path)) { + modulePaths.push(join(path, 'node_modules')); + if (dirname(path) === path) break; + } + return modulePaths; + } + + // Executable is `ts-node` on Posix, `bin.js` on Windows due to Windows shimming limitations (this is determined by package manager) + const tsNodeExe = exp.stringMatching(/\b(ts-node|bin.js)$/); + + test( + 'stdin', + cliTest, + { + stdin: `${setReportGlobal('stdin')};${printReports}`, + flags: '', + }, + (stdout) => { + const report = parseStdout(stdout); + exp(report).toMatchObject({ + stdinReport: { + __filename: '[stdin]', + __dirname: '.', + moduleId: '[stdin]', + modulePath: '.', + // Note: vanilla node does does not have file extension + moduleFilename: join(TEST_DIR, `[stdin].ts`), + modulePaths, + exportsTest: true, + // Note: vanilla node uses different name. See #1360 + stackTest: exp.stringContaining( + ` at ${join(TEST_DIR, `[stdin].ts`)}:1:` + ), + moduleAccessorsTest: null, + argv: [tsNodeExe], + }, + evalReport: false, + replReport: false, + }); + } + ); + test( + 'repl', + cliTest, + { + stdin: `${setReportGlobal('repl')};${printReports}`, + flags: '-i', + }, + (stdout) => { + const report = parseStdoutStripReplPrompt(stdout); + exp(report).toMatchObject({ + stdinReport: false, + evalReport: false, + replReport: { + __filename: false, + __dirname: false, + moduleId: '', + modulePath: '.', + moduleFilename: null, + modulePaths: exp.objectContaining({ + ...[join(TEST_DIR, `repl/node_modules`), ...modulePaths], + }), + // Note: vanilla node REPL does not set exports + exportsTest: true, + // Note: vanilla node uses different name. See #1360 + stackTest: exp.stringContaining( + ` at ${join(TEST_DIR, '.ts')}:1:` + ), + moduleAccessorsTest: true, + argv: [tsNodeExe], + }, + }); + // Prior to these, nyc adds another entry on Windows; we need to ignore it + exp(report.replReport.modulePaths.slice(-3)).toMatchObject([ + join(homedir(), `.node_modules`), + join(homedir(), `.node_libraries`), + // additional entry goes to node's install path + exp.any(String), + ]); + } + ); + + // Should ignore -i and run the entrypoint + test( + '-i w/entrypoint ignores -i', + cliTest, + { + stdin: `${setReportGlobal('repl')};${printReports}`, + flags: '-i ./repl/script.js', + }, + (stdout) => { + const report = parseStdout(stdout); + exp(report).toMatchObject({ + stdinReport: false, + evalReport: false, + replReport: false, + }); + } + ); + + // Should not execute stdin + // Should not interpret positional arg as an entrypoint script + test( + '-e', + cliTest, + { + stdin: `throw new Error()`, + flags: `-e "${setReportGlobal('eval')};${printReports}"`, + }, + (stdout) => { + const report = parseStdout(stdout); + exp(report).toMatchObject({ + stdinReport: false, + evalReport: { + __filename: '[eval]', + __dirname: '.', + moduleId: '[eval]', + modulePath: '.', + // Note: vanilla node does does not have file extension + moduleFilename: join(TEST_DIR, `[eval].ts`), + modulePaths: [...modulePaths], + exportsTest: true, + // Note: vanilla node uses different name. See #1360 + stackTest: exp.stringContaining( + ` at ${join(TEST_DIR, `[eval].ts`)}:1:` + ), + moduleAccessorsTest: true, + argv: [tsNodeExe], + }, + replReport: false, + }); + } + ); + test( + '-e w/entrypoint arg does not execute entrypoint', + cliTest, + { + stdin: `throw new Error()`, + flags: `-e "${setReportGlobal( + 'eval' + )};${printReports}" ./repl/script.js`, + }, + (stdout) => { + const report = parseStdout(stdout); + exp(report).toMatchObject({ + stdinReport: false, + evalReport: { + __filename: '[eval]', + __dirname: '.', + moduleId: '[eval]', + modulePath: '.', + // Note: vanilla node does does not have file extension + moduleFilename: join(TEST_DIR, `[eval].ts`), + modulePaths, + exportsTest: true, + // Note: vanilla node uses different name. See #1360 + stackTest: exp.stringContaining( + ` at ${join(TEST_DIR, `[eval].ts`)}:1:` + ), + moduleAccessorsTest: true, + argv: [tsNodeExe, './repl/script.js'], + }, + replReport: false, + }); + } + ); + test( + '-e w/non-path arg', + cliTest, + { + stdin: `throw new Error()`, + flags: `-e "${setReportGlobal( + 'eval' + )};${printReports}" ./does-not-exist.js`, + }, + (stdout) => { + const report = parseStdout(stdout); + exp(report).toMatchObject({ + stdinReport: false, + evalReport: { + __filename: '[eval]', + __dirname: '.', + moduleId: '[eval]', + modulePath: '.', + // Note: vanilla node does does not have file extension + moduleFilename: join(TEST_DIR, `[eval].ts`), + modulePaths, + exportsTest: true, + // Note: vanilla node uses different name. See #1360 + stackTest: exp.stringContaining( + ` at ${join(TEST_DIR, `[eval].ts`)}:1:` + ), + moduleAccessorsTest: true, + argv: [tsNodeExe, './does-not-exist.js'], + }, + replReport: false, + }); + } + ); + test( + '-e -i', + cliTest, + { + stdin: `${setReportGlobal('repl')};${printReports}`, + flags: `-e "${setReportGlobal('eval')}" -i`, + }, + (stdout) => { + const report = parseStdoutStripReplPrompt(stdout); + exp(report).toMatchObject({ + stdinReport: false, + evalReport: { + __filename: '[eval]', + __dirname: '.', + moduleId: '[eval]', + modulePath: '.', + // Note: vanilla node does does not have file extension + moduleFilename: join(TEST_DIR, `[eval].ts`), + modulePaths, + exportsTest: true, + // Note: vanilla node uses different name. See #1360 + stackTest: exp.stringContaining( + ` at ${join(TEST_DIR, `[eval].ts`)}:1:` + ), + moduleAccessorsTest: true, + argv: [tsNodeExe], + }, + replReport: { + __filename: '[eval]', + __dirname: '.', + moduleId: '', + modulePath: '.', + moduleFilename: null, + modulePaths: exp.objectContaining({ + ...[join(TEST_DIR, `repl/node_modules`), ...modulePaths], + }), + // Note: vanilla node REPL does not set exports, so this would be false + exportsTest: true, + // Note: vanilla node uses different name. See #1360 + stackTest: exp.stringContaining( + ` at ${join(TEST_DIR, '.ts')}:1:` + ), + moduleAccessorsTest: true, + argv: [tsNodeExe], + }, + }); + // Prior to these, nyc adds another entry on Windows; we need to ignore it + exp(report.replReport.modulePaths.slice(-3)).toMatchObject([ + join(homedir(), `.node_modules`), + join(homedir(), `.node_libraries`), + // additional entry goes to node's install path + exp.any(String), + ]); + } + ); + + test( + '-e -i w/entrypoint ignores -e and -i, runs entrypoint', + cliTest, + { + stdin: `throw new Error()`, + flags: '-e "throw new Error()" -i ./repl/script.js', + }, + (stdout) => { + const report = parseStdout(stdout); + exp(report).toMatchObject({ + stdinReport: false, + evalReport: false, + replReport: false, + }); + } + ); + + test( + '-e -i when -e throws error, -i does not run', + cliTest, + { + stdin: `console.log('hello')`, + flags: `-e "throw new Error('error from -e')" -i`, + allowError: true, + }, + (stdout, stderr, err) => { + exp(err).toBeDefined(); + exp(stdout).toBe(''); + exp(stderr).toContain('error from -e'); + } + ); + + // Serial because it's timing-sensitive + test.serial( + 'programmatically, eval-ing before starting REPL', + programmaticTest, + { + evalCodeBefore: `${setReportGlobal('repl')};${saveReportsAsGlobal}`, + stdinCode: '', + }, + (stdout) => { + exp(globalInRepl.testReport).toMatchObject({ + stdinReport: false, + evalReport: false, + replReport: { + __filename: false, + __dirname: false, + + // Due to limitations in node's REPL API, we can't really expose + // the `module` prior to calling repl.start() which also sends + // output to stdout. + // For now, leaving this as unsupported / undefined behavior. + + // moduleId: '', + // modulePath: '.', + // moduleFilename: null, + // modulePaths: [ + // join(ROOT_DIR, `repl/node_modules`), + // ...rootModulePaths, + // join(homedir(), `.node_modules`), + // join(homedir(), `.node_libraries`), + // // additional entry goes to node's install path + // exp.any(String), + // ], + // // Note: vanilla node REPL does not set exports + // exportsTest: true, + // moduleAccessorsTest: true, + + // Note: vanilla node uses different name. See #1360 + stackTest: exp.stringContaining( + ` at ${join(ROOT_DIR, '.ts')}:1:` + ), + }, + }); + } + ); + test.serial( + 'programmatically, passing code to stdin after starting REPL', + programmaticTest, + { + evalCodeBefore: null, + stdinCode: `${setReportGlobal('repl')};${saveReportsAsGlobal}`, + }, + (stdout) => { + exp(globalInRepl.testReport).toMatchObject({ + stdinReport: false, + evalReport: false, + replReport: { + __filename: false, + __dirname: false, + moduleId: '', + modulePath: '.', + moduleFilename: null, + modulePaths: exp.objectContaining({ + ...[join(ROOT_DIR, `repl/node_modules`), ...rootModulePaths], + }), + // Note: vanilla node REPL does not set exports + exportsTest: true, + // Note: vanilla node uses different name. See #1360 + stackTest: exp.stringContaining( + ` at ${join(ROOT_DIR, '.ts')}:1:` + ), + moduleAccessorsTest: true, + }, + }); + // Prior to these, nyc adds another entry on Windows; we need to ignore it + exp( + globalInRepl.testReport.replReport.modulePaths.slice(-3) + ).toMatchObject([ + join(homedir(), `.node_modules`), + join(homedir(), `.node_libraries`), + // additional entry goes to node's install path + exp.any(String), + ]); + } + ); + } + ); + test('should support require flags', async () => { const { err, stdout } = await exec( `${cmd} -r ./hello-world -pe "console.log('success')"` diff --git a/src/util.ts b/src/util.ts index 63ed6a67e..9ea98a66d 100644 --- a/src/util.ts +++ b/src/util.ts @@ -64,6 +64,14 @@ export function normalizeSlashes(value: string): string { return value.replace(backslashRegExp, directorySeparator); } +/** + * Safe `hasOwnProperty` + * @internal + */ +export function hasOwnProperty(object: any, property: string): boolean { + return Object.prototype.hasOwnProperty.call(object, property); +} + /** * Cached fs operation wrapper. */ diff --git a/tests/repl/script.js b/tests/repl/script.js new file mode 100644 index 000000000..468972685 --- /dev/null +++ b/tests/repl/script.js @@ -0,0 +1,7 @@ +console.log( + JSON.stringify({ + stdinReport: typeof stdinReport !== 'undefined' && stdinReport, + evalReport: typeof evalReport !== 'undefined' && evalReport, + replReport: typeof replReport !== 'undefined' && replReport, + }) +);