diff --git a/src/index.js b/src/index.js index ae3f137..1de16f2 100644 --- a/src/index.js +++ b/src/index.js @@ -19,13 +19,14 @@ const [nodeMajor] = process.version.slice(1).split('.').map(Number) const PERMISSION_FLAG = nodeMajor >= 24 ? '--permission' : '--experimental-permission' -const flags = ({ memory }) => { +const flags = ({ memory, allow }) => { const flags = ['--disable-warning=ExperimentalWarning', PERMISSION_FLAG] if (memory) flags.push(`--max-old-space-size=${memory}`) + allow.forEach(resource => flags.push(`--allow-${resource}`)) return flags.join(' ') } -module.exports = (snippet, { tmpdir, timeout, memory, throwError = true } = {}) => { +module.exports = (snippet, { tmpdir, timeout, memory, throwError = true, allow = [] } = {}) => { if (!['function', 'string'].includes(typeof snippet)) throw new TypeError('Expected a function') const compilePromise = compile(snippet, tmpdir) @@ -38,7 +39,7 @@ module.exports = (snippet, { tmpdir, timeout, memory, throwError = true } = {}) const subprocess = $('node', ['-', JSON.stringify(args)], { env: { ...process.env, - NODE_OPTIONS: flags({ memory }) + NODE_OPTIONS: flags({ memory, allow }) }, timeout, killSignal: 'SIGKILL' diff --git a/test/allow.js b/test/allow.js new file mode 100644 index 0000000..6ab564f --- /dev/null +++ b/test/allow.js @@ -0,0 +1,62 @@ +'use strict' + +const test = require('ava') + +const isolatedFunction = require('..') + +const [nodeMajor] = process.version.slice(1).split('.').map(Number) + +test('child-process', async t => { + const [fn, cleanup] = isolatedFunction( + () => { + const { execSync } = require('child_process') + return execSync('echo hello').toString() + }, + { + allow: ['child_process'] + } + ) + + t.teardown(cleanup) + + const { value } = await fn() + t.is(value, 'hello\n') +}) +;(nodeMajor >= 25 ? test : test.skip)('network', async t => { + const [fn, cleanup] = isolatedFunction( + async () => { + function doFetch (url) { + return new Promise((resolve, reject) => { + const req = require('node:http').get(url, res => { + let data = '' + + res.on('data', chunk => { + data += chunk + }) + + res.on('end', () => { + resolve({ + statusCode: res.statusCode, + headers: res.headers, + body: data + }) + }) + }) + + req.on('error', reject) + }) + } + + const { statusCode } = await doFetch('http://example.com') + return statusCode + }, + { + allow: ['net'] + } + ) + + t.teardown(cleanup) + + const { value } = await fn() + t.is(value, 200) +})