提交 42d1024c 编写于 作者: 迷渡's avatar 迷渡 提交者: Ryan Dahl

forbidden to set `this` for setTimeout (#2511)

上级 bca5cc50
......@@ -181,6 +181,12 @@ function fireTimers(): void {
export type Args = unknown[];
function checkThis(thisArg: unknown): void {
if (thisArg !== null && thisArg !== undefined && thisArg !== window) {
throw new TypeError("Illegal invocation");
}
}
function setTimer(
cb: (...args: Args) => void,
delay: number,
......@@ -226,6 +232,8 @@ export function setTimeout(
delay: number,
...args: Args
): number {
// @ts-ignore
checkThis(this);
return setTimer(cb, delay, args, false);
}
......@@ -235,6 +243,8 @@ export function setInterval(
delay: number,
...args: Args
): number {
// @ts-ignore
checkThis(this);
return setTimer(cb, delay, args, true);
}
......
......@@ -177,3 +177,57 @@ test(async function timeoutCallbackThis(): Promise<void> {
setTimeout(obj.foo, 1);
await promise;
});
test(async function timeoutBindThis(): Promise<void> {
function noop(): void {}
const thisCheckPassed = [null, undefined, window, globalThis];
const thisCheckFailed = [
0,
"",
true,
false,
{},
[],
"foo",
(): void => {},
Object.prototype
];
thisCheckPassed.forEach(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(thisArg: any): void => {
let hasThrown = 0;
try {
setTimeout.call(thisArg, noop, 1);
hasThrown = 1;
} catch (err) {
if (err instanceof TypeError) {
hasThrown = 2;
} else {
hasThrown = 3;
}
}
assertEquals(hasThrown, 1);
}
);
thisCheckFailed.forEach(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(thisArg: any): void => {
let hasThrown = 0;
try {
setTimeout.call(thisArg, noop, 1);
hasThrown = 1;
} catch (err) {
if (err instanceof TypeError) {
hasThrown = 2;
} else {
hasThrown = 3;
}
}
assertEquals(hasThrown, 2);
}
);
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册