mirror of
https://github.com/denoland/deno.git
synced 2025-01-03 12:58:54 -05:00
refactor(core): validate promise id in refOp (#13905)
This commit is contained in:
parent
f9b4d262b3
commit
b198bfd795
5 changed files with 59 additions and 20 deletions
10
cli/tests/unit/ref_unref_test.ts
Normal file
10
cli/tests/unit/ref_unref_test.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { assertNotEquals, execCode } from "./test_util.ts";
|
||||||
|
|
||||||
|
Deno.test("[unrefOp] unref'ing invalid ops does not have effects", async () => {
|
||||||
|
const [statusCode, _] = await execCode(`
|
||||||
|
Deno.core.unrefOp(-1);
|
||||||
|
setTimeout(() => { throw new Error() }, 10)
|
||||||
|
`);
|
||||||
|
// Invalid unrefOp call doesn't affect exit condition of event loop
|
||||||
|
assertNotEquals(statusCode, 0);
|
||||||
|
});
|
|
@ -27,3 +27,21 @@ export function pathToAbsoluteFileUrl(path: string): URL {
|
||||||
|
|
||||||
return new URL(`file://${Deno.build.os === "windows" ? "/" : ""}${path}`);
|
return new URL(`file://${Deno.build.os === "windows" ? "/" : ""}${path}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const decoder = new TextDecoder();
|
||||||
|
|
||||||
|
export async function execCode(code: string) {
|
||||||
|
const p = Deno.run({
|
||||||
|
cmd: [
|
||||||
|
Deno.execPath(),
|
||||||
|
"eval",
|
||||||
|
"--unstable",
|
||||||
|
"--no-check",
|
||||||
|
code,
|
||||||
|
],
|
||||||
|
stdout: "piped",
|
||||||
|
});
|
||||||
|
const [status, output] = await Promise.all([p.status(), p.output()]);
|
||||||
|
p.close();
|
||||||
|
return [status.code, decoder.decode(output)];
|
||||||
|
}
|
||||||
|
|
|
@ -6,11 +6,10 @@ import {
|
||||||
Deferred,
|
Deferred,
|
||||||
deferred,
|
deferred,
|
||||||
delay,
|
delay,
|
||||||
|
execCode,
|
||||||
unreachable,
|
unreachable,
|
||||||
} from "./test_util.ts";
|
} from "./test_util.ts";
|
||||||
|
|
||||||
const decoder = new TextDecoder();
|
|
||||||
|
|
||||||
Deno.test(async function functionParameterBindingSuccess() {
|
Deno.test(async function functionParameterBindingSuccess() {
|
||||||
const promise = deferred();
|
const promise = deferred();
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
@ -578,21 +577,6 @@ Deno.test(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
async function execCode(code: string) {
|
|
||||||
const p = Deno.run({
|
|
||||||
cmd: [
|
|
||||||
Deno.execPath(),
|
|
||||||
"eval",
|
|
||||||
"--unstable",
|
|
||||||
code,
|
|
||||||
],
|
|
||||||
stdout: "piped",
|
|
||||||
});
|
|
||||||
const [status, output] = await Promise.all([p.status(), p.output()]);
|
|
||||||
p.close();
|
|
||||||
return [status.code, decoder.decode(output)];
|
|
||||||
}
|
|
||||||
|
|
||||||
Deno.test({
|
Deno.test({
|
||||||
name: "unrefTimer",
|
name: "unrefTimer",
|
||||||
permissions: { run: true },
|
permissions: { run: true },
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
} = window.__bootstrap.primordials;
|
} = window.__bootstrap.primordials;
|
||||||
|
|
||||||
// Available on start due to bindings.
|
// Available on start due to bindings.
|
||||||
const { opcallSync, opcallAsync } = window.Deno.core;
|
const { opcallSync, opcallAsync, refOp_, unrefOp_ } = window.Deno.core;
|
||||||
|
|
||||||
let opsCache = {};
|
let opsCache = {};
|
||||||
const errorMap = {};
|
const errorMap = {};
|
||||||
|
@ -99,6 +99,17 @@
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hasPromise(promiseId) {
|
||||||
|
// Check if out of ring bounds, fallback to map
|
||||||
|
const outOfBounds = promiseId < nextPromiseId - RING_SIZE;
|
||||||
|
if (outOfBounds) {
|
||||||
|
return MapPrototypeHas(promiseMap, promiseId);
|
||||||
|
}
|
||||||
|
// Otherwise check it in ring
|
||||||
|
const idx = promiseId % RING_SIZE;
|
||||||
|
return promiseRing[idx] != NO_PROMISE;
|
||||||
|
}
|
||||||
|
|
||||||
function ops() {
|
function ops() {
|
||||||
return opsCache;
|
return opsCache;
|
||||||
}
|
}
|
||||||
|
@ -172,6 +183,20 @@
|
||||||
return unwrapOpResult(opcallSync(opsCache[opName], arg1, arg2));
|
return unwrapOpResult(opcallSync(opsCache[opName], arg1, arg2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function refOp(promiseId) {
|
||||||
|
if (!hasPromise(promiseId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
refOp_(promiseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function unrefOp(promiseId) {
|
||||||
|
if (!hasPromise(promiseId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unrefOp_(promiseId);
|
||||||
|
}
|
||||||
|
|
||||||
function resources() {
|
function resources() {
|
||||||
return ObjectFromEntries(opSync("op_resources"));
|
return ObjectFromEntries(opSync("op_resources"));
|
||||||
}
|
}
|
||||||
|
@ -252,6 +277,8 @@
|
||||||
enableOpCallTracing,
|
enableOpCallTracing,
|
||||||
isOpCallTracingEnabled,
|
isOpCallTracingEnabled,
|
||||||
opCallTraces,
|
opCallTraces,
|
||||||
|
refOp,
|
||||||
|
unrefOp,
|
||||||
});
|
});
|
||||||
|
|
||||||
ObjectAssign(globalThis.__bootstrap, { core });
|
ObjectAssign(globalThis.__bootstrap, { core });
|
||||||
|
|
|
@ -173,8 +173,8 @@ pub fn initialize_context<'s>(
|
||||||
// Bind functions to Deno.core.*
|
// Bind functions to Deno.core.*
|
||||||
set_func(scope, core_val, "opcallSync", opcall_sync);
|
set_func(scope, core_val, "opcallSync", opcall_sync);
|
||||||
set_func(scope, core_val, "opcallAsync", opcall_async);
|
set_func(scope, core_val, "opcallAsync", opcall_async);
|
||||||
set_func(scope, core_val, "refOp", ref_op);
|
set_func(scope, core_val, "refOp_", ref_op);
|
||||||
set_func(scope, core_val, "unrefOp", unref_op);
|
set_func(scope, core_val, "unrefOp_", unref_op);
|
||||||
set_func(
|
set_func(
|
||||||
scope,
|
scope,
|
||||||
core_val,
|
core_val,
|
||||||
|
|
Loading…
Reference in a new issue