Skip to content

Commit d8e9cc5

Browse files
committed
fix(linter/plugins): validate type of before and after hooks (#14086)
Validate that `before` and `after` hooks are functions, and throw an error if they're not. Also throw an error if `createOnce` doesn't return an object.
1 parent b7fb7ba commit d8e9cc5

File tree

1 file changed

+23
-2
lines changed

1 file changed

+23
-2
lines changed

apps/oxlint/src-js/plugins/load.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,16 @@ async function loadPluginImpl(path: string): Promise<string> {
100100
let ruleAndContext;
101101
if ('createOnce' in rule) {
102102
// TODO: Compile visitor object to array here, instead of repeating compilation on each file
103-
const { before: beforeHook, after: afterHook, ...visitor } = rule.createOnce(context);
104-
ruleAndContext = { rule, context, visitor, beforeHook: beforeHook || null, afterHook: afterHook || null };
103+
let visitorWithHooks = rule.createOnce(context);
104+
if (typeof visitorWithHooks !== 'object' || visitorWithHooks === null) {
105+
throw new TypeError('`createOnce` must return an object');
106+
}
107+
108+
let { before: beforeHook, after: afterHook, ...visitor } = visitorWithHooks;
109+
beforeHook = conformHookFn(beforeHook, 'before');
110+
afterHook = conformHookFn(afterHook, 'after');
111+
112+
ruleAndContext = { rule, context, visitor, beforeHook, afterHook };
105113
} else {
106114
ruleAndContext = { rule, context, visitor: null, beforeHook: null, afterHook: null };
107115
}
@@ -111,3 +119,16 @@ async function loadPluginImpl(path: string): Promise<string> {
111119

112120
return JSON.stringify({ Success: { name: pluginName, offset, ruleNames } });
113121
}
122+
123+
/**
124+
* Validate and conform `before` / `after` hook function.
125+
* @param hookFn - Hook function, or `null` / `undefined`
126+
* @param hookName - Name of the hook
127+
* @returns Hook function, or null
128+
* @throws {TypeError} If `hookFn` is not a function, `null`, or `undefined`
129+
*/
130+
function conformHookFn<H>(hookFn: H | null | undefined, hookName: string): H | null {
131+
if (hookFn == null) return null;
132+
if (typeof hookFn !== 'function') throw new TypeError(`\`${hookName}\` hook must be a function if provided`);
133+
return hookFn;
134+
}

0 commit comments

Comments
 (0)