summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYoshiya Hinosawa <stibium121@gmail.com>2022-03-12 01:18:49 +0900
committerGitHub <noreply@github.com>2022-03-12 01:18:49 +0900
commitb198bfd7950ce3f20aeaef265be59ff038fc4e11 (patch)
tree4be0fc3266d6507504eb2fdf8164a12b182d4acb
parentf9b4d262b307649966b6433c72a9ee2b57bde8f7 (diff)
refactor(core): validate promise id in refOp (#13905)
-rw-r--r--cli/tests/unit/ref_unref_test.ts10
-rw-r--r--cli/tests/unit/test_util.ts18
-rw-r--r--cli/tests/unit/timers_test.ts18
-rw-r--r--core/01_core.js29
-rw-r--r--core/bindings.rs4
5 files changed, 59 insertions, 20 deletions
diff --git a/cli/tests/unit/ref_unref_test.ts b/cli/tests/unit/ref_unref_test.ts
new file mode 100644
index 000000000..da6e95efc
--- /dev/null
+++ b/cli/tests/unit/ref_unref_test.ts
@@ -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);
+});
diff --git a/cli/tests/unit/test_util.ts b/cli/tests/unit/test_util.ts
index 3591864d4..b18ad9550 100644
--- a/cli/tests/unit/test_util.ts
+++ b/cli/tests/unit/test_util.ts
@@ -27,3 +27,21 @@ export function pathToAbsoluteFileUrl(path: string): URL {
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)];
+}
diff --git a/cli/tests/unit/timers_test.ts b/cli/tests/unit/timers_test.ts
index e85a2effc..ac0403bf7 100644
--- a/cli/tests/unit/timers_test.ts
+++ b/cli/tests/unit/timers_test.ts
@@ -6,11 +6,10 @@ import {
Deferred,
deferred,
delay,
+ execCode,
unreachable,
} from "./test_util.ts";
-const decoder = new TextDecoder();
-
Deno.test(async function functionParameterBindingSuccess() {
const promise = deferred();
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({
name: "unrefTimer",
permissions: { run: true },
diff --git a/core/01_core.js b/core/01_core.js
index 50d4537f0..b6c72e5d2 100644
--- a/core/01_core.js
+++ b/core/01_core.js
@@ -29,7 +29,7 @@
} = window.__bootstrap.primordials;
// Available on start due to bindings.
- const { opcallSync, opcallAsync } = window.Deno.core;
+ const { opcallSync, opcallAsync, refOp_, unrefOp_ } = window.Deno.core;
let opsCache = {};
const errorMap = {};
@@ -99,6 +99,17 @@
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() {
return opsCache;
}
@@ -172,6 +183,20 @@
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() {
return ObjectFromEntries(opSync("op_resources"));
}
@@ -252,6 +277,8 @@
enableOpCallTracing,
isOpCallTracingEnabled,
opCallTraces,
+ refOp,
+ unrefOp,
});
ObjectAssign(globalThis.__bootstrap, { core });
diff --git a/core/bindings.rs b/core/bindings.rs
index 084d30a15..f84711abf 100644
--- a/core/bindings.rs
+++ b/core/bindings.rs
@@ -173,8 +173,8 @@ pub fn initialize_context<'s>(
// Bind functions to Deno.core.*
set_func(scope, core_val, "opcallSync", opcall_sync);
set_func(scope, core_val, "opcallAsync", opcall_async);
- set_func(scope, core_val, "refOp", ref_op);
- set_func(scope, core_val, "unrefOp", unref_op);
+ set_func(scope, core_val, "refOp_", ref_op);
+ set_func(scope, core_val, "unrefOp_", unref_op);
set_func(
scope,
core_val,