diff --git a/build/build.mjs b/build/build.mjs index feaff82f8..cdb124cdd 100644 --- a/build/build.mjs +++ b/build/build.mjs @@ -196,6 +196,7 @@ async function main() { contents.push(['lib/ours/primordials.js', await readFile('src/primordials.js', 'utf-8')]) contents.push(['lib/ours/util.js', await readFile('src/util.js', 'utf-8')]) contents.push(['lib/ours/util/inspect.js', await readFile('src/util/inspect.js', 'utf-8')]) + contents.push(['lib/internal/shims/process.js', await readFile('src/internal/shims/process.js', 'utf-8')]) for (const file of await readdir('src/test/ours')) { contents.push([`test/ours/${file}`, await readFile(`src/test/ours/${file}`, 'utf-8')]) diff --git a/build/headers.mjs b/build/headers.mjs index 9f056aea0..cad6b4f63 100644 --- a/build/headers.mjs +++ b/build/headers.mjs @@ -9,7 +9,7 @@ const bufferRequire = ` const processRequire = ` /* replacement start */ - const process = require('process/') + const process = require('../shims/process') /* replacement end */ ` diff --git a/lib/internal/shims/process.js b/lib/internal/shims/process.js new file mode 100644 index 000000000..cdc2a0786 --- /dev/null +++ b/lib/internal/shims/process.js @@ -0,0 +1,19 @@ +'use strict' + +/* wraps the internal process module, circumventing issues with some polyfills (see #539) */ +const process = ((base, esmKey, keys, isValid) => { + if (esmKey in base && base[esmKey] === true) { + let candidate + for (const key of keys) { + if (!(key in base)) { + continue + } + candidate = base[key] + if (isValid(candidate)) { + return candidate + } + } + } + return base +})(require('process/'), '__esModule', ['default', 'process'], (candidate) => 'nextTick' in candidate) +module.exports = process diff --git a/lib/internal/streams/destroy.js b/lib/internal/streams/destroy.js index 38292315e..fe9651841 100644 --- a/lib/internal/streams/destroy.js +++ b/lib/internal/streams/destroy.js @@ -2,7 +2,7 @@ /* replacement start */ -const process = require('process/') +const process = require('../shims/process') /* replacement end */ diff --git a/lib/internal/streams/duplexify.js b/lib/internal/streams/duplexify.js index 05740d70f..bb1e251a0 100644 --- a/lib/internal/streams/duplexify.js +++ b/lib/internal/streams/duplexify.js @@ -1,6 +1,6 @@ /* replacement start */ -const process = require('process/') +const process = require('../shims/process') /* replacement end */ diff --git a/lib/internal/streams/end-of-stream.js b/lib/internal/streams/end-of-stream.js index 94d18321d..35a4926f2 100644 --- a/lib/internal/streams/end-of-stream.js +++ b/lib/internal/streams/end-of-stream.js @@ -5,7 +5,7 @@ /* replacement start */ -const process = require('process/') +const process = require('../shims/process') /* replacement end */ diff --git a/lib/internal/streams/from.js b/lib/internal/streams/from.js index c7e753140..5cd814260 100644 --- a/lib/internal/streams/from.js +++ b/lib/internal/streams/from.js @@ -2,7 +2,7 @@ /* replacement start */ -const process = require('process/') +const process = require('../shims/process') /* replacement end */ diff --git a/lib/internal/streams/pipeline.js b/lib/internal/streams/pipeline.js index a2bab8800..cafe9aad3 100644 --- a/lib/internal/streams/pipeline.js +++ b/lib/internal/streams/pipeline.js @@ -1,6 +1,6 @@ /* replacement start */ -const process = require('process/') +const process = require('../shims/process') /* replacement end */ // Ported from https://github.com/mafintosh/pump with diff --git a/lib/internal/streams/readable.js b/lib/internal/streams/readable.js index 90c731605..9c7b15d06 100644 --- a/lib/internal/streams/readable.js +++ b/lib/internal/streams/readable.js @@ -23,7 +23,7 @@ /* replacement start */ -const process = require('process/') +const process = require('../shims/process') /* replacement end */ diff --git a/lib/internal/streams/writable.js b/lib/internal/streams/writable.js index b4ecf0e21..f80e8c55c 100644 --- a/lib/internal/streams/writable.js +++ b/lib/internal/streams/writable.js @@ -27,7 +27,7 @@ /* replacement start */ -const process = require('process/') +const process = require('../shims/process') /* replacement end */ diff --git a/src/internal/shims/process.js b/src/internal/shims/process.js new file mode 100644 index 000000000..cfee4ae29 --- /dev/null +++ b/src/internal/shims/process.js @@ -0,0 +1,21 @@ +'use strict' + +/* wraps the internal process module, circumventing issues with some polyfills (see #539) */ + +const process = ((base, esmKey, keys, isValid) => { + if (esmKey in base && base[esmKey] === true) { + let candidate + for (const key of keys) { + if (!(key in base)) { + continue + } + candidate = base[key] + if (isValid(candidate)) { + return candidate + } + } + } + return base +})(require('process/'), '__esModule', ['default', 'process'], (candidate) => 'nextTick' in candidate) + +module.exports = process diff --git a/src/test/ours/test-process-shim.js b/src/test/ours/test-process-shim.js new file mode 100644 index 000000000..8dc3e6304 --- /dev/null +++ b/src/test/ours/test-process-shim.js @@ -0,0 +1,54 @@ +'use strict' + +const t = require('tap') +const shimPath = '../../lib/internal/shims/process' + +t.test('unwraps an ES module default export containing the process object', (t) => { + const processLike = { nextTick() {} } + const wrappedProcess = { __esModule: true, default: processLike } + + const shimmedProcess = t.mock(shimPath, { + 'process/': wrappedProcess + }) + + t.equal(shimmedProcess, processLike) + t.equal(typeof shimmedProcess.nextTick, 'function') + t.end() +}) + +t.test('unwraps an ES module process export when default is not process-like', (t) => { + const processLike = { nextTick() {} } + const wrappedProcess = { __esModule: true, default: {}, process: processLike } + + const shimmedProcess = t.mock(shimPath, { + 'process/': wrappedProcess + }) + + t.equal(shimmedProcess, processLike) + t.equal(typeof shimmedProcess.nextTick, 'function') + t.end() +}) + +t.test('returns a plain process-like object unchanged', (t) => { + const processLike = { nextTick() {} } + + const shimmedProcess = t.mock(shimPath, { + 'process/': processLike + }) + + t.equal(shimmedProcess, processLike) + t.equal(typeof shimmedProcess.nextTick, 'function') + t.end() +}) + +t.test('returns an ES module wrapper unchanged when no candidate is process-like', (t) => { + const wrappedProcess = { __esModule: true, default: {}, process: {} } + + const shimmedProcess = t.mock(shimPath, { + 'process/': wrappedProcess + }) + + t.equal(shimmedProcess, wrappedProcess) + t.notOk('nextTick' in shimmedProcess) + t.end() +}) diff --git a/test/ours/test-process-shim.js b/test/ours/test-process-shim.js new file mode 100644 index 000000000..32c30aec5 --- /dev/null +++ b/test/ours/test-process-shim.js @@ -0,0 +1,59 @@ +'use strict' + +const t = require('tap') +const shimPath = '../../lib/internal/shims/process' +t.test('unwraps an ES module default export containing the process object', (t) => { + const processLike = { + nextTick() {} + } + const wrappedProcess = { + __esModule: true, + default: processLike + } + const shimmedProcess = t.mock(shimPath, { + 'process/': wrappedProcess + }) + t.equal(shimmedProcess, processLike) + t.equal(typeof shimmedProcess.nextTick, 'function') + t.end() +}) +t.test('unwraps an ES module process export when default is not process-like', (t) => { + const processLike = { + nextTick() {} + } + const wrappedProcess = { + __esModule: true, + default: {}, + process: processLike + } + const shimmedProcess = t.mock(shimPath, { + 'process/': wrappedProcess + }) + t.equal(shimmedProcess, processLike) + t.equal(typeof shimmedProcess.nextTick, 'function') + t.end() +}) +t.test('returns a plain process-like object unchanged', (t) => { + const processLike = { + nextTick() {} + } + const shimmedProcess = t.mock(shimPath, { + 'process/': processLike + }) + t.equal(shimmedProcess, processLike) + t.equal(typeof shimmedProcess.nextTick, 'function') + t.end() +}) +t.test('returns an ES module wrapper unchanged when no candidate is process-like', (t) => { + const wrappedProcess = { + __esModule: true, + default: {}, + process: {} + } + const shimmedProcess = t.mock(shimPath, { + 'process/': wrappedProcess + }) + t.equal(shimmedProcess, wrappedProcess) + t.notOk('nextTick' in shimmedProcess) + t.end() +})