diff --git a/packages/npm/date/Date.parse/shim.js b/packages/npm/date/Date.parse/shim.js index 0e79d3f7..d89acf0f 100644 --- a/packages/npm/date/Date.parse/shim.js +++ b/packages/npm/date/Date.parse/shim.js @@ -6,7 +6,7 @@ const { defineProperty: ObjectDefineProperty } = Object module.exports = function shimDateParse() { const polyfill = getPolyfill() - if (polyfill && Date.parse !== polyfill) { + if (Date.parse !== polyfill) { ObjectDefineProperty(Date, 'parse', { __proto__: null, configurable: true, diff --git a/packages/npm/es-iterator-helpers/Iterator.prototype.drop/index.js b/packages/npm/es-iterator-helpers/Iterator.prototype.drop/index.js index 387e6478..0b404192 100644 --- a/packages/npm/es-iterator-helpers/Iterator.prototype.drop/index.js +++ b/packages/npm/es-iterator-helpers/Iterator.prototype.drop/index.js @@ -1,6 +1,7 @@ 'use strict' -const impl = require('./implementation') +const getPolyfill = require('./polyfill') +const polyfill = getPolyfill() const desc = value => ({ __proto__: null, @@ -11,11 +12,11 @@ const desc = value => ({ module.exports = Object.defineProperties( function drop(thisArg, limit = 0) { - return new.target ? impl() : Reflect.apply(impl, thisArg, [limit]) + return new.target ? polyfill() : Reflect.apply(polyfill, thisArg, [limit]) }, { - getPolyfill: desc(require('./polyfill')), - implementation: desc(impl), + getPolyfill: desc(getPolyfill), + implementation: desc(require('./implementation')), shim: desc(require('./shim')) } ) diff --git a/packages/npm/es-iterator-helpers/Iterator.prototype.filter/index.js b/packages/npm/es-iterator-helpers/Iterator.prototype.filter/index.js index 74a17d8e..27bbad0d 100644 --- a/packages/npm/es-iterator-helpers/Iterator.prototype.filter/index.js +++ b/packages/npm/es-iterator-helpers/Iterator.prototype.filter/index.js @@ -1,6 +1,7 @@ 'use strict' -const impl = require('./implementation') +const getPolyfill = require('./polyfill') +const polyfill = getPolyfill() const desc = value => ({ __proto__: null, @@ -11,11 +12,13 @@ const desc = value => ({ module.exports = Object.defineProperties( function filter(thisArg, predicate) { - return new.target ? new impl() : Reflect.apply(impl, thisArg, [predicate]) + return new.target + ? new polyfill() + : Reflect.apply(polyfill, thisArg, [predicate]) }, { - getPolyfill: desc(require('./polyfill')), - implementation: desc(impl), + getPolyfill: desc(getPolyfill), + implementation: desc(require('./implementation')), shim: desc(require('./shim')) } ) diff --git a/packages/npm/es-iterator-helpers/Iterator.prototype.flatMap/index.js b/packages/npm/es-iterator-helpers/Iterator.prototype.flatMap/index.js index b18c32b0..cdb536bb 100644 --- a/packages/npm/es-iterator-helpers/Iterator.prototype.flatMap/index.js +++ b/packages/npm/es-iterator-helpers/Iterator.prototype.flatMap/index.js @@ -1,6 +1,7 @@ 'use strict' -const impl = require('./implementation') +const getPolyfill = require('./polyfill') +const polyfill = getPolyfill() const desc = value => ({ __proto__: null, @@ -11,11 +12,13 @@ const desc = value => ({ module.exports = Object.defineProperties( function flatMap(thisArg, mapper) { - return new.target ? new impl() : Reflect.apply(impl, thisArg, [mapper]) + return new.target + ? new polyfill() + : Reflect.apply(polyfill, thisArg, [mapper]) }, { - getPolyfill: desc(require('./polyfill')), - implementation: desc(impl), + getPolyfill: desc(getPolyfill), + implementation: desc(require('./implementation')), shim: desc(require('./shim')) } ) diff --git a/packages/npm/es-iterator-helpers/Iterator.prototype.map/index.js b/packages/npm/es-iterator-helpers/Iterator.prototype.map/index.js index c3a0d794..9f5d935a 100644 --- a/packages/npm/es-iterator-helpers/Iterator.prototype.map/index.js +++ b/packages/npm/es-iterator-helpers/Iterator.prototype.map/index.js @@ -1,6 +1,7 @@ 'use strict' -const impl = require('./implementation') +const getPolyfill = require('./polyfill') +const polyfill = getPolyfill() const desc = value => ({ __proto__: null, @@ -11,11 +12,13 @@ const desc = value => ({ module.exports = Object.defineProperties( function map(thisArg, mapper) { - return new.target ? new impl() : Reflect.apply(impl, thisArg, [mapper]) + return new.target + ? new polyfill() + : Reflect.apply(polyfill, thisArg, [mapper]) }, { - getPolyfill: desc(require('./polyfill')), - implementation: desc(impl), + getPolyfill: desc(getPolyfill), + implementation: desc(require('./implementation')), shim: desc(require('./shim')) } ) diff --git a/packages/npm/regexp.prototype.flags/auto.js b/packages/npm/regexp.prototype.flags/auto.js index 40a8c178..67d3d96d 100644 --- a/packages/npm/regexp.prototype.flags/auto.js +++ b/packages/npm/regexp.prototype.flags/auto.js @@ -1 +1,3 @@ -/* empty */ +'use strict' + +require('./shim')() diff --git a/packages/npm/regexp.prototype.flags/implementation.js b/packages/npm/regexp.prototype.flags/implementation.js index b46adf3e..ad1152da 100644 --- a/packages/npm/regexp.prototype.flags/implementation.js +++ b/packages/npm/regexp.prototype.flags/implementation.js @@ -1,3 +1,41 @@ 'use strict' -module.exports = RegExp.prototype.__lookupGetter__('flags') +const { flagsGetter } = require('./shared') + +module.exports = { + get flags() { + if (new.target || this === null || typeof this !== 'object') { + // Defer to builtin flags getter for the error case. + return flagsGetter.call(this) + } + // Flag check order defined as hasIndices, global, ignoreCase, multiline, + // dotAll, unicode, unicodeSets, and sticky. + // https://tc39.es/ecma262/#sec-get-regexp.prototype.flags + let result = '' + if (this.hasIndices) { + result += 'd' + } + if (this.global) { + result += 'g' + } + if (this.ignoreCase) { + result += 'i' + } + if (this.multiline) { + result += 'm' + } + if (this.dotAll) { + result += 's' + } + if (this.unicode) { + result += 'u' + } + if (this.unicodeSets) { + result += 'v' + } + if (this.sticky) { + result += 'y' + } + return result + } +}.__lookupGetter__('flags') diff --git a/packages/npm/regexp.prototype.flags/index.js b/packages/npm/regexp.prototype.flags/index.js index 6703a57b..d15d2a47 100644 --- a/packages/npm/regexp.prototype.flags/index.js +++ b/packages/npm/regexp.prototype.flags/index.js @@ -1,6 +1,7 @@ 'use strict' -const impl = require('./implementation') +const getPolyfill = require('./polyfill') +const polyfill = getPolyfill() const desc = value => ({ __proto__: null, @@ -11,11 +12,11 @@ const desc = value => ({ module.exports = Object.defineProperties( function flags(thisArg) { - return new.target ? new impl() : Reflect.apply(impl, thisArg, []) + return new.target ? new polyfill() : Reflect.apply(polyfill, thisArg, []) }, { - getPolyfill: desc(require('./polyfill')), - implementation: desc(impl), + getPolyfill: desc(getPolyfill), + implementation: desc(require('./implementation')), shim: desc(require('./shim')) } ) diff --git a/packages/npm/regexp.prototype.flags/polyfill.js b/packages/npm/regexp.prototype.flags/polyfill.js index ff68a60c..bd9fd025 100644 --- a/packages/npm/regexp.prototype.flags/polyfill.js +++ b/packages/npm/regexp.prototype.flags/polyfill.js @@ -1,7 +1,19 @@ 'use strict' const impl = require('./implementation') +const { flagsGetter } = require('./shared') module.exports = function getPolyfill() { - return impl + let calls = '' + flagsGetter.call({ + // eslint-disable-next-line getter-return + get hasIndices() { + calls += 'd' + }, + // eslint-disable-next-line getter-return + get sticky() { + calls += 'y' + } + }) + return calls === 'dy' ? flagsGetter : impl } diff --git a/packages/npm/regexp.prototype.flags/shared.d.ts b/packages/npm/regexp.prototype.flags/shared.d.ts new file mode 100644 index 00000000..45c28818 --- /dev/null +++ b/packages/npm/regexp.prototype.flags/shared.d.ts @@ -0,0 +1,5 @@ +declare interface InternalShared { + flagsGetter(): string +} +declare const shared: InternalShared +export = shared diff --git a/packages/npm/regexp.prototype.flags/shared.js b/packages/npm/regexp.prototype.flags/shared.js new file mode 100644 index 00000000..e3d2e350 --- /dev/null +++ b/packages/npm/regexp.prototype.flags/shared.js @@ -0,0 +1,7 @@ +'use strict' + +const flagsGetter = RegExp.prototype.__lookupGetter__('flags') + +module.exports = { + flagsGetter +} diff --git a/packages/npm/regexp.prototype.flags/shim.js b/packages/npm/regexp.prototype.flags/shim.js index c5061d1f..d7e4a37c 100644 --- a/packages/npm/regexp.prototype.flags/shim.js +++ b/packages/npm/regexp.prototype.flags/shim.js @@ -1,7 +1,20 @@ 'use strict' -const impl = require('./implementation') +const getPolyfill = require('./polyfill') + +const { defineProperty: ObjectDefineProperty } = Object +const { __lookupGetter__: ObjectProtoLookupGetter } = Object.prototype +const { prototype: RegExpPrototype } = RegExp module.exports = function shimRegExpProtoFlags() { - return impl + const polyfill = getPolyfill() + if (ObjectProtoLookupGetter.call(RegExpPrototype, 'flags') !== polyfill) { + ObjectDefineProperty(RegExpPrototype, 'flags', { + __proto__: null, + configurable: true, + enumerable: false, + get: polyfill + }) + } + return polyfill } diff --git a/scripts/constants.js b/scripts/constants.js index 5c959ad2..88fa7ae9 100644 --- a/scripts/constants.js +++ b/scripts/constants.js @@ -328,7 +328,7 @@ const lazyPrettierConfigPromise = () => prettier.resolveConfig(prettierConfigPath, { editorconfig: true }) const lazyPrettierIgnoreFile = () => includeIgnoreFile(prettierIgnorePath) const lazyRunScriptParallelExecPath = () => whichSync('run-p') -const lazyTapRunExecPath = () => whichSync('tap-run') +const lazyTapExecPath = () => whichSync('tap') const copyLeftLicenses = new Set([ 'AGPL-3.0-or-later', @@ -526,7 +526,7 @@ const constants = Object.freeze( rootTapConfigPath, rootTsConfigPath, runScriptParallelExecPath: undefined, - tapRunExecPath: undefined, + tapExecPath: undefined, templatesPath, testNpmPath, testNpmPkgJsonPath, @@ -551,7 +551,7 @@ const constants = Object.freeze( npmPackageNames: lazyNpmPackageNames, prettierConfigPromise: lazyPrettierConfigPromise, prettierIgnoreFile: lazyPrettierIgnoreFile, - tapRunExecPath: lazyTapRunExecPath, + tapExecPath: lazyTapExecPath, runScriptParallelExecPath: lazyRunScriptParallelExecPath } ) diff --git a/scripts/make-npm-package.js b/scripts/make-npm-package.js index 161b91ad..11952ff4 100644 --- a/scripts/make-npm-package.js +++ b/scripts/make-npm-package.js @@ -425,7 +425,6 @@ function toChoice(value) { ], { cwd: rootPath, - shell: true, stdio: 'inherit' } ) diff --git a/scripts/tap.js b/scripts/tap.js index 3b52504d..dfb66171 100644 --- a/scripts/tap.js +++ b/scripts/tap.js @@ -6,12 +6,11 @@ const { runBin } = require('@socketregistry/scripts/utils/npm') ;(async () => { await runBin( - // Lazily access constants.tapRunExecPath. - constants.tapRunExecPath, + // Lazily access constants.tapExecPath. + constants.tapExecPath, process.argv.slice(2), { cwd: rootPath, - shell: true, stdio: 'inherit', env: { __proto__: null, diff --git a/scripts/utils/npm.js b/scripts/utils/npm.js index 9bdde1d6..aef46fa6 100644 --- a/scripts/utils/npm.js +++ b/scripts/utils/npm.js @@ -25,7 +25,11 @@ async function runBin(binPath, args, options) { return await spawn( WIN_32 ? binPath : execPath, [...(WIN_32 ? [] : [binPath]), ...args], - options + { + __proto__: null, + ...options, + shell: true, + } ) } diff --git a/test/packages.test.ts b/test/packages.test.ts index 9fabf6a3..fac3d234 100644 --- a/test/packages.test.ts +++ b/test/packages.test.ts @@ -1,3 +1,4 @@ +import assertLoose from 'node:assert' import assert from 'node:assert/strict' import { createRequire } from 'node:module' import path from 'node:path' @@ -314,12 +315,17 @@ for (const eco of constants.ecosystems) { assert.ok(shimApiKeys.every(k => mainKeys.includes(k))) }) - it('getPolyfill() === implementation', async t => { + it('getPolyfill() is like implementation', async t => { if (skipping) return t.skip(skipMessage) - assert.strictEqual( - req('./polyfill.js')(), - req('./implementation.js') - ) + const impl = req('./implementation.js') + const polyfill = req('./polyfill.js')() + assert.strictEqual(typeof impl, typeof polyfill) + if (typeof impl === 'function') { + assert.strictEqual(impl.name, polyfill.name) + assert.strictEqual(impl.length, polyfill.length) + } else { + assertLoose.equal(impl, polyfill) + } }) }) }