| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 7197fce commit f56c785
32 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -36,7 +36,7 @@ | |||
| 36 | 36 | ||
| 37 | 37 | # Reset this number to 0 on major V8 upgrades. | |
| 38 | 38 | # Increment by one for each non-official patch applied to deps/v8. | |
| 39 | - 'v8_embedder_string': '-node.8', | ||
| 39 | + 'v8_embedder_string': '-node.9', | ||
| 40 | 40 | ||
| 41 | 41 | ##### V8 defaults for Node.js ##### | |
| 42 | 42 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -211,6 +211,7 @@ Seo Sanghyeon <sanxiyn@gmail.com> | |||
| 211 | 211 | Shawn Anastasio <shawnanastasio@gmail.com> | |
| 212 | 212 | Shawn Presser <shawnpresser@gmail.com> | |
| 213 | 213 | Stefan Penner <stefan.penner@gmail.com> | |
| 214 | + Stephen Belanger <stephen.belanger@datadoghq.com> | ||
| 214 | 215 | Sylvestre Ledru <sledru@mozilla.com> | |
| 215 | 216 | Taketoshi Aono <brn@b6n.ch> | |
| 216 | 217 | Tao Liqiang <taolq@outlook.com> | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -10585,6 +10585,18 @@ class V8_EXPORT Context : public Data { | |||
| 10585 | 10585 | */ | |
| 10586 | 10586 | void SetContinuationPreservedEmbedderData(Local<Value> context); | |
| 10587 | 10587 | ||
| 10588 | + /** | ||
| 10589 | + * Set or clear hooks to be invoked for promise lifecycle operations. | ||
| 10590 | + * To clear a hook, set it to an empty v8::Function. Each function will | ||
| 10591 | + * receive the observed promise as the first argument. If a chaining | ||
| 10592 | + * operation is used on a promise, the init will additionally receive | ||
| 10593 | + * the parent promise as the second argument. | ||
| 10594 | + */ | ||
| 10595 | + void SetPromiseHooks(Local<Function> init_hook, | ||
| 10596 | + Local<Function> before_hook, | ||
| 10597 | + Local<Function> after_hook, | ||
| 10598 | + Local<Function> resolve_hook); | ||
| 10599 | + | ||
| 10588 | 10600 | /** | |
| 10589 | 10601 | * Stack-allocated class which sets the execution context for all | |
| 10590 | 10602 | * operations executed within a local scope. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6220,6 +6220,45 @@ void Context::SetContinuationPreservedEmbedderData(Local<Value> data) { | |||
| 6220 | 6220 | *i::Handle<i::HeapObject>::cast(Utils::OpenHandle(*data))); | |
| 6221 | 6221 | } | |
| 6222 | 6222 | ||
| 6223 | + void v8::Context::SetPromiseHooks(Local<Function> init_hook, | ||
| 6224 | + Local<Function> before_hook, | ||
| 6225 | + Local<Function> after_hook, | ||
| 6226 | + Local<Function> resolve_hook) { | ||
| 6227 | + i::Handle<i::Context> context = Utils::OpenHandle(this); | ||
| 6228 | + i::Isolate* isolate = context->GetIsolate(); | ||
| 6229 | + | ||
| 6230 | + i::Handle<i::Object> init = isolate->factory()->undefined_value(); | ||
| 6231 | + i::Handle<i::Object> before = isolate->factory()->undefined_value(); | ||
| 6232 | + i::Handle<i::Object> after = isolate->factory()->undefined_value(); | ||
| 6233 | + i::Handle<i::Object> resolve = isolate->factory()->undefined_value(); | ||
| 6234 | + | ||
| 6235 | + bool has_hook = false; | ||
| 6236 | + | ||
| 6237 | + if (!init_hook.IsEmpty()) { | ||
| 6238 | + init = Utils::OpenHandle(*init_hook); | ||
| 6239 | + has_hook = true; | ||
| 6240 | + } | ||
| 6241 | + if (!before_hook.IsEmpty()) { | ||
| 6242 | + before = Utils::OpenHandle(*before_hook); | ||
| 6243 | + has_hook = true; | ||
| 6244 | + } | ||
| 6245 | + if (!after_hook.IsEmpty()) { | ||
| 6246 | + after = Utils::OpenHandle(*after_hook); | ||
| 6247 | + has_hook = true; | ||
| 6248 | + } | ||
| 6249 | + if (!resolve_hook.IsEmpty()) { | ||
| 6250 | + resolve = Utils::OpenHandle(*resolve_hook); | ||
| 6251 | + has_hook = true; | ||
| 6252 | + } | ||
| 6253 | + | ||
| 6254 | + isolate->SetHasContextPromiseHooks(has_hook); | ||
| 6255 | + | ||
| 6256 | + context->native_context().set_promise_hook_init_function(*init); | ||
| 6257 | + context->native_context().set_promise_hook_before_function(*before); | ||
| 6258 | + context->native_context().set_promise_hook_after_function(*after); | ||
| 6259 | + context->native_context().set_promise_hook_resolve_function(*resolve); | ||
| 6260 | + } | ||
| 6261 | + | ||
| 6223 | 6262 | MaybeLocal<Context> metrics::Recorder::GetContext( | |
| 6224 | 6263 | Isolate* isolate, metrics::Recorder::ContextId id) { | |
| 6225 | 6264 | i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -157,12 +157,14 @@ TF_BUILTIN(AsyncFunctionEnter, AsyncFunctionBuiltinsAssembler) { | |||
| 157 | 157 | StoreObjectFieldNoWriteBarrier( | |
| 158 | 158 | async_function_object, JSAsyncFunctionObject::kPromiseOffset, promise); | |
| 159 | 159 | ||
| 160 | + RunContextPromiseHookInit(context, promise, UndefinedConstant()); | ||
| 161 | + | ||
| 160 | 162 | // Fire promise hooks if enabled and push the Promise under construction | |
| 161 | 163 | // in an async function on the catch prediction stack to handle exceptions | |
| 162 | 164 | // thrown before the first await. | |
| 163 | 165 | Label if_instrumentation(this, Label::kDeferred), | |
| 164 | 166 | if_instrumentation_done(this); | |
| 165 | - Branch(IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(), | ||
| 167 | + Branch(IsIsolatePromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(), | ||
| 166 | 168 | &if_instrumentation, &if_instrumentation_done); | |
| 167 | 169 | BIND(&if_instrumentation); | |
| 168 | 170 | { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -97,18 +97,11 @@ TNode<Object> AsyncBuiltinsAssembler::AwaitOld( | |||
| 97 | 97 | ||
| 98 | 98 | TVARIABLE(HeapObject, var_throwaway, UndefinedConstant()); | |
| 99 | 99 | ||
| 100 | - // Deal with PromiseHooks and debug support in the runtime. This | ||
| 101 | - // also allocates the throwaway promise, which is only needed in | ||
| 102 | - // case of PromiseHooks or debugging. | ||
| 103 | - Label if_debugging(this, Label::kDeferred), do_resolve_promise(this); | ||
| 104 | - Branch(IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(), | ||
| 105 | - &if_debugging, &do_resolve_promise); | ||
| 106 | - BIND(&if_debugging); | ||
| 107 | - var_throwaway = | ||
| 108 | - CAST(CallRuntime(Runtime::kAwaitPromisesInitOld, context, value, promise, | ||
| 109 | - outer_promise, on_reject, is_predicted_as_caught)); | ||
| 110 | - Goto(&do_resolve_promise); | ||
| 111 | - BIND(&do_resolve_promise); | ||
| 100 | + RunContextPromiseHookInit(context, promise, outer_promise); | ||
| 101 | + | ||
| 102 | + InitAwaitPromise(Runtime::kAwaitPromisesInitOld, context, value, promise, | ||
| 103 | + outer_promise, on_reject, is_predicted_as_caught, | ||
| 104 | + &var_throwaway); | ||
| 112 | 105 | ||
| 113 | 106 | // Perform ! Call(promiseCapability.[[Resolve]], undefined, « promise »). | |
| 114 | 107 | CallBuiltin(Builtins::kResolvePromise, context, promise, value); | |
@@ -168,21 +161,46 @@ TNode<Object> AsyncBuiltinsAssembler::AwaitOptimized( | |||
| 168 | 161 | ||
| 169 | 162 | TVARIABLE(HeapObject, var_throwaway, UndefinedConstant()); | |
| 170 | 163 | ||
| 164 | + InitAwaitPromise(Runtime::kAwaitPromisesInit, context, promise, promise, | ||
| 165 | + outer_promise, on_reject, is_predicted_as_caught, | ||
| 166 | + &var_throwaway); | ||
| 167 | + | ||
| 168 | + return CallBuiltin(Builtins::kPerformPromiseThen, native_context, promise, | ||
| 169 | + on_resolve, on_reject, var_throwaway.value()); | ||
| 170 | + } | ||
| 171 | + | ||
| 172 | + void AsyncBuiltinsAssembler::InitAwaitPromise( | ||
| 173 | + Runtime::FunctionId id, TNode<Context> context, TNode<Object> value, | ||
| 174 | + TNode<Object> promise, TNode<Object> outer_promise, | ||
| 175 | + TNode<HeapObject> on_reject, TNode<Oddball> is_predicted_as_caught, | ||
| 176 | + TVariable<HeapObject>* var_throwaway) { | ||
| 171 | 177 | // Deal with PromiseHooks and debug support in the runtime. This | |
| 172 | 178 | // also allocates the throwaway promise, which is only needed in | |
| 173 | 179 | // case of PromiseHooks or debugging. | |
| 174 | - Label if_debugging(this, Label::kDeferred), do_perform_promise_then(this); | ||
| 175 | - Branch(IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(), | ||
| 176 | - &if_debugging, &do_perform_promise_then); | ||
| 180 | + Label if_debugging(this, Label::kDeferred), | ||
| 181 | + if_promise_hook(this, Label::kDeferred), | ||
| 182 | + not_debugging(this), | ||
| 183 | + do_nothing(this); | ||
| 184 | + TNode<Uint32T> promiseHookFlags = PromiseHookFlags(); | ||
| 185 | + Branch(IsIsolatePromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate( | ||
| 186 | + promiseHookFlags), &if_debugging, ¬_debugging); | ||
| 177 | 187 | BIND(&if_debugging); | |
| 178 | - var_throwaway = | ||
| 179 | - CAST(CallRuntime(Runtime::kAwaitPromisesInit, context, promise, promise, | ||
| 188 | + *var_throwaway = | ||
| 189 | + CAST(CallRuntime(id, context, value, promise, | ||
| 180 | 190 | outer_promise, on_reject, is_predicted_as_caught)); | |
| 181 | - Goto(&do_perform_promise_then); | ||
| 182 | - BIND(&do_perform_promise_then); | ||
| 183 | - | ||
| 184 | - return CallBuiltin(Builtins::kPerformPromiseThen, native_context, promise, | ||
| 185 | - on_resolve, on_reject, var_throwaway.value()); | ||
| 191 | + Goto(&do_nothing); | ||
| 192 | + BIND(¬_debugging); | ||
| 193 | + | ||
| 194 | + // This call to NewJSPromise is to keep behaviour parity with what happens | ||
| 195 | + // in Runtime::kAwaitPromisesInit above if native hooks are set. It will | ||
| 196 | + // create a throwaway promise that will trigger an init event and will get | ||
| 197 | + // passed into Builtins::kPerformPromiseThen below. | ||
| 198 | + Branch(IsContextPromiseHookEnabled(promiseHookFlags), &if_promise_hook, | ||
| 199 | + &do_nothing); | ||
| 200 | + BIND(&if_promise_hook); | ||
| 201 | + *var_throwaway = NewJSPromise(context, promise); | ||
| 202 | + Goto(&do_nothing); | ||
| 203 | + BIND(&do_nothing); | ||
| 186 | 204 | } | |
| 187 | 205 | ||
| 188 | 206 | TNode<Object> AsyncBuiltinsAssembler::Await( | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -62,6 +62,12 @@ class AsyncBuiltinsAssembler : public PromiseBuiltinsAssembler { | |||
| 62 | 62 | TNode<SharedFunctionInfo> on_resolve_sfi, | |
| 63 | 63 | TNode<SharedFunctionInfo> on_reject_sfi, | |
| 64 | 64 | TNode<Oddball> is_predicted_as_caught); | |
| 65 | + | ||
| 66 | + void InitAwaitPromise( | ||
| 67 | + Runtime::FunctionId id, TNode<Context> context, TNode<Object> value, | ||
| 68 | + TNode<Object> promise, TNode<Object> outer_promise, | ||
| 69 | + TNode<HeapObject> on_reject, TNode<Oddball> is_predicted_as_caught, | ||
| 70 | + TVariable<HeapObject>* var_throwaway); | ||
| 65 | 71 | }; | |
| 66 | 72 | ||
| 67 | 73 | } // namespace internal | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -518,7 +518,7 @@ TF_BUILTIN(AsyncGeneratorResolve, AsyncGeneratorBuiltinsAssembler) { | |||
| 518 | 518 | // the "promiseResolve" hook would not be fired otherwise. | |
| 519 | 519 | Label if_fast(this), if_slow(this, Label::kDeferred), return_promise(this); | |
| 520 | 520 | GotoIfForceSlowPath(&if_slow); | |
| 521 | - GotoIf(IsPromiseHookEnabled(), &if_slow); | ||
| 521 | + GotoIf(IsIsolatePromiseHookEnabledOrHasAsyncEventDelegate(), &if_slow); | ||
| 522 | 522 | Branch(IsPromiseThenProtectorCellInvalid(), &if_slow, &if_fast); | |
| 523 | 523 | ||
| 524 | 524 | BIND(&if_fast); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -46,8 +46,11 @@ class MicrotaskQueueBuiltinsAssembler : public CodeStubAssembler { | |||
| 46 | 46 | void EnterMicrotaskContext(TNode<Context> native_context); | |
| 47 | 47 | void RewindEnteredContext(TNode<IntPtrT> saved_entered_context_count); | |
| 48 | 48 | ||
| 49 | + void RunAllPromiseHooks(PromiseHookType type, TNode<Context> context, | ||
| 50 | + TNode<HeapObject> promise_or_capability); | ||
| 49 | 51 | void RunPromiseHook(Runtime::FunctionId id, TNode<Context> context, | |
| 50 | - TNode<HeapObject> promise_or_capability); | ||
| 52 | + TNode<HeapObject> promise_or_capability, | ||
| 53 | + TNode<Uint32T> promiseHookFlags); | ||
| 51 | 54 | }; | |
| 52 | 55 | ||
| 53 | 56 | TNode<RawPtrT> MicrotaskQueueBuiltinsAssembler::GetMicrotaskQueue( | |
@@ -199,7 +202,7 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( | |||
| 199 | 202 | const TNode<Object> thenable = LoadObjectField( | |
| 200 | 203 | microtask, PromiseResolveThenableJobTask::kThenableOffset); | |
| 201 | 204 | ||
| 202 | - RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context, | ||
| 205 | + RunAllPromiseHooks(PromiseHookType::kBefore, microtask_context, | ||
| 203 | 206 | CAST(promise_to_resolve)); | |
| 204 | 207 | ||
| 205 | 208 | { | |
@@ -208,7 +211,7 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( | |||
| 208 | 211 | promise_to_resolve, thenable, then); | |
| 209 | 212 | } | |
| 210 | 213 | ||
| 211 | - RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context, | ||
| 214 | + RunAllPromiseHooks(PromiseHookType::kAfter, microtask_context, | ||
| 212 | 215 | CAST(promise_to_resolve)); | |
| 213 | 216 | ||
| 214 | 217 | RewindEnteredContext(saved_entered_context_count); | |
@@ -243,8 +246,8 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( | |||
| 243 | 246 | BIND(&preserved_data_done); | |
| 244 | 247 | ||
| 245 | 248 | // Run the promise before/debug hook if enabled. | |
| 246 | - RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context, | ||
| 247 | - promise_or_capability); | ||
| 249 | + RunAllPromiseHooks(PromiseHookType::kBefore, microtask_context, | ||
| 250 | + promise_or_capability); | ||
| 248 | 251 | ||
| 249 | 252 | { | |
| 250 | 253 | ScopedExceptionHandler handler(this, &if_exception, &var_exception); | |
@@ -253,8 +256,8 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( | |||
| 253 | 256 | } | |
| 254 | 257 | ||
| 255 | 258 | // Run the promise after/debug hook if enabled. | |
| 256 | - RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context, | ||
| 257 | - promise_or_capability); | ||
| 259 | + RunAllPromiseHooks(PromiseHookType::kAfter, microtask_context, | ||
| 260 | + promise_or_capability); | ||
| 258 | 261 | ||
| 259 | 262 | Label preserved_data_reset_done(this); | |
| 260 | 263 | GotoIf(IsUndefined(preserved_embedder_data), &preserved_data_reset_done); | |
@@ -296,8 +299,8 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( | |||
| 296 | 299 | BIND(&preserved_data_done); | |
| 297 | 300 | ||
| 298 | 301 | // Run the promise before/debug hook if enabled. | |
| 299 | - RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context, | ||
| 300 | - promise_or_capability); | ||
| 302 | + RunAllPromiseHooks(PromiseHookType::kBefore, microtask_context, | ||
| 303 | + promise_or_capability); | ||
| 301 | 304 | ||
| 302 | 305 | { | |
| 303 | 306 | ScopedExceptionHandler handler(this, &if_exception, &var_exception); | |
@@ -306,8 +309,8 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( | |||
| 306 | 309 | } | |
| 307 | 310 | ||
| 308 | 311 | // Run the promise after/debug hook if enabled. | |
| 309 | - RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context, | ||
| 310 | - promise_or_capability); | ||
| 312 | + RunAllPromiseHooks(PromiseHookType::kAfter, microtask_context, | ||
| 313 | + promise_or_capability); | ||
| 311 | 314 | ||
| 312 | 315 | Label preserved_data_reset_done(this); | |
| 313 | 316 | GotoIf(IsUndefined(preserved_embedder_data), &preserved_data_reset_done); | |
@@ -465,12 +468,43 @@ void MicrotaskQueueBuiltinsAssembler::RewindEnteredContext( | |||
| 465 | 468 | saved_entered_context_count); | |
| 466 | 469 | } | |
| 467 | 470 | ||
| 471 | + void MicrotaskQueueBuiltinsAssembler::RunAllPromiseHooks( | ||
| 472 | + PromiseHookType type, TNode<Context> context, | ||
| 473 | + TNode<HeapObject> promise_or_capability) { | ||
| 474 | + Label hook(this, Label::kDeferred), done_hook(this); | ||
| 475 | + TNode<Uint32T> promiseHookFlags = PromiseHookFlags(); | ||
| 476 | + Branch(IsAnyPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate( | ||
| 477 | + promiseHookFlags), &hook, &done_hook); | ||
| 478 | + BIND(&hook); | ||
| 479 | + { | ||
| 480 | + switch (type) { | ||
| 481 | + case PromiseHookType::kBefore: | ||
| 482 | + RunContextPromiseHookBefore(context, promise_or_capability, | ||
| 483 | + promiseHookFlags); | ||
| 484 | + RunPromiseHook(Runtime::kPromiseHookBefore, context, | ||
| 485 | + promise_or_capability, promiseHookFlags); | ||
| 486 | + break; | ||
| 487 | + case PromiseHookType::kAfter: | ||
| 488 | + RunContextPromiseHookAfter(context, promise_or_capability, | ||
| 489 | + promiseHookFlags); | ||
| 490 | + RunPromiseHook(Runtime::kPromiseHookAfter, context, | ||
| 491 | + promise_or_capability, promiseHookFlags); | ||
| 492 | + break; | ||
| 493 | + default: | ||
| 494 | + UNREACHABLE(); | ||
| 495 | + } | ||
| 496 | + Goto(&done_hook); | ||
| 497 | + } | ||
| 498 | + BIND(&done_hook); | ||
| 499 | + } | ||
| 500 | + | ||
| 468 | 501 | void MicrotaskQueueBuiltinsAssembler::RunPromiseHook( | |
| 469 | 502 | Runtime::FunctionId id, TNode<Context> context, | |
| 470 | - TNode<HeapObject> promise_or_capability) { | ||
| 503 | + TNode<HeapObject> promise_or_capability, | ||
| 504 | + TNode<Uint32T> promiseHookFlags) { | ||
| 471 | 505 | Label hook(this, Label::kDeferred), done_hook(this); | |
| 472 | - Branch(IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(), &hook, | ||
| 473 | - &done_hook); | ||
| 506 | + Branch(IsIsolatePromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate( | ||
| 507 | + promiseHookFlags), &hook, &done_hook); | ||
| 474 | 508 | BIND(&hook); | |
| 475 | 509 | { | |
| 476 | 510 | // Get to the underlying JSPromise instance. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -386,6 +386,12 @@ Cast<Undefined|Callable>(o: HeapObject): Undefined|Callable | |||
| 386 | 386 | return HeapObjectToCallable(o) otherwise CastError; | |
| 387 | 387 | } | |
| 388 | 388 | ||
| 389 | + Cast<Undefined|JSFunction>(o: HeapObject): Undefined|JSFunction | ||
| 390 | + labels CastError { | ||
| 391 | + if (o == Undefined) return Undefined; | ||
| 392 | + return Cast<JSFunction>(o) otherwise CastError; | ||
| 393 | + } | ||
| 394 | + | ||
| 389 | 395 | macro Cast<T : type extends Symbol>(o: Symbol): T labels CastError; | |
| 390 | 396 | Cast<PublicSymbol>(s: Symbol): PublicSymbol labels CastError { | |
| 391 | 397 | if (s.flags.is_private) goto CastError; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments