1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-25 15:29:32 -05:00

forbidden to set this for setTimeout (#2511)

This commit is contained in:
迷渡 2019-06-13 23:08:27 +08:00 committed by Ryan Dahl
parent bca5cc5041
commit 42d1024cd9
2 changed files with 64 additions and 0 deletions

View file

@ -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);
}

View file

@ -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);
}
);
});