Skip to content

Commit 05c4089

Browse files
authored
Disallow sync createConfigItem,loadPartialConfig,loadOptions (#15869)
1 parent 866ea43 commit 05c4089

File tree

8 files changed

+320
-168
lines changed

8 files changed

+320
-168
lines changed

eslint/babel-eslint-parser/src/worker/babel-core.cjs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@ function initialize(babel) {
77
exports.parseSync = babel.parseSync;
88
exports.loadPartialConfigSync = babel.loadPartialConfigSync;
99
exports.loadPartialConfigAsync = babel.loadPartialConfigAsync;
10-
exports.createConfigItem = babel.createConfigItem;
10+
if (process.env.BABEL_8_BREAKING) {
11+
exports.createConfigItemSync = babel.createConfigItemSync;
12+
} else {
13+
// babel.createConfigItemSync is available on 7.13+
14+
// we support Babel 7.11+
15+
exports.createConfigItemSync =
16+
babel.createConfigItemSync || babel.createConfigItem;
17+
}
1118
}
1219

1320
if (USE_ESM) {

eslint/babel-eslint-parser/src/worker/maybeParse.cjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const MULTIPLE_OVERRIDES = /More than one plugin attempted to override parsing/;
1010

1111
module.exports = function maybeParse(code, options) {
1212
if (!extractParserOptionsConfigItem) {
13-
extractParserOptionsConfigItem = babel.createConfigItem(
13+
extractParserOptionsConfigItem = babel.createConfigItemSync(
1414
[extractParserOptionsPlugin, ref],
1515
{ dirname: __dirname, type: "plugin" },
1616
);
Lines changed: 100 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import gensync, { type Handler, type Callback } from "gensync";
1+
import gensync, { type Handler } from "gensync";
22

33
export type {
44
ResolvedConfig,
@@ -24,62 +24,125 @@ export type {
2424
} from "./validation/options";
2525

2626
import loadFullConfig, { type ResolvedConfig } from "./full";
27-
import { loadPartialConfig as loadPartialConfigRunner } from "./partial";
27+
import {
28+
type PartialConfig,
29+
loadPartialConfig as loadPartialConfigImpl,
30+
} from "./partial";
2831

2932
export { loadFullConfig as default };
3033
export type { PartialConfig } from "./partial";
3134

3235
import { createConfigItem as createConfigItemImpl } from "./item";
3336
import type { ConfigItem } from "./item";
3437

35-
const loadOptionsRunner = gensync(function* (
36-
opts: unknown,
37-
): Handler<ResolvedConfig | null> {
38+
import { beginHiddenCallStack } from "../errors/rewrite-stack-trace";
39+
40+
const loadPartialConfigRunner = gensync(loadPartialConfigImpl);
41+
export function loadPartialConfigAsync(
42+
...args: Parameters<typeof loadPartialConfigRunner.async>
43+
) {
44+
return beginHiddenCallStack(loadPartialConfigRunner.async)(...args);
45+
}
46+
export function loadPartialConfigSync(
47+
...args: Parameters<typeof loadPartialConfigRunner.sync>
48+
) {
49+
return beginHiddenCallStack(loadPartialConfigRunner.sync)(...args);
50+
}
51+
export function loadPartialConfig(
52+
opts: Parameters<typeof loadPartialConfigImpl>[0],
53+
callback?: (err: Error, val: PartialConfig | null) => void,
54+
) {
55+
if (callback !== undefined) {
56+
beginHiddenCallStack(loadPartialConfigRunner.errback)(opts, callback);
57+
} else if (typeof opts === "function") {
58+
beginHiddenCallStack(loadPartialConfigRunner.errback)(
59+
undefined,
60+
opts as (err: Error, val: PartialConfig | null) => void,
61+
);
62+
} else {
63+
if (process.env.BABEL_8_BREAKING) {
64+
throw new Error(
65+
"Starting from Babel 8.0.0, the 'loadPartialConfig' function expects a callback. If you need to call it synchronously, please use 'loadPartialConfigSync'.",
66+
);
67+
} else {
68+
return loadPartialConfigSync(opts);
69+
}
70+
}
71+
}
72+
73+
function* loadOptionsImpl(opts: unknown): Handler<ResolvedConfig | null> {
3874
const config = yield* loadFullConfig(opts);
3975
// NOTE: We want to return "null" explicitly, while ?. alone returns undefined
4076
return config?.options ?? null;
41-
});
42-
43-
const createConfigItemRunner = gensync(createConfigItemImpl);
44-
45-
const maybeErrback =
46-
<Arg, Return>(runner: gensync.Gensync<[Arg], Return>) =>
47-
(argOrCallback: Arg | Callback<Return>, maybeCallback?: Callback<Return>) => {
48-
let arg: Arg | undefined;
49-
let callback: Callback<Return>;
50-
if (maybeCallback === undefined && typeof argOrCallback === "function") {
51-
callback = argOrCallback as Callback<Return>;
52-
arg = undefined;
77+
}
78+
const loadOptionsRunner = gensync(loadOptionsImpl);
79+
export function loadOptionsAsync(
80+
...args: Parameters<typeof loadOptionsRunner.async>
81+
) {
82+
return beginHiddenCallStack(loadOptionsRunner.async)(...args);
83+
}
84+
export function loadOptionsSync(
85+
...args: Parameters<typeof loadOptionsRunner.sync>
86+
) {
87+
return beginHiddenCallStack(loadOptionsRunner.sync)(...args);
88+
}
89+
export function loadOptions(
90+
opts: Parameters<typeof loadOptionsImpl>[0],
91+
callback?: (err: Error, val: ResolvedConfig | null) => void,
92+
) {
93+
if (callback !== undefined) {
94+
beginHiddenCallStack(loadOptionsRunner.errback)(opts, callback);
95+
} else if (typeof opts === "function") {
96+
beginHiddenCallStack(loadOptionsRunner.errback)(
97+
undefined,
98+
opts as (err: Error, val: ResolvedConfig | null) => void,
99+
);
100+
} else {
101+
if (process.env.BABEL_8_BREAKING) {
102+
throw new Error(
103+
"Starting from Babel 8.0.0, the 'loadOptions' function expects a callback. If you need to call it synchronously, please use 'loadOptionsSync'.",
104+
);
53105
} else {
54-
callback = maybeCallback;
55-
arg = argOrCallback as Arg;
56-
}
57-
if (!callback) {
58-
return runner.sync(arg);
106+
return loadOptionsSync(opts);
59107
}
60-
runner.errback(arg, callback);
61-
};
62-
63-
export const loadPartialConfig = maybeErrback(loadPartialConfigRunner);
64-
export const loadPartialConfigSync = loadPartialConfigRunner.sync;
65-
export const loadPartialConfigAsync = loadPartialConfigRunner.async;
66-
67-
export const loadOptions = maybeErrback(loadOptionsRunner);
68-
export const loadOptionsSync = loadOptionsRunner.sync;
69-
export const loadOptionsAsync = loadOptionsRunner.async;
108+
}
109+
}
70110

71-
export const createConfigItemSync = createConfigItemRunner.sync;
72-
export const createConfigItemAsync = createConfigItemRunner.async;
111+
const createConfigItemRunner = gensync(createConfigItemImpl);
112+
export function createConfigItemAsync(
113+
...args: Parameters<typeof createConfigItemRunner.async>
114+
) {
115+
return beginHiddenCallStack(createConfigItemRunner.async)(...args);
116+
}
117+
export function createConfigItemSync(
118+
...args: Parameters<typeof createConfigItemRunner.sync>
119+
) {
120+
return beginHiddenCallStack(createConfigItemRunner.sync)(...args);
121+
}
73122
export function createConfigItem(
74123
target: PluginTarget,
75124
options: Parameters<typeof createConfigItemImpl>[1],
76125
callback?: (err: Error, val: ConfigItem<PluginAPI> | null) => void,
77126
) {
78127
if (callback !== undefined) {
79-
createConfigItemRunner.errback(target, options, callback);
128+
beginHiddenCallStack(createConfigItemRunner.errback)(
129+
target,
130+
options,
131+
callback,
132+
);
80133
} else if (typeof options === "function") {
81-
createConfigItemRunner.errback(target, undefined, callback);
134+
beginHiddenCallStack(createConfigItemRunner.errback)(
135+
target,
136+
undefined,
137+
callback,
138+
);
82139
} else {
83-
return createConfigItemRunner.sync(target, options);
140+
if (process.env.BABEL_8_BREAKING) {
141+
throw new Error(
142+
"Starting from Babel 8.0.0, the 'createConfigItem' function expects a callback. If you need to call it synchronously, please use 'createConfigItemSync'.",
143+
);
144+
} else {
145+
return createConfigItemSync(target, options);
146+
}
84147
}
85148
}

packages/babel-core/src/config/partial.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import path from "path";
2-
import gensync from "gensync";
32
import type { Handler } from "gensync";
43
import Plugin from "./plugin";
54
import { mergeOptions } from "./util";
@@ -159,7 +158,7 @@ type LoadPartialConfigOpts = {
159158
showIgnoredFiles?: boolean;
160159
};
161160

162-
export const loadPartialConfig = gensync(function* (
161+
export function* loadPartialConfig(
163162
opts?: LoadPartialConfigOpts,
164163
): Handler<PartialConfig | null> {
165164
let showIgnoredFiles = false;
@@ -197,7 +196,7 @@ export const loadPartialConfig = gensync(function* (
197196
fileHandling,
198197
files,
199198
);
200-
});
199+
}
201200

202201
export type { PartialConfig };
203202

packages/babel-core/test/assumptions.js

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
import path from "path";
22
import { fileURLToPath } from "url";
3-
import { loadOptions as loadOptionsOrig, transformSync } from "../lib/index.js";
3+
import {
4+
loadOptionsSync as loadOptionsSyncOrig,
5+
transformSync,
6+
} from "../lib/index.js";
47
import pluginCommonJS from "@babel/plugin-transform-modules-commonjs";
58

69
const cwd = path.dirname(fileURLToPath(import.meta.url));
710

8-
function loadOptions(opts) {
9-
return loadOptionsOrig({ cwd, ...opts });
11+
function loadOptionsSync(opts) {
12+
return loadOptionsSyncOrig({ cwd, ...opts });
1013
}
1114

1215
function withAssumptions(assumptions) {
13-
return loadOptions({ assumptions });
16+
return loadOptionsSync({ assumptions });
1417
}
1518

1619
describe("assumptions", () => {
@@ -35,7 +38,7 @@ describe("assumptions", () => {
3538

3639
it("can be enabled by presets", () => {
3740
expect(
38-
loadOptions({
41+
loadOptionsSync({
3942
assumptions: {
4043
setPublicClassFields: true,
4144
},
@@ -49,7 +52,7 @@ describe("assumptions", () => {
4952

5053
it("cannot be disabled by presets", () => {
5154
expect(() =>
52-
loadOptions({
55+
loadOptionsSync({
5356
presets: [() => ({ assumptions: { mutableTemplateObject: false } })],
5457
}),
5558
).toThrow(
@@ -116,7 +119,7 @@ describe("assumptions", () => {
116119
it("plugin defined outside preset", () => {
117120
const ref = {};
118121

119-
loadOptions({
122+
loadOptionsSync({
120123
configFile: false,
121124
presets: [presetEnumerableModuleMeta],
122125
plugins: [[pluginExtractEnumerableModuleMeta, ref]],
@@ -128,7 +131,7 @@ describe("assumptions", () => {
128131
it("plugin defined inside preset", () => {
129132
const ref = {};
130133

131-
loadOptions({
134+
loadOptionsSync({
132135
configFile: false,
133136
presets: [
134137
() => ({

0 commit comments

Comments
 (0)