summaryrefslogtreecommitdiff
path: root/runtime/js
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/js
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/js')
-rw-r--r--runtime/js/01_async_context.js45
1 files changed, 45 insertions, 0 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;
+ }
+}