| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent f162896 commit 7ba3055
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -454,8 +454,8 @@ static void EnablePromiseHook(const FunctionCallbackInfo<Value>& args) { | |||
| 454 | 454 | ||
| 455 | 455 | static void SetPromiseHooks(const FunctionCallbackInfo<Value>& args) { | |
| 456 | 456 | Environment* env = Environment::GetCurrent(args); | |
| 457 | - Local<Context> ctx = env->context(); | ||
| 458 | - ctx->SetPromiseHooks( | ||
| 457 | + | ||
| 458 | + env->async_hooks()->SetJSPromiseHooks( | ||
| 459 | 459 | args[0]->IsFunction() ? args[0].As<Function>() : Local<Function>(), | |
| 460 | 460 | args[1]->IsFunction() ? args[1].As<Function>() : Local<Function>(), | |
| 461 | 461 | args[2]->IsFunction() ? args[2].As<Function>() : Local<Function>(), | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -95,6 +95,20 @@ v8::Local<v8::Object> AsyncHooks::native_execution_async_resource(size_t i) { | |||
| 95 | 95 | return PersistentToLocal::Strong(native_execution_async_resources_[i]); | |
| 96 | 96 | } | |
| 97 | 97 | ||
| 98 | + inline void AsyncHooks::SetJSPromiseHooks(v8::Local<v8::Function> init, | ||
| 99 | + v8::Local<v8::Function> before, | ||
| 100 | + v8::Local<v8::Function> after, | ||
| 101 | + v8::Local<v8::Function> resolve) { | ||
| 102 | + js_promise_hooks_[0].Reset(env()->isolate(), init); | ||
| 103 | + js_promise_hooks_[1].Reset(env()->isolate(), before); | ||
| 104 | + js_promise_hooks_[2].Reset(env()->isolate(), after); | ||
| 105 | + js_promise_hooks_[3].Reset(env()->isolate(), resolve); | ||
| 106 | + for (auto it = contexts_.begin(); it != contexts_.end(); it++) { | ||
| 107 | + PersistentToLocal::Weak(env()->isolate(), *it) | ||
| 108 | + ->SetPromiseHooks(init, before, after, resolve); | ||
| 109 | + } | ||
| 110 | + } | ||
| 111 | + | ||
| 98 | 112 | inline v8::Local<v8::String> AsyncHooks::provider_string(int idx) { | |
| 99 | 113 | return env()->isolate_data()->async_wrap_provider(idx); | |
| 100 | 114 | } | |
@@ -217,6 +231,41 @@ void AsyncHooks::clear_async_id_stack() { | |||
| 217 | 231 | fields_[kStackLength] = 0; | |
| 218 | 232 | } | |
| 219 | 233 | ||
| 234 | + inline void AsyncHooks::AddContext(v8::Local<v8::Context> ctx) { | ||
| 235 | + ctx->SetPromiseHooks( | ||
| 236 | + js_promise_hooks_[0].IsEmpty() ? | ||
| 237 | + v8::Local<v8::Function>() : | ||
| 238 | + PersistentToLocal::Strong(js_promise_hooks_[0]), | ||
| 239 | + js_promise_hooks_[1].IsEmpty() ? | ||
| 240 | + v8::Local<v8::Function>() : | ||
| 241 | + PersistentToLocal::Strong(js_promise_hooks_[1]), | ||
| 242 | + js_promise_hooks_[2].IsEmpty() ? | ||
| 243 | + v8::Local<v8::Function>() : | ||
| 244 | + PersistentToLocal::Strong(js_promise_hooks_[2]), | ||
| 245 | + js_promise_hooks_[3].IsEmpty() ? | ||
| 246 | + v8::Local<v8::Function>() : | ||
| 247 | + PersistentToLocal::Strong(js_promise_hooks_[3])); | ||
| 248 | + | ||
| 249 | + size_t id = contexts_.size(); | ||
| 250 | + contexts_.resize(id + 1); | ||
| 251 | + contexts_[id].Reset(env()->isolate(), ctx); | ||
| 252 | + contexts_[id].SetWeak(); | ||
| 253 | + } | ||
| 254 | + | ||
| 255 | + inline void AsyncHooks::RemoveContext(v8::Local<v8::Context> ctx) { | ||
| 256 | + v8::Isolate* isolate = env()->isolate(); | ||
| 257 | + v8::HandleScope handle_scope(isolate); | ||
| 258 | + for (auto it = contexts_.begin(); it != contexts_.end(); it++) { | ||
| 259 | + v8::Local<v8::Context> saved_context = | ||
| 260 | + PersistentToLocal::Weak(env()->isolate(), *it); | ||
| 261 | + if (saved_context == ctx) { | ||
| 262 | + it->Reset(); | ||
| 263 | + contexts_.erase(it); | ||
| 264 | + break; | ||
| 265 | + } | ||
| 266 | + } | ||
| 267 | + } | ||
| 268 | + | ||
| 220 | 269 | // The DefaultTriggerAsyncIdScope(AsyncWrap*) constructor is defined in | |
| 221 | 270 | // async_wrap-inl.h to avoid a circular dependency. | |
| 222 | 271 | ||
@@ -304,6 +353,8 @@ inline void Environment::AssignToContext(v8::Local<v8::Context> context, | |||
| 304 | 353 | #if HAVE_INSPECTOR | |
| 305 | 354 | inspector_agent()->ContextCreated(context, info); | |
| 306 | 355 | #endif // HAVE_INSPECTOR | |
| 356 | + | ||
| 357 | + this->async_hooks()->AddContext(context); | ||
| 307 | 358 | } | |
| 308 | 359 | ||
| 309 | 360 | inline Environment* Environment::GetCurrent(v8::Isolate* isolate) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1156,6 +1156,12 @@ AsyncHooks::SerializeInfo AsyncHooks::Serialize(Local<Context> context, | |||
| 1156 | 1156 | context, | |
| 1157 | 1157 | native_execution_async_resources_[i].Get(context->GetIsolate())); | |
| 1158 | 1158 | } | |
| 1159 | + CHECK_EQ(contexts_.size(), 1); | ||
| 1160 | + CHECK_EQ(contexts_[0], env()->context()); | ||
| 1161 | + CHECK(js_promise_hooks_[0].IsEmpty()); | ||
| 1162 | + CHECK(js_promise_hooks_[1].IsEmpty()); | ||
| 1163 | + CHECK(js_promise_hooks_[2].IsEmpty()); | ||
| 1164 | + CHECK(js_promise_hooks_[3].IsEmpty()); | ||
| 1159 | 1165 | ||
| 1160 | 1166 | return info; | |
| 1161 | 1167 | } | |
@@ -1164,6 +1170,7 @@ void AsyncHooks::MemoryInfo(MemoryTracker* tracker) const { | |||
| 1164 | 1170 | tracker->TrackField("async_ids_stack", async_ids_stack_); | |
| 1165 | 1171 | tracker->TrackField("fields", fields_); | |
| 1166 | 1172 | tracker->TrackField("async_id_fields", async_id_fields_); | |
| 1173 | + tracker->TrackField("js_promise_hooks", js_promise_hooks_); | ||
| 1167 | 1174 | } | |
| 1168 | 1175 | ||
| 1169 | 1176 | void AsyncHooks::grow_async_ids_stack() { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -701,6 +701,11 @@ class AsyncHooks : public MemoryRetainer { | |||
| 701 | 701 | // The `js_execution_async_resources` array contains the value in that case. | |
| 702 | 702 | inline v8::Local<v8::Object> native_execution_async_resource(size_t index); | |
| 703 | 703 | ||
| 704 | + inline void SetJSPromiseHooks(v8::Local<v8::Function> init, | ||
| 705 | + v8::Local<v8::Function> before, | ||
| 706 | + v8::Local<v8::Function> after, | ||
| 707 | + v8::Local<v8::Function> resolve); | ||
| 708 | + | ||
| 704 | 709 | inline v8::Local<v8::String> provider_string(int idx); | |
| 705 | 710 | ||
| 706 | 711 | inline void no_force_checks(); | |
@@ -711,6 +716,9 @@ class AsyncHooks : public MemoryRetainer { | |||
| 711 | 716 | inline bool pop_async_context(double async_id); | |
| 712 | 717 | inline void clear_async_id_stack(); // Used in fatal exceptions. | |
| 713 | 718 | ||
| 719 | + inline void AddContext(v8::Local<v8::Context> ctx); | ||
| 720 | + inline void RemoveContext(v8::Local<v8::Context> ctx); | ||
| 721 | + | ||
| 714 | 722 | AsyncHooks(const AsyncHooks&) = delete; | |
| 715 | 723 | AsyncHooks& operator=(const AsyncHooks&) = delete; | |
| 716 | 724 | AsyncHooks(AsyncHooks&&) = delete; | |
@@ -770,6 +778,10 @@ class AsyncHooks : public MemoryRetainer { | |||
| 770 | 778 | ||
| 771 | 779 | // Non-empty during deserialization | |
| 772 | 780 | const SerializeInfo* info_ = nullptr; | |
| 781 | + | ||
| 782 | + std::vector<v8::Global<v8::Context>> contexts_; | ||
| 783 | + | ||
| 784 | + std::array<v8::Global<v8::Function>, 4> js_promise_hooks_; | ||
| 773 | 785 | }; | |
| 774 | 786 | ||
| 775 | 787 | class ImmediateInfo : public MemoryRetainer { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -127,6 +127,11 @@ ContextifyContext::ContextifyContext( | |||
| 127 | 127 | ||
| 128 | 128 | ContextifyContext::~ContextifyContext() { | |
| 129 | 129 | env()->RemoveCleanupHook(CleanupHook, this); | |
| 130 | + Isolate* isolate = env()->isolate(); | ||
| 131 | + HandleScope scope(isolate); | ||
| 132 | + | ||
| 133 | + env()->async_hooks() | ||
| 134 | + ->RemoveContext(PersistentToLocal::Weak(isolate, context_)); | ||
| 130 | 135 | } | |
| 131 | 136 | ||
| 132 | 137 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,35 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + require('../common'); | ||
| 4 | + const assert = require('assert'); | ||
| 5 | + const vm = require('vm'); | ||
| 6 | + const { AsyncLocalStorage } = require('async_hooks'); | ||
| 7 | + | ||
| 8 | + // Regression test for https://github.com/nodejs/node/issues/38781 | ||
| 9 | + | ||
| 10 | + const context = vm.createContext({ | ||
| 11 | + AsyncLocalStorage, | ||
| 12 | + assert | ||
| 13 | + }); | ||
| 14 | + | ||
| 15 | + vm.runInContext(` | ||
| 16 | + const storage = new AsyncLocalStorage() | ||
| 17 | + async function test() { | ||
| 18 | + return storage.run({ test: 'vm' }, async () => { | ||
| 19 | + assert.strictEqual(storage.getStore().test, 'vm'); | ||
| 20 | + await 42; | ||
| 21 | + assert.strictEqual(storage.getStore().test, 'vm'); | ||
| 22 | + }); | ||
| 23 | + } | ||
| 24 | + test() | ||
| 25 | + `, context); | ||
| 26 | + | ||
| 27 | + const storage = new AsyncLocalStorage(); | ||
| 28 | + async function test() { | ||
| 29 | + return storage.run({ test: 'main context' }, async () => { | ||
| 30 | + assert.strictEqual(storage.getStore().test, 'main context'); | ||
| 31 | + await 42; | ||
| 32 | + assert.strictEqual(storage.getStore().test, 'main context'); | ||
| 33 | + }); | ||
| 34 | + } | ||
| 35 | + test(); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments