mirror of
https://github.com/denoland/deno.git
synced 2024-11-29 16:30:56 -05:00
forbidden to set this
for setTimeout (#2511)
This commit is contained in:
parent
bca5cc5041
commit
42d1024cd9
2 changed files with 64 additions and 0 deletions
10
js/timers.ts
10
js/timers.ts
|
@ -181,6 +181,12 @@ function fireTimers(): void {
|
||||||
|
|
||||||
export type Args = unknown[];
|
export type Args = unknown[];
|
||||||
|
|
||||||
|
function checkThis(thisArg: unknown): void {
|
||||||
|
if (thisArg !== null && thisArg !== undefined && thisArg !== window) {
|
||||||
|
throw new TypeError("Illegal invocation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function setTimer(
|
function setTimer(
|
||||||
cb: (...args: Args) => void,
|
cb: (...args: Args) => void,
|
||||||
delay: number,
|
delay: number,
|
||||||
|
@ -226,6 +232,8 @@ export function setTimeout(
|
||||||
delay: number,
|
delay: number,
|
||||||
...args: Args
|
...args: Args
|
||||||
): number {
|
): number {
|
||||||
|
// @ts-ignore
|
||||||
|
checkThis(this);
|
||||||
return setTimer(cb, delay, args, false);
|
return setTimer(cb, delay, args, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,6 +243,8 @@ export function setInterval(
|
||||||
delay: number,
|
delay: number,
|
||||||
...args: Args
|
...args: Args
|
||||||
): number {
|
): number {
|
||||||
|
// @ts-ignore
|
||||||
|
checkThis(this);
|
||||||
return setTimer(cb, delay, args, true);
|
return setTimer(cb, delay, args, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -177,3 +177,57 @@ test(async function timeoutCallbackThis(): Promise<void> {
|
||||||
setTimeout(obj.foo, 1);
|
setTimeout(obj.foo, 1);
|
||||||
await promise;
|
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);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in a new issue