summaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
authorsnek <snek@deno.com>2024-08-02 08:14:35 -0700
committerGitHub <noreply@github.com>2024-08-02 08:14:35 -0700
commit3a1a1cc030fb7fc90d51ee27162466d6ac924926 (patch)
treeb23cc115bbe39d25eb8ff7dc410700b7f42cf46d /runtime
parentb82a2f114c7c936bf4398669453513ace478cb1d (diff)
feat: async context (#24402)
We are switching to ContinuationPreservedEmbedderData. This allows adding async context tracking to the various async operations that deno provides. Fixes: https://github.com/denoland/deno/issues/7010 Fixes: https://github.com/denoland/deno/issues/22886 Fixes: https://github.com/denoland/deno/issues/24368
Diffstat (limited to 'runtime')
-rw-r--r--runtime/js/01_async_context.js45
-rw-r--r--runtime/ops/runtime.rs11
-rw-r--r--runtime/shared.rs1
3 files changed, 56 insertions, 1 deletions
diff --git a/runtime/js/01_async_context.js b/runtime/js/01_async_context.js
new file mode 100644
index 000000000..9c0236fbe
--- /dev/null
+++ b/runtime/js/01_async_context.js
@@ -0,0 +1,45 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+import { primordials } from "ext:core/mod.js";
+import { op_get_extras_binding_object } from "ext:core/ops";
+
+const {
+ SafeWeakMap,
+} = primordials;
+
+const {
+ getContinuationPreservedEmbedderData,
+ setContinuationPreservedEmbedderData,
+} = op_get_extras_binding_object();
+
+let counter = 0;
+
+export const getAsyncContext = getContinuationPreservedEmbedderData;
+export const setAsyncContext = setContinuationPreservedEmbedderData;
+
+export class AsyncVariable {
+ #id = counter++;
+ #data = new SafeWeakMap();
+
+ enter(value) {
+ const previousContextMapping = getAsyncContext();
+ const entry = { id: this.#id };
+ const asyncContextMapping = {
+ __proto__: null,
+ ...previousContextMapping,
+ [this.#id]: entry,
+ };
+ this.#data.set(entry, value);
+ setAsyncContext(asyncContextMapping);
+ return previousContextMapping;
+ }
+
+ get() {
+ const current = getAsyncContext();
+ const entry = current?.[this.#id];
+ if (entry) {
+ return this.#data.get(entry);
+ }
+ return undefined;
+ }
+}
diff --git a/runtime/ops/runtime.rs b/runtime/ops/runtime.rs
index 306e6ce8f..b52a23f30 100644
--- a/runtime/ops/runtime.rs
+++ b/runtime/ops/runtime.rs
@@ -2,13 +2,14 @@
use deno_core::error::AnyError;
use deno_core::op2;
+use deno_core::v8;
use deno_core::ModuleSpecifier;
use deno_core::OpState;
use deno_permissions::PermissionsContainer;
deno_core::extension!(
deno_runtime,
- ops = [op_main_module, op_ppid],
+ ops = [op_main_module, op_ppid, op_get_extras_binding_object],
options = { main_module: ModuleSpecifier },
state = |state, options| {
state.put::<ModuleSpecifier>(options.main_module);
@@ -94,3 +95,11 @@ pub fn op_ppid() -> i64 {
parent_id().into()
}
}
+
+#[op2]
+pub fn op_get_extras_binding_object<'a>(
+ scope: &mut v8::HandleScope<'a>,
+) -> v8::Local<'a, v8::Value> {
+ let context = scope.get_current_context();
+ context.get_extras_binding_object(scope).into()
+}
diff --git a/runtime/shared.rs b/runtime/shared.rs
index 1b2136c63..185cbc0a9 100644
--- a/runtime/shared.rs
+++ b/runtime/shared.rs
@@ -38,6 +38,7 @@ extension!(runtime,
dir "js",
"01_errors.js",
"01_version.ts",
+ "01_async_context.js",
"06_util.js",
"10_permissions.js",
"11_workers.js",