| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 129a1d6 commit be2a5e1
7 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -48,17 +48,26 @@ InternalCallbackScope::InternalCallbackScope(AsyncWrap* async_wrap, int flags) | |||
| 48 | 48 | flags, | |
| 49 | 49 | async_wrap->context_frame()) {} | |
| 50 | 50 | ||
| 51 | - InternalCallbackScope::InternalCallbackScope(Environment* env, | ||
| 52 | - Local<Object> object, | ||
| 53 | - const async_context& asyncContext, | ||
| 54 | - int flags, | ||
| 55 | - Local<Value> context_frame) | ||
| 51 | + InternalCallbackScope::InternalCallbackScope( | ||
| 52 | + Environment* env, | ||
| 53 | + std::variant<Local<Object>, Local<Object>*> object, | ||
| 54 | + const async_context& asyncContext, | ||
| 55 | + int flags, | ||
| 56 | + Local<Value> context_frame) | ||
| 56 | 57 | : env_(env), | |
| 57 | 58 | async_context_(asyncContext), | |
| 58 | - object_(object), | ||
| 59 | 59 | skip_hooks_(flags & kSkipAsyncHooks), | |
| 60 | 60 | skip_task_queues_(flags & kSkipTaskQueues) { | |
| 61 | 61 | CHECK_NOT_NULL(env); | |
| 62 | + | ||
| 63 | + if (std::holds_alternative<Local<Object>>(object)) { | ||
| 64 | + object_storage_ = std::get<Local<Object>>(object); | ||
| 65 | + object_ = &object_storage_; | ||
| 66 | + } else { | ||
| 67 | + object_ = std::get<Local<Object>*>(object); | ||
| 68 | + CHECK_NOT_NULL(object_); | ||
| 69 | + } | ||
| 70 | + | ||
| 62 | 71 | env->PushAsyncCallbackScope(); | |
| 63 | 72 | ||
| 64 | 73 | if (!env->can_call_into_js()) { | |
@@ -85,7 +94,7 @@ InternalCallbackScope::InternalCallbackScope(Environment* env, | |||
| 85 | 94 | isolate, async_context_frame::exchange(isolate, context_frame)); | |
| 86 | 95 | ||
| 87 | 96 | env->async_hooks()->push_async_context( | |
| 88 | - async_context_.async_id, async_context_.trigger_async_id, object); | ||
| 97 | + async_context_.async_id, async_context_.trigger_async_id, object_); | ||
| 89 | 98 | ||
| 90 | 99 | pushed_ids_ = true; | |
| 91 | 100 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -278,7 +278,7 @@ void AsyncWrap::PushAsyncContext(const FunctionCallbackInfo<Value>& args) { | |||
| 278 | 278 | // then the checks in push_async_ids() and pop_async_id() will. | |
| 279 | 279 | double async_id = args[0]->NumberValue(env->context()).FromJust(); | |
| 280 | 280 | double trigger_async_id = args[1]->NumberValue(env->context()).FromJust(); | |
| 281 | - env->async_hooks()->push_async_context(async_id, trigger_async_id, {}); | ||
| 281 | + env->async_hooks()->push_async_context(async_id, trigger_async_id, nullptr); | ||
| 282 | 282 | } | |
| 283 | 283 | ||
| 284 | 284 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -141,8 +141,10 @@ v8::Local<v8::Array> AsyncHooks::js_execution_async_resources() { | |||
| 141 | 141 | } | |
| 142 | 142 | ||
| 143 | 143 | v8::Local<v8::Object> AsyncHooks::native_execution_async_resource(size_t i) { | |
| 144 | - if (i >= native_execution_async_resources_.size()) return {}; | ||
| 145 | - return native_execution_async_resources_[i]; | ||
| 144 | + if (i >= native_execution_async_resources_.size() || | ||
| 145 | + native_execution_async_resources_[i] == nullptr) | ||
| 146 | + return {}; | ||
| 147 | + return *native_execution_async_resources_[i]; | ||
| 146 | 148 | } | |
| 147 | 149 | ||
| 148 | 150 | inline v8::Local<v8::String> AsyncHooks::provider_string(int idx) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -120,7 +120,8 @@ void Environment::ResetPromiseHooks(Local<Function> init, | |||
| 120 | 120 | // Remember to keep this code aligned with pushAsyncContext() in JS. | |
| 121 | 121 | void AsyncHooks::push_async_context(double async_id, | |
| 122 | 122 | double trigger_async_id, | |
| 123 | - Local<Object> resource) { | ||
| 123 | + Local<Object>* resource) { | ||
| 124 | + CHECK_IMPLIES(resource != nullptr, !resource->IsEmpty()); | ||
| 124 | 125 | // Since async_hooks is experimental, do only perform the check | |
| 125 | 126 | // when async_hooks is enabled. | |
| 126 | 127 | if (fields_[kCheck] > 0) { | |
@@ -138,14 +139,14 @@ void AsyncHooks::push_async_context(double async_id, | |||
| 138 | 139 | ||
| 139 | 140 | #ifdef DEBUG | |
| 140 | 141 | for (uint32_t i = offset; i < native_execution_async_resources_.size(); i++) | |
| 141 | - CHECK(native_execution_async_resources_[i].IsEmpty()); | ||
| 142 | + CHECK_NULL(native_execution_async_resources_[i]); | ||
| 142 | 143 | #endif | |
| 143 | 144 | ||
| 144 | 145 | // When this call comes from JS (as a way of increasing the stack size), | |
| 145 | 146 | // `resource` will be empty, because JS caches these values anyway. | |
| 146 | - if (!resource.IsEmpty()) { | ||
| 147 | + if (resource != nullptr) { | ||
| 147 | 148 | native_execution_async_resources_.resize(offset + 1); | |
| 148 | - // Caveat: This is a v8::Local<> assignment, we do not keep a v8::Global<>! | ||
| 149 | + // Caveat: This is a v8::Local<>* assignment, we do not keep a v8::Global<>! | ||
| 149 | 150 | native_execution_async_resources_[offset] = resource; | |
| 150 | 151 | } | |
| 151 | 152 | } | |
@@ -170,11 +171,11 @@ bool AsyncHooks::pop_async_context(double async_id) { | |||
| 170 | 171 | fields_[kStackLength] = offset; | |
| 171 | 172 | ||
| 172 | 173 | if (offset < native_execution_async_resources_.size() && | |
| 173 | - !native_execution_async_resources_[offset].IsEmpty()) [[likely]] { | ||
| 174 | + native_execution_async_resources_[offset] != nullptr) [[likely]] { | ||
| 174 | 175 | #ifdef DEBUG | |
| 175 | 176 | for (uint32_t i = offset + 1; i < native_execution_async_resources_.size(); | |
| 176 | 177 | i++) { | |
| 177 | - CHECK(native_execution_async_resources_[i].IsEmpty()); | ||
| 178 | + CHECK_NULL(native_execution_async_resources_[i]); | ||
| 178 | 179 | } | |
| 179 | 180 | #endif | |
| 180 | 181 | native_execution_async_resources_.resize(offset); | |
@@ -1740,7 +1741,6 @@ AsyncHooks::AsyncHooks(Isolate* isolate, const SerializeInfo* info) | |||
| 1740 | 1741 | fields_(isolate, kFieldsCount, MAYBE_FIELD_PTR(info, fields)), | |
| 1741 | 1742 | async_id_fields_( | |
| 1742 | 1743 | isolate, kUidFieldsCount, MAYBE_FIELD_PTR(info, async_id_fields)), | |
| 1743 | - native_execution_async_resources_(isolate), | ||
| 1744 | 1744 | info_(info) { | |
| 1745 | 1745 | HandleScope handle_scope(isolate); | |
| 1746 | 1746 | if (info == nullptr) { | |
@@ -1829,10 +1829,9 @@ AsyncHooks::SerializeInfo AsyncHooks::Serialize(Local<Context> context, | |||
| 1829 | 1829 | native_execution_async_resources_.size()); | |
| 1830 | 1830 | for (size_t i = 0; i < native_execution_async_resources_.size(); i++) { | |
| 1831 | 1831 | info.native_execution_async_resources[i] = | |
| 1832 | - native_execution_async_resources_[i].IsEmpty() ? SIZE_MAX : | ||
| 1833 | - creator->AddData( | ||
| 1834 | - context, | ||
| 1835 | - native_execution_async_resources_[i]); | ||
| 1832 | + native_execution_async_resources_[i] == nullptr | ||
| 1833 | + ? SIZE_MAX | ||
| 1834 | + : creator->AddData(context, *native_execution_async_resources_[i]); | ||
| 1836 | 1835 | } | |
| 1837 | 1836 | ||
| 1838 | 1837 | // At the moment, promise hooks are not supported in the startup snapshot. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -58,6 +58,7 @@ | |||
| 58 | 58 | #include <array> | |
| 59 | 59 | #include <atomic> | |
| 60 | 60 | #include <cstdint> | |
| 61 | + #include <deque> | ||
| 61 | 62 | #include <functional> | |
| 62 | 63 | #include <list> | |
| 63 | 64 | #include <memory> | |
@@ -345,7 +346,7 @@ class AsyncHooks : public MemoryRetainer { | |||
| 345 | 346 | // `pop_async_context()` or `clear_async_id_stack()` are called. | |
| 346 | 347 | void push_async_context(double async_id, | |
| 347 | 348 | double trigger_async_id, | |
| 348 | - v8::Local<v8::Object> execution_async_resource); | ||
| 349 | + v8::Local<v8::Object>* execution_async_resource); | ||
| 349 | 350 | bool pop_async_context(double async_id); | |
| 350 | 351 | void clear_async_id_stack(); // Used in fatal exceptions. | |
| 351 | 352 | ||
@@ -407,15 +408,9 @@ class AsyncHooks : public MemoryRetainer { | |||
| 407 | 408 | ||
| 408 | 409 | v8::Global<v8::Array> js_execution_async_resources_; | |
| 409 | 410 | ||
| 410 | - // TODO(@jasnell): Note that this is technically illegal use of | ||
| 411 | - // v8::Locals which should be kept on the stack. Here, the entries | ||
| 412 | - // in this object grows and shrinks with the C stack, and entries | ||
| 413 | - // will be in the right handle scopes, but v8::Locals are supposed | ||
| 414 | - // to remain on the stack and not the heap. For general purposes | ||
| 415 | - // this *should* be ok but may need to be looked at further should | ||
| 416 | - // v8 become stricter in the future about v8::Locals being held in | ||
| 417 | - // the stack. | ||
| 418 | - v8::LocalVector<v8::Object> native_execution_async_resources_; | ||
| 411 | + // We avoid storing the handles directly here, because they are already | ||
| 412 | + // properly allocated on the stack, we just need access to them here. | ||
| 413 | + std::deque<v8::Local<v8::Object>*> native_execution_async_resources_; | ||
| 419 | 414 | ||
| 420 | 415 | // Non-empty during deserialization | |
| 421 | 416 | const SerializeInfo* info_ = nullptr; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -37,6 +37,7 @@ | |||
| 37 | 37 | #include <cstdlib> | |
| 38 | 38 | ||
| 39 | 39 | #include <string> | |
| 40 | + #include <variant> | ||
| 40 | 41 | #include <vector> | |
| 41 | 42 | ||
| 42 | 43 | struct sockaddr; | |
@@ -245,9 +246,14 @@ class InternalCallbackScope { | |||
| 245 | 246 | // compatibility issues, but it shouldn't.) | |
| 246 | 247 | kSkipTaskQueues = 2 | |
| 247 | 248 | }; | |
| 249 | + // You need to either guarantee that this `InternalCallbackScope` is | ||
| 250 | + // stack-allocated itself, OR that `object` is a pointer to a stack-allocated | ||
| 251 | + // `v8::Local<v8::Object>` which outlives this scope (e.g. for the | ||
| 252 | + // public `CallbackScope` which indirectly allocates an instance of | ||
| 253 | + // this class for ABI stability purposes). | ||
| 248 | 254 | InternalCallbackScope( | |
| 249 | 255 | Environment* env, | |
| 250 | - v8::Local<v8::Object> object, | ||
| 256 | + std::variant<v8::Local<v8::Object>, v8::Local<v8::Object>*> object, | ||
| 251 | 257 | const async_context& asyncContext, | |
| 252 | 258 | int flags = kNoFlags, | |
| 253 | 259 | v8::Local<v8::Value> context_frame = v8::Local<v8::Value>()); | |
@@ -263,7 +269,8 @@ class InternalCallbackScope { | |||
| 263 | 269 | private: | |
| 264 | 270 | Environment* env_; | |
| 265 | 271 | async_context async_context_; | |
| 266 | - v8::Local<v8::Object> object_; | ||
| 272 | + v8::Local<v8::Object> object_storage_; | ||
| 273 | + v8::Local<v8::Object>* object_; | ||
| 267 | 274 | bool skip_hooks_; | |
| 268 | 275 | bool skip_task_queues_; | |
| 269 | 276 | bool failed_ = false; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -100,10 +100,11 @@ void PromiseRejectCallback(PromiseRejectMessage message) { | |||
| 100 | 100 | if (!GetAssignedPromiseAsyncId(env, promise, env->trigger_async_id_symbol()) | |
| 101 | 101 | .To(&trigger_async_id)) return; | |
| 102 | 102 | ||
| 103 | + Local<Object> promise_as_obj = promise; | ||
| 103 | 104 | if (async_id != AsyncWrap::kInvalidAsyncId && | |
| 104 | 105 | trigger_async_id != AsyncWrap::kInvalidAsyncId) { | |
| 105 | 106 | env->async_hooks()->push_async_context( | |
| 106 | - async_id, trigger_async_id, promise); | ||
| 107 | + async_id, trigger_async_id, &promise_as_obj); | ||
| 107 | 108 | } | |
| 108 | 109 | ||
| 109 | 110 | USE(callback->Call( | |
| Back | FazBrowse Home | New Git URL |
0 commit comments