From 04219496f1fc3e986332f580c96fa279b065ea0e Mon Sep 17 00:00:00 2001 From: James M Snell Date: Tue, 13 Feb 2024 08:42:32 -0800 Subject: [PATCH] Add v8 patch to preserve async context for custom thenables --- WORKSPACE | 1 + ...etting-ValueDeserializer-format-vers.patch | 2 +- ...etting-ValueSerializer-format-versio.patch | 2 +- .../v8/0003-Make-icudata-target-public.patch | 2 +- .../v8/0004-Add-ArrayBuffer-MaybeNew.patch | 2 +- ...005-Allow-Windows-builds-under-Bazel.patch | 2 +- ...06-Disable-bazel-whole-archive-build.patch | 2 +- ...ker-automatically-call-isolate-Enter.patch | 2 +- ...pture-and-restore-the-cage-base-poin.patch | 2 +- ...zel-build-by-always-using-target-cfg.patch | 2 +- ...10-Implement-Promise-Context-Tagging.patch | 60 +++---- .../v8/0011-Enable-V8-shared-linkage.patch | 2 +- patches/v8/0012-Fix-V8-ICU-build.patch | 2 +- ...itial-ExecutionContextId-used-by-the.patch | 2 +- ...ntinuation-preserved-data-in-the-bui.patch | 2 +- ...ion-context-to-Promise-thenable-task.patch | 165 ++++++++++++++++++ src/workerd/api/tests/als-test.js | 31 ++++ src/workerd/api/tests/als-test.wd-test | 15 ++ 18 files changed, 255 insertions(+), 43 deletions(-) create mode 100644 patches/v8/0015-Attach-continuation-context-to-Promise-thenable-task.patch create mode 100644 src/workerd/api/tests/als-test.js create mode 100644 src/workerd/api/tests/als-test.wd-test diff --git a/WORKSPACE b/WORKSPACE index 815ce07ac01..eb8c28408a9 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -434,6 +434,7 @@ http_archive( "//:patches/v8/0012-Fix-V8-ICU-build.patch", "//:patches/v8/0013-Randomize-the-initial-ExecutionContextId-used-by-the.patch", "//:patches/v8/0014-Always-enable-continuation-preserved-data-in-the-bui.patch", + "//:patches/v8/0015-Attach-continuation-context-to-Promise-thenable-task.patch", ], sha256 = "45e0ba667fb1a86f834d6a92b513c43fcfdc672525c8a5a60bfdb56eec137d4a", strip_prefix = "v8-12.1.285.26", diff --git a/patches/v8/0001-Allow-manually-setting-ValueDeserializer-format-vers.patch b/patches/v8/0001-Allow-manually-setting-ValueDeserializer-format-vers.patch index a151767be9c..2fbb3c0c61b 100644 --- a/patches/v8/0001-Allow-manually-setting-ValueDeserializer-format-vers.patch +++ b/patches/v8/0001-Allow-manually-setting-ValueDeserializer-format-vers.patch @@ -1,4 +1,4 @@ -From 025482cca7b65b7692d2905fdf8eb8844cd560c3 Mon Sep 17 00:00:00 2001 +From d529886e9db66ef38cd317d417c23bb7bdc964c0 Mon Sep 17 00:00:00 2001 From: Alex Robinson Date: Wed, 2 Mar 2022 15:58:04 -0600 Subject: Allow manually setting ValueDeserializer format version diff --git a/patches/v8/0002-Allow-manually-setting-ValueSerializer-format-versio.patch b/patches/v8/0002-Allow-manually-setting-ValueSerializer-format-versio.patch index 7f4553f4f32..a4469b274b8 100644 --- a/patches/v8/0002-Allow-manually-setting-ValueSerializer-format-versio.patch +++ b/patches/v8/0002-Allow-manually-setting-ValueSerializer-format-versio.patch @@ -1,4 +1,4 @@ -From 029d28b2a8470a26bb60c54781a0835910dcc583 Mon Sep 17 00:00:00 2001 +From b05b76fd24b4277a9d6fcf6d6462aa5f583582ab Mon Sep 17 00:00:00 2001 From: James M Snell Date: Wed, 16 Mar 2022 08:59:21 -0700 Subject: Allow manually setting ValueSerializer format version diff --git a/patches/v8/0003-Make-icudata-target-public.patch b/patches/v8/0003-Make-icudata-target-public.patch index cd9389ec611..153539d7dc4 100644 --- a/patches/v8/0003-Make-icudata-target-public.patch +++ b/patches/v8/0003-Make-icudata-target-public.patch @@ -1,4 +1,4 @@ -From 727f8f091a86edfe8c006cff310f1def08cbed6b Mon Sep 17 00:00:00 2001 +From fbeb4c7407709f33902a316b80464aaf8f3cdc5d Mon Sep 17 00:00:00 2001 From: Kenton Varda Date: Sat, 17 Sep 2022 11:11:15 -0500 Subject: Make `:icudata` target public. diff --git a/patches/v8/0004-Add-ArrayBuffer-MaybeNew.patch b/patches/v8/0004-Add-ArrayBuffer-MaybeNew.patch index 4bf71a12602..b014f0c20b2 100644 --- a/patches/v8/0004-Add-ArrayBuffer-MaybeNew.patch +++ b/patches/v8/0004-Add-ArrayBuffer-MaybeNew.patch @@ -1,4 +1,4 @@ -From f8be71a7afa20ded149f594f7ac38e53d2c85fa0 Mon Sep 17 00:00:00 2001 +From bd257320c7a70ec3a330086b58f85b02d178d534 Mon Sep 17 00:00:00 2001 From: Kenton Varda Date: Fri, 16 Sep 2022 21:41:45 -0500 Subject: Add `ArrayBuffer::MaybeNew()`. diff --git a/patches/v8/0005-Allow-Windows-builds-under-Bazel.patch b/patches/v8/0005-Allow-Windows-builds-under-Bazel.patch index f712c4ae04c..e9fcbad46f1 100644 --- a/patches/v8/0005-Allow-Windows-builds-under-Bazel.patch +++ b/patches/v8/0005-Allow-Windows-builds-under-Bazel.patch @@ -1,4 +1,4 @@ -From 9e93f5c62780aac7bf8649f76ecd3181df1473dc Mon Sep 17 00:00:00 2001 +From 5e8439c07e9f3a31591cb7c8bef6581293435255 Mon Sep 17 00:00:00 2001 From: Brendan Coll Date: Thu, 16 Mar 2023 11:56:10 +0000 Subject: Allow Windows builds under Bazel diff --git a/patches/v8/0006-Disable-bazel-whole-archive-build.patch b/patches/v8/0006-Disable-bazel-whole-archive-build.patch index f71b08bc635..400894bdc39 100644 --- a/patches/v8/0006-Disable-bazel-whole-archive-build.patch +++ b/patches/v8/0006-Disable-bazel-whole-archive-build.patch @@ -1,4 +1,4 @@ -From 42ae0d533772f9aae98f0f17454802e2b2af3bc0 Mon Sep 17 00:00:00 2001 +From 7783257dadbc076574a7b0156a5f3c2b8d192956 Mon Sep 17 00:00:00 2001 From: Felix Hanau Date: Tue, 11 Apr 2023 14:41:31 -0400 Subject: Disable bazel whole-archive build diff --git a/patches/v8/0007-Make-v8-Locker-automatically-call-isolate-Enter.patch b/patches/v8/0007-Make-v8-Locker-automatically-call-isolate-Enter.patch index 79f7387f527..2e5f7bd44ec 100644 --- a/patches/v8/0007-Make-v8-Locker-automatically-call-isolate-Enter.patch +++ b/patches/v8/0007-Make-v8-Locker-automatically-call-isolate-Enter.patch @@ -1,4 +1,4 @@ -From 10c232c3282ceda1c144b4edf0d762a2289fa23f Mon Sep 17 00:00:00 2001 +From 7ed177af0c5fa711cbd95e58e0161732ca601e6c Mon Sep 17 00:00:00 2001 From: Kenton Varda Date: Tue, 23 May 2023 09:18:57 -0500 Subject: Make v8::Locker automatically call isolate->Enter(). diff --git a/patches/v8/0008-Add-an-API-to-capture-and-restore-the-cage-base-poin.patch b/patches/v8/0008-Add-an-API-to-capture-and-restore-the-cage-base-poin.patch index 77ed1426671..8c6057fd46b 100644 --- a/patches/v8/0008-Add-an-API-to-capture-and-restore-the-cage-base-poin.patch +++ b/patches/v8/0008-Add-an-API-to-capture-and-restore-the-cage-base-poin.patch @@ -1,4 +1,4 @@ -From 44878c36ee87d51dadd3815bf5de749d05cfe189 Mon Sep 17 00:00:00 2001 +From c793b007c8605fa8827ca80dac70aaef02908777 Mon Sep 17 00:00:00 2001 From: Kenton Varda Date: Tue, 23 May 2023 09:24:11 -0500 Subject: Add an API to capture and restore the cage base pointers. diff --git a/patches/v8/0009-Speed-up-V8-bazel-build-by-always-using-target-cfg.patch b/patches/v8/0009-Speed-up-V8-bazel-build-by-always-using-target-cfg.patch index 4fefec59b2b..896624a6e3f 100644 --- a/patches/v8/0009-Speed-up-V8-bazel-build-by-always-using-target-cfg.patch +++ b/patches/v8/0009-Speed-up-V8-bazel-build-by-always-using-target-cfg.patch @@ -1,4 +1,4 @@ -From 8316053ffc2767486f2722aecb0a4af623474a26 Mon Sep 17 00:00:00 2001 +From e7293ce5f06664b96c146bdb36d6377ff158769a Mon Sep 17 00:00:00 2001 From: Felix Hanau Date: Wed, 7 Jun 2023 21:40:54 -0400 Subject: Speed up V8 bazel build by always using target cfg diff --git a/patches/v8/0010-Implement-Promise-Context-Tagging.patch b/patches/v8/0010-Implement-Promise-Context-Tagging.patch index d600000fa77..6352e2ab06d 100644 --- a/patches/v8/0010-Implement-Promise-Context-Tagging.patch +++ b/patches/v8/0010-Implement-Promise-Context-Tagging.patch @@ -1,4 +1,4 @@ -From 19ab176443e7dbc6a11b8f4b1b766c2e00759133 Mon Sep 17 00:00:00 2001 +From 1fb5093f0fedcfa03ed1482fe34d3452c9f4250e Mon Sep 17 00:00:00 2001 From: James M Snell Date: Thu, 22 Jun 2023 15:29:26 -0700 Subject: Implement Promise Context Tagging @@ -29,7 +29,7 @@ index 2a25b9ee04e003ee69ec91a614769b43be9cd2eb..8736ed62924d12ff679cd99fdb100df6 @@ -463,6 +463,15 @@ using FilterETWSessionByURLCallback = bool (*)(Local context, const std::string& etw_filter_payload); #endif // V8_OS_WIN - + +/** + * PromiseCrossContextCallback is called when following a promise and the + * promise's context tag is not strictly equal to the isolate's current @@ -40,7 +40,7 @@ index 2a25b9ee04e003ee69ec91a614769b43be9cd2eb..8736ed62924d12ff679cd99fdb100df6 + Local tag); + } // namespace v8 - + #endif // INCLUDE_V8_ISOLATE_CALLBACKS_H_ diff --git a/include/v8-isolate.h b/include/v8-isolate.h index 6c0aefdb490f7b1e32b9b3057302843e6451af12..b7e62f7afc38d0b093734f0a9c948eaab6256afe 100644 @@ -49,7 +49,7 @@ index 6c0aefdb490f7b1e32b9b3057302843e6451af12..b7e62f7afc38d0b093734f0a9c948eaa @@ -1703,6 +1703,9 @@ class V8_EXPORT Isolate { */ void LocaleConfigurationChangeNotification(); - + + class PromiseContextScope; + void SetPromiseCrossContextCallback(PromiseCrossContextCallback callback); + @@ -59,7 +59,7 @@ index 6c0aefdb490f7b1e32b9b3057302843e6451af12..b7e62f7afc38d0b093734f0a9c948eaa @@ -1747,6 +1750,19 @@ MaybeLocal Isolate::GetDataFromSnapshotOnce(size_t index) { return Local::FromSlot(slot); } - + +class Isolate::PromiseContextScope { +public: + PromiseContextScope(Isolate* isolate, v8::Local tag); @@ -74,7 +74,7 @@ index 6c0aefdb490f7b1e32b9b3057302843e6451af12..b7e62f7afc38d0b093734f0a9c948eaa +}; + } // namespace v8 - + #endif // INCLUDE_V8_ISOLATE_H_ diff --git a/src/api/api.cc b/src/api/api.cc index f59eed43d782fe434e4dcbcd7fb7cb4c5f2590b4..b3b92936b5d0936211e788c7da61395b55cfbace 100644 @@ -83,7 +83,7 @@ index f59eed43d782fe434e4dcbcd7fb7cb4c5f2590b4..b3b92936b5d0936211e788c7da61395b @@ -11860,6 +11860,23 @@ std::string SourceLocation::ToString() const { return std::string(function_) + "@" + file_ + ":" + std::to_string(line_); } - + +void Isolate::SetPromiseCrossContextCallback(PromiseCrossContextCallback callback) { + i::Isolate* isolate = reinterpret_cast(this); + isolate->set_promise_cross_context_callback(callback); @@ -102,21 +102,21 @@ index f59eed43d782fe434e4dcbcd7fb7cb4c5f2590b4..b3b92936b5d0936211e788c7da61395b +} + } // namespace v8 - + #include "src/api/api-macros-undef.h" diff --git a/src/builtins/promise-abstract-operations.tq b/src/builtins/promise-abstract-operations.tq index 7ee1f5db9eecc96c28f27a04c85bead57e043c82..7126d20f9f8bf1646d847eb65ef9eea1ef4b5473 100644 --- a/src/builtins/promise-abstract-operations.tq +++ b/src/builtins/promise-abstract-operations.tq @@ -20,6 +20,9 @@ extern transitioning runtime PromiseResolveAfterResolved( - + extern transitioning runtime PromiseRejectEventFromStack( implicit context: Context)(JSPromise, JSAny): JSAny; + +extern transitioning runtime PromiseContextCheck( + implicit context: Context)(JSPromise): JSPromise; } - + // https://tc39.es/ecma262/#sec-promise-abstract-operations @@ -445,14 +448,15 @@ transitioning macro PerformPromiseThenImpl( // PromiseReaction holding both the onFulfilled and onRejected callbacks. @@ -145,21 +145,21 @@ index 7ee1f5db9eecc96c28f27a04c85bead57e043c82..7126d20f9f8bf1646d847eb65ef9eea1 } - promise.SetHasHandler(); } - + // https://tc39.es/ecma262/#sec-performpromisethen diff --git a/src/builtins/promise-constructor.tq b/src/builtins/promise-constructor.tq index 5611e228b50cfdccdc0a15e5736a6446c8785fa7..f644158394705f1313a505f1c5e517f01d66630e 100644 --- a/src/builtins/promise-constructor.tq +++ b/src/builtins/promise-constructor.tq @@ -13,6 +13,9 @@ extern transitioning runtime DebugPopPromise(implicit context: Context)(): JSAny - + extern transitioning runtime PromiseHookInit( implicit context: Context)(Object, Object): JSAny; + +extern transitioning runtime PromiseContextInit( + implicit context: Context)(JSPromise): JSAny; } - + // https://tc39.es/ecma262/#sec-promise-constructor @@ -70,6 +73,7 @@ transitioning javascript builtin PromiseConstructor( result = UnsafeCast( @@ -168,7 +168,7 @@ index 5611e228b50cfdccdc0a15e5736a6446c8785fa7..f644158394705f1313a505f1c5e517f0 + runtime::PromiseContextInit(result); RunAnyPromiseHookInit(result, Undefined); } - + diff --git a/src/builtins/promise-misc.tq b/src/builtins/promise-misc.tq index 6b167839f107b95dfbd6e4e5ee72805615625ace..0abec7c6d2faa13a7b193ff66a53619d2d00fb64 100644 --- a/src/builtins/promise-misc.tq @@ -180,7 +180,7 @@ index 6b167839f107b95dfbd6e4e5ee72805615625ace..0abec7c6d2faa13a7b193ff66a53619d + promise.context_tag = kZero; promise_internal::ZeroOutEmbedderOffsets(promise); } - + @@ -68,6 +69,7 @@ macro InnerNewJSPromise(implicit context: Context)(): JSPromise { is_silent: false, async_task_id: 0 @@ -188,7 +188,7 @@ index 6b167839f107b95dfbd6e4e5ee72805615625ace..0abec7c6d2faa13a7b193ff66a53619d + promise.context_tag = kZero; return promise; } - + @@ -277,6 +279,7 @@ transitioning macro NewJSPromise(implicit context: Context)(parent: Object): JSPromise { const instance = InnerNewJSPromise(); @@ -234,7 +234,7 @@ index 5be3bfb2e3c890321de063f617def3d4ee03eaad..2f459e09a0f1b0ef7b5312a5238b821a + os << "\n - context_tag: " << Brief(context_tag()); JSObjectPrintBody(os, *this); } - + diff --git a/src/execution/isolate-inl.h b/src/execution/isolate-inl.h index f2b1759d7cd8e0b8a52648bd401419f8d1c8d0d8..0305a6cf783a721c46042468ac08739c43d4aecd 100644 --- a/src/execution/isolate-inl.h @@ -242,7 +242,7 @@ index f2b1759d7cd8e0b8a52648bd401419f8d1c8d0d8..0305a6cf783a721c46042468ac08739c @@ -100,6 +100,26 @@ bool Isolate::is_execution_terminating() { i::ReadOnlyRoots(this).termination_exception(); } - + +Tagged Isolate::promise_context_tag() { + return promise_context_tag_; +} @@ -267,7 +267,7 @@ index f2b1759d7cd8e0b8a52648bd401419f8d1c8d0d8..0305a6cf783a721c46042468ac08739c Tagged Isolate::VerifyBuiltinsResult(Tagged result) { DCHECK_EQ(has_exception(), result == ReadOnlyRoots(this).exception()); diff --git a/src/execution/isolate.cc b/src/execution/isolate.cc -index 28d1a8866e4f0730d75d19f54c005ec9728c8766..70a701d6fe425d0f8fb6aceb1713fd78aca407b1 100644 +index 28d1a8866e4f0730d75d19f54c005ec9728c8766..b3003a99efd152e14ae13f324aa8f3017b6fec34 100644 --- a/src/execution/isolate.cc +++ b/src/execution/isolate.cc @@ -571,6 +571,8 @@ void Isolate::Iterate(RootVisitor* v, ThreadLocalTop* thread) { @@ -276,21 +276,21 @@ index 28d1a8866e4f0730d75d19f54c005ec9728c8766..70a701d6fe425d0f8fb6aceb1713fd78 FullObjectSlot(&thread->context_)); + v->VisitRootPointer(Root::kStackRoots, nullptr, + FullObjectSlot(&promise_context_tag_)); - + for (v8::TryCatch* block = thread->try_catch_handler_; block != nullptr; block = block->next_) { @@ -4764,6 +4766,7 @@ bool Isolate::Init(SnapshotData* startup_snapshot_data, shared_heap_object_cache_.push_back(ReadOnlyRoots(this).undefined_value()); } - + + clear_promise_context_tag(); InitializeThreadLocal(); - + // Profiler has to be created after ThreadLocal is initialized @@ -6581,5 +6584,39 @@ void DefaultWasmAsyncResolvePromiseCallback( CHECK(ret.IsJust() ? ret.FromJust() : isolate->IsExecutionTerminating()); } - + +class Isolate::PromiseCrossContextCallbackScope { +public: + PromiseCrossContextCallbackScope(Isolate& isolate) : isolate_(isolate) { @@ -334,7 +334,7 @@ index afd785b807f7d79cbc0feb75d93e40e5f8babde6..8182a9c0c077dbd742fed79add299cc5 @@ -2177,6 +2177,14 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory { // stack. void PrepareForSuddenShutdown(); - + + inline Tagged promise_context_tag(); + inline bool has_promise_context_tag(); + inline void clear_promise_context_tag(); @@ -349,7 +349,7 @@ index afd785b807f7d79cbc0feb75d93e40e5f8babde6..8182a9c0c077dbd742fed79add299cc5 @@ -2670,11 +2678,18 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory { SimulatorData* simulator_data_ = nullptr; #endif - + + Tagged promise_context_tag_; + PromiseCrossContextCallback promise_cross_context_callback_; + bool in_promise_cross_context_callback_ = false; @@ -363,7 +363,7 @@ index afd785b807f7d79cbc0feb75d93e40e5f8babde6..8182a9c0c077dbd742fed79add299cc5 friend class IsolateForSandbox; + friend class PromiseCrossContextCallbackScope; }; - + // The current entered Isolate and its thread data. Do not access these diff --git a/src/heap/factory.cc b/src/heap/factory.cc index 0e840992304b4792937145df82f786c31dac8d47..3eeecf24fd273b69b4897a37c68dc02048dc1339 100644 @@ -393,7 +393,7 @@ index 25c7e1f76c72996eb1d8fb3d93cbfc06f4f41bf3..5afde92d7cdbd7d1b06060a2c047474a + context_tag: Zero|JSAny; flags: SmiTagged; } - + diff --git a/src/profiler/heap-snapshot-generator.cc b/src/profiler/heap-snapshot-generator.cc index 3a10d2332f9b37b0359ac9c0b69d8093bb02ed6d..dd04726fd68ae5b01ed5181ca54898255a292557 100644 --- a/src/profiler/heap-snapshot-generator.cc @@ -406,7 +406,7 @@ index 3a10d2332f9b37b0359ac9c0b69d8093bb02ed6d..dd04726fd68ae5b01ed5181ca5489825 + promise->context_tag(), + JSPromise::kContextTagOffset); } - + void V8HeapExplorer::ExtractJSGeneratorObjectReferences( diff --git a/src/runtime/runtime-promise.cc b/src/runtime/runtime-promise.cc index 139bab490bd05eac001e0799201d536c9d64eb29..392becbc6689dc693ee9bd1919b7f55af23031cc 100644 @@ -415,7 +415,7 @@ index 139bab490bd05eac001e0799201d536c9d64eb29..392becbc6689dc693ee9bd1919b7f55a @@ -209,5 +209,40 @@ RUNTIME_FUNCTION(Runtime_ConstructInternalAggregateErrorHelper) { return *result; } - + +RUNTIME_FUNCTION(Runtime_PromiseContextInit) { + HandleScope scope(isolate); + DCHECK_EQ(1, args.length()); @@ -465,6 +465,6 @@ index 567d60f75807a7e25445955c3d2f0b812d274b80..8f04fb34cf615f1ef4bdfd0eaa6dbb18 + F(ConstructInternalAggregateErrorHelper, -1 /* <= 5*/, 1) \ + F(PromiseContextInit, 1, 1) \ + F(PromiseContextCheck, 1, 1) - + #define FOR_EACH_INTRINSIC_PROXY(F, I) \ F(CheckProxyGetSetTrapResult, 2, 1) \ diff --git a/patches/v8/0011-Enable-V8-shared-linkage.patch b/patches/v8/0011-Enable-V8-shared-linkage.patch index 93479a5cd0c..ad8d7899592 100644 --- a/patches/v8/0011-Enable-V8-shared-linkage.patch +++ b/patches/v8/0011-Enable-V8-shared-linkage.patch @@ -1,4 +1,4 @@ -From ab92e41e703b846b461befaf8af2f8be706c4065 Mon Sep 17 00:00:00 2001 +From 1dcf856d0dbef118c3dc221d2820b2cbd4b16a7f Mon Sep 17 00:00:00 2001 From: Felix Hanau Date: Sun, 9 Jul 2023 18:46:20 -0400 Subject: Enable V8 shared linkage diff --git a/patches/v8/0012-Fix-V8-ICU-build.patch b/patches/v8/0012-Fix-V8-ICU-build.patch index 22b5144bef3..5d7b54daea5 100644 --- a/patches/v8/0012-Fix-V8-ICU-build.patch +++ b/patches/v8/0012-Fix-V8-ICU-build.patch @@ -1,4 +1,4 @@ -From 4c01cb76c54c8d3365c711b44413fb3da2917a11 Mon Sep 17 00:00:00 2001 +From 8ec1bbc4c6c97e087ec33192d2230e377c6fc140 Mon Sep 17 00:00:00 2001 From: Felix Hanau Date: Wed, 26 Jul 2023 18:40:13 +0200 Subject: Fix V8/ICU build diff --git a/patches/v8/0013-Randomize-the-initial-ExecutionContextId-used-by-the.patch b/patches/v8/0013-Randomize-the-initial-ExecutionContextId-used-by-the.patch index e8a695329be..6b3a113ff71 100644 --- a/patches/v8/0013-Randomize-the-initial-ExecutionContextId-used-by-the.patch +++ b/patches/v8/0013-Randomize-the-initial-ExecutionContextId-used-by-the.patch @@ -1,4 +1,4 @@ -From 4ded67a1634ef0dd7e06252d1f3085fbd3faaf92 Mon Sep 17 00:00:00 2001 +From b92876218fc06d53911724ee40ff463e36e7de4d Mon Sep 17 00:00:00 2001 From: Orion Hodson Date: Wed, 13 Sep 2023 15:38:15 +0100 Subject: Randomize the initial ExecutionContextId used by the inspector diff --git a/patches/v8/0014-Always-enable-continuation-preserved-data-in-the-bui.patch b/patches/v8/0014-Always-enable-continuation-preserved-data-in-the-bui.patch index 81a81752b3c..e320f0c7be9 100644 --- a/patches/v8/0014-Always-enable-continuation-preserved-data-in-the-bui.patch +++ b/patches/v8/0014-Always-enable-continuation-preserved-data-in-the-bui.patch @@ -1,4 +1,4 @@ -From 5516cf4ef1610748570cc6dd88c2a9141d5d79f8 Mon Sep 17 00:00:00 2001 +From 1552093829d95880cd253e45915f195e1602df56 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Thu, 18 Jan 2024 10:19:14 -0800 Subject: Always enable continuation preserved data in the build diff --git a/patches/v8/0015-Attach-continuation-context-to-Promise-thenable-task.patch b/patches/v8/0015-Attach-continuation-context-to-Promise-thenable-task.patch new file mode 100644 index 00000000000..7800f07abc8 --- /dev/null +++ b/patches/v8/0015-Attach-continuation-context-to-Promise-thenable-task.patch @@ -0,0 +1,165 @@ +From ecb1e7084e1afe72fa335536e7f8cf9f9951df64 Mon Sep 17 00:00:00 2001 +From: James M Snell +Date: Tue, 6 Feb 2024 17:21:53 -0800 +Subject: Attach continuation context to Promise thenable task + +--- + src/builtins/builtins-microtask-queue-gen.cc | 42 ++++++++++++++++ + src/builtins/promise-misc.tq | 50 +++++++++++++++----- + src/heap/factory.cc | 8 ++++ + src/objects/promise.tq | 4 ++ + 4 files changed, 91 insertions(+), 13 deletions(-) + +diff --git a/src/builtins/builtins-microtask-queue-gen.cc b/src/builtins/builtins-microtask-queue-gen.cc +index 764c2b3eaf3fe763285560b62c95f32aa1f2e85a..377a6710888be8287e76b0c0787ed7699da47136 100644 +--- a/src/builtins/builtins-microtask-queue-gen.cc ++++ b/src/builtins/builtins-microtask-queue-gen.cc +@@ -203,6 +203,30 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( + const TNode thenable = LoadObjectField( + microtask, PromiseResolveThenableJobTask::kThenableOffset); + ++#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA ++ TNode isolate_preserved_embedder_data = LoadObjectField( ++ microtask, PromiseResolveThenableJobTask:: ++ kIsolateContinuationPreservedEmbedderDataOffset); ++ Label isolate_preserved_data_done(this); ++ GotoIf(IsUndefined(isolate_preserved_embedder_data), ++ &isolate_preserved_data_done); ++ SetContinuationPreservedEmbedderData(isolate_preserved_embedder_data); ++ Goto(&isolate_preserved_data_done); ++ BIND(&isolate_preserved_data_done); ++ ++ TNode context_preserved_embedder_data = LoadObjectField( ++ microtask, PromiseResolveThenableJobTask:: ++ kContextContinuationPreservedEmbedderDataOffset); ++ Label context_preserved_data_done(this); ++ GotoIf(IsUndefined(context_preserved_embedder_data), ++ &context_preserved_data_done); ++ StoreContextElement(native_context, ++ Context::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX, ++ context_preserved_embedder_data); ++ Goto(&context_preserved_data_done); ++ BIND(&context_preserved_data_done); ++#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA ++ + RunAllPromiseHooks(PromiseHookType::kBefore, microtask_context, + CAST(promise_to_resolve)); + +@@ -215,6 +239,24 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( + RunAllPromiseHooks(PromiseHookType::kAfter, microtask_context, + CAST(promise_to_resolve)); + ++#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA ++ Label isolate_preserved_data_reset_done(this); ++ GotoIf(IsUndefined(isolate_preserved_embedder_data), ++ &isolate_preserved_data_reset_done); ++ SetContinuationPreservedEmbedderData(UndefinedConstant()); ++ Goto(&isolate_preserved_data_reset_done); ++ BIND(&isolate_preserved_data_reset_done); ++ ++ Label context_preserved_data_reset_done(this); ++ GotoIf(IsUndefined(context_preserved_embedder_data), ++ &context_preserved_data_reset_done); ++ StoreContextElement(native_context, ++ Context::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX, ++ UndefinedConstant()); ++ Goto(&context_preserved_data_reset_done); ++ BIND(&context_preserved_data_reset_done); ++#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA ++ + RewindEnteredContext(saved_entered_context_count); + SetCurrentContext(current_context); + Goto(&done); +diff --git a/src/builtins/promise-misc.tq b/src/builtins/promise-misc.tq +index 0abec7c6d2faa13a7b193ff66a53619d2d00fb64..3e36fe3123c158d727bfc5ad94942b841413598b 100644 +--- a/src/builtins/promise-misc.tq ++++ b/src/builtins/promise-misc.tq +@@ -358,19 +358,43 @@ macro NewPromiseResolveThenableJobTask( + // Proxy object, which would throw when it is called anyway. So instead of + // setting the context to null as the spec does, we just use the current + // realm. +- const thenContext: Context = ExtractHandlerContext(then); +- const nativeContext = LoadNativeContext(thenContext); +- +- // 1. Let job be a new Job abstract closure with no parameters that +- // captures promiseToResolve, thenable, and then... +- // 5. Return { [[Job]]: job, [[Realm]]: thenRealm }. +- return new PromiseResolveThenableJobTask{ +- map: PromiseResolveThenableJobTaskMapConstant(), +- context: nativeContext, +- promise_to_resolve: promiseToResolve, +- thenable, +- then +- }; ++ @if(V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA) { ++ const thenContext: Context = ExtractHandlerContext(then); ++ const isolateContinuationData = GetContinuationPreservedEmbedderData(); ++ const nativeContext = LoadNativeContext(thenContext); ++ ++ // 1. Let job be a new Job abstract closure with no parameters that ++ // captures promiseToResolve, thenable, and then... ++ // 5. Return { [[Job]]: job, [[Realm]]: thenRealm }. ++ return new PromiseResolveThenableJobTask{ ++ map: PromiseResolveThenableJobTaskMapConstant(), ++ context: nativeContext, ++ promise_to_resolve: promiseToResolve, ++ thenable, ++ then, ++ isolate_continuation_preserved_embedder_data: isolateContinuationData, ++ context_continuation_preserved_embedder_data: ++ *ContextSlot( ++ nativeContext, ++ ContextSlot::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX) ++ }; ++ } ++ ++ @ifnot(V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA) { ++ const thenContext: Context = ExtractHandlerContext(then); ++ const nativeContext = LoadNativeContext(thenContext); ++ ++ // 1. Let job be a new Job abstract closure with no parameters that ++ // captures promiseToResolve, thenable, and then... ++ // 5. Return { [[Job]]: job, [[Realm]]: thenRealm }. ++ return new PromiseResolveThenableJobTask{ ++ map: PromiseResolveThenableJobTaskMapConstant(), ++ context: nativeContext, ++ promise_to_resolve: promiseToResolve, ++ thenable, ++ then ++ }; ++ } + } + + struct InvokeThenOneArgFunctor { +diff --git a/src/heap/factory.cc b/src/heap/factory.cc +index 3eeecf24fd273b69b4897a37c68dc02048dc1339..9abb36e806a56c41e4c942b44cd623e783e20d23 100644 +--- a/src/heap/factory.cc ++++ b/src/heap/factory.cc +@@ -1570,6 +1570,14 @@ Handle Factory::NewPromiseResolveThenableJobTask( + microtask->set_thenable(*thenable, SKIP_WRITE_BARRIER); + microtask->set_then(*then, SKIP_WRITE_BARRIER); + microtask->set_context(*context, SKIP_WRITE_BARRIER); ++#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA ++ microtask->set_isolate_continuation_preserved_embedder_data( ++ isolate()->isolate_data()->continuation_preserved_embedder_data(), ++ SKIP_WRITE_BARRIER); ++ microtask->set_context_continuation_preserved_embedder_data( ++ isolate()->native_context()->continuation_preserved_embedder_data(), ++ SKIP_WRITE_BARRIER); ++#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + return handle(microtask, isolate()); + } + +diff --git a/src/objects/promise.tq b/src/objects/promise.tq +index 0633251781eb43657cb237b9d19200378569f743..47cf1350e3e436fc7bc56bac89aef60310b4a828 100644 +--- a/src/objects/promise.tq ++++ b/src/objects/promise.tq +@@ -90,4 +90,8 @@ extern class PromiseResolveThenableJobTask extends Microtask { + promise_to_resolve: JSPromise; + thenable: JSReceiver; + then: JSReceiver; ++ @if(V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA) ++ isolate_continuation_preserved_embedder_data: Object|Undefined; ++ @if(V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA) ++ context_continuation_preserved_embedder_data: Object|Undefined; + } diff --git a/src/workerd/api/tests/als-test.js b/src/workerd/api/tests/als-test.js new file mode 100644 index 00000000000..cad43928a1a --- /dev/null +++ b/src/workerd/api/tests/als-test.js @@ -0,0 +1,31 @@ +import { + strictEqual, +} from 'node:assert'; + +import { + AsyncLocalStorage, +} from 'node:async_hooks'; + +export const customthenable = { + // Test to ensure that async context is propagated into custom thenables. + async test() { + const als = new AsyncLocalStorage(); + const result = await als.run(123, async () => { + return await { + then(done) { + done(als.getStore()); + } + }; + }); + strictEqual(result, 123); + + const result2 = await als.run(123, async () => { + return await new Promise((resolve) => resolve({ + then(done) { + done(als.getStore()); + } + })); + }); + strictEqual(result2, 123); + } +}; diff --git a/src/workerd/api/tests/als-test.wd-test b/src/workerd/api/tests/als-test.wd-test new file mode 100644 index 00000000000..5858439e4a8 --- /dev/null +++ b/src/workerd/api/tests/als-test.wd-test @@ -0,0 +1,15 @@ +using Workerd = import "/workerd/workerd.capnp"; + +const unitTests :Workerd.Config = ( + services = [ + ( name = "als-test", + worker = ( + modules = [ + (name = "worker", esModule = embed "als-test.js") + ], + compatibilityDate = "2023-01-15", + compatibilityFlags = ["nodejs_compat"] + ) + ), + ], +);