Skip to content

Commit dc3da89

Browse files
jdaltonSBoudrias
andauthored
Support Node's --frozen-intrinsics flag (#1683)
* Support Node's --frozen-intrinsics flag * Chore: Add integration test covering the callsite usage. --------- Co-authored-by: Simon Boudrias <admin@simonboudrias.com>
1 parent 3e04fe1 commit dc3da89

File tree

6 files changed

+32
-7
lines changed

6 files changed

+32
-7
lines changed

.github/workflows/main.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ jobs:
103103
- run: yarn install --immutable --immutable-cache
104104
- run: yarn tsc
105105
- name: Integration tests
106-
run: yarn node --test integration/
106+
run: yarn node --test integration/**/*.test.*
107107

108108
e2e:
109109
name: End to End build tests

integration/cjs/fixturePrompt.cjs

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
const { createPrompt } = require('@inquirer/core');
2+
3+
module.exports = createPrompt(function fixturePrompt() {});

integration/cjs/integration.test.cjs

+7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const { createPrompt } = require('@inquirer/core');
66
const defaultInput = require('@inquirer/input').default;
77
const inquirer = require('inquirer').default;
88
const { createPromptModule } = require('inquirer');
9+
const fixturePrompt = require('./fixturePrompt.cjs');
910

1011
describe('CommonJS Integration', () => {
1112
it('@inquirer/prompts should be exported', () => {
@@ -20,6 +21,12 @@ describe('CommonJS Integration', () => {
2021
assert(typeof createPrompt === 'function');
2122
});
2223

24+
it('works when prompt throws an error', async () => {
25+
await assert.rejects(() => fixturePrompt({}), {
26+
message: `Prompt functions must return a string.\n at ${require.resolve('./fixturePrompt.cjs')}`,
27+
});
28+
});
29+
2330
it('inquirer should be exported', () => {
2431
assert(typeof inquirer.prompt === 'function');
2532
assert(typeof inquirer.createPromptModule === 'function');

integration/esm/fixturePrompt.mjs

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { createPrompt } from '@inquirer/core';
2+
3+
export default createPrompt(function fixturePrompt() {});

integration/esm/integration.test.mjs

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
/* eslint-disable n/no-unsupported-features/node-builtins */
2+
import { createRequire } from 'node:module';
23
import { describe, it } from 'node:test';
3-
import assert from 'node:assert';
4+
import assert from 'node:assert/strict';
45
import { input } from '@inquirer/prompts';
56
import defaultInput from '@inquirer/input';
67
import { createPrompt } from '@inquirer/core';
78
import inquirer, { createPromptModule } from 'inquirer';
9+
import fixturePrompt from './fixturePrompt.mjs';
10+
11+
const require = createRequire(import.meta.url);
812

913
describe('ESM Integration', () => {
1014
it('@inquirer/prompts should be exported', () => {
@@ -19,6 +23,12 @@ describe('ESM Integration', () => {
1923
assert.ok(typeof createPrompt === 'function');
2024
});
2125

26+
it('works when prompt throws an error', async () => {
27+
await assert.rejects(() => fixturePrompt({}), {
28+
message: `Prompt functions must return a string.\n at file://${require.resolve('./fixturePrompt.mjs')}`,
29+
});
30+
});
31+
2232
it('inquirer should be exported', () => {
2333
assert.ok(typeof inquirer.prompt === 'function');
2434
assert.ok(typeof inquirer.createPromptModule === 'function');

packages/core/src/lib/create-prompt.ts

+7-5
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,26 @@ type ViewFunction<Value, Config> = (
1616

1717
function getCallSites() {
1818
const _prepareStackTrace = Error.prepareStackTrace;
19+
let result: NodeJS.CallSite[] = [];
1920
try {
20-
let result: NodeJS.CallSite[] = [];
2121
Error.prepareStackTrace = (_, callSites) => {
2222
const callSitesWithoutCurrent = callSites.slice(1);
2323
result = callSitesWithoutCurrent;
2424
return callSitesWithoutCurrent;
2525
};
26-
2726
// eslint-disable-next-line @typescript-eslint/no-unused-expressions, unicorn/error-message
2827
new Error().stack;
28+
} catch {
29+
// An error will occur if the Node flag --frozen-intrinsics is used.
30+
// https://nodejs.org/api/cli.html#--frozen-intrinsics
2931
return result;
30-
} finally {
31-
Error.prepareStackTrace = _prepareStackTrace;
3232
}
33+
Error.prepareStackTrace = _prepareStackTrace;
34+
return result;
3335
}
3436

3537
export function createPrompt<Value, Config>(view: ViewFunction<Value, Config>) {
3638
const callSites = getCallSites();
37-
const callerFilename = callSites[1]?.getFileName?.();
3839

3940
const prompt: Prompt<Value, Config> = (config, context = {}) => {
4041
// Default `input` to stdin
@@ -98,6 +99,7 @@ export function createPrompt<Value, Config>(view: ViewFunction<Value, Config>) {
9899
// Typescript won't allow this, but not all users rely on typescript.
99100
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
100101
if (nextView === undefined) {
102+
const callerFilename = callSites[1]?.getFileName?.();
101103
throw new Error(
102104
`Prompt functions must return a string.\n at ${callerFilename}`,
103105
);

0 commit comments

Comments
 (0)