GeezerVison is showing github.com — deps: V8: backport da20a197a7f9 · nodejs/node@879fdc4
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: common.gypi +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
| 41 | 41 |
| 42 | 42 | # Reset this number to 0 on major V8 upgrades. | 43 | 43 | # Increment by one for each non-official patch applied to deps/v8. | 44 | | - 'v8_embedder_string': '-node.23', | | 44 | + 'v8_embedder_string': '-node.24', | 45 | 45 |
| 46 | 46 | ##### V8 defaults for Node.js ##### | 47 | 47 |
| |
Collapse file Copy file name to clipboardExpand all lines: deps/v8/src/builtins/builtins-promise.h +3-5Lines changed: 3 additions & 5 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -13,11 +13,9 @@ namespace internal { | 13 | 13 | class PromiseBuiltins { | 14 | 14 | public: | 15 | 15 | enum PromiseResolvingFunctionContextSlot { | 16 | | - // The promise which resolve/reject callbacks fulfill. | 17 | | - kPromiseSlot = Context::MIN_CONTEXT_SLOTS, | 18 | | - | 19 | | - // Whether the callback was already invoked. | 20 | | - kAlreadyResolvedSlot, | | 16 | + // The promise which resolve/reject callbacks fulfill, or Undefined | | 17 | + // if already resolved. | | 18 | + kPromiseIfNotResolvedSlot = Context::MIN_CONTEXT_SLOTS, | 21 | 19 |
| 22 | 20 | // Whether to trigger a debug event or not. Used in catch | 23 | 21 | // prediction. | |
Collapse file Copy file name to clipboardExpand all lines: deps/v8/src/builtins/promise-abstract-operations.tq +38-31Lines changed: 38 additions & 31 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -265,8 +265,8 @@ const kPromiseCapabilitySize: | 265 | 265 | type PromiseResolvingFunctionContext extends FunctionContext; | 266 | 266 | extern enum PromiseResolvingFunctionContextSlot extends intptr | 267 | 267 | constexpr 'PromiseBuiltins::PromiseResolvingFunctionContextSlot' { | 268 | | - kPromiseSlot: Slot<PromiseResolvingFunctionContext, JSPromise>, | 269 | | - kAlreadyResolvedSlot: Slot<PromiseResolvingFunctionContext, Boolean>, | | 268 | + kPromiseIfNotResolvedSlot: | | 269 | + Slot<PromiseResolvingFunctionContext, JSPromise|Undefined>, | 270 | 270 | kDebugEventSlot: Slot<PromiseResolvingFunctionContext, Boolean>, | 271 | 271 | kPromiseContextLength | 272 | 272 | } | @@ -390,25 +390,29 @@ transitioning builtin NewPromiseCapability( | 390 | 390 | transitioning javascript builtin PromiseCapabilityDefaultReject( | 391 | 391 | js-implicit context: Context, receiver: JSAny)(reason: JSAny): JSAny { | 392 | 392 | const context = %RawDownCast<PromiseResolvingFunctionContext>(context); | 393 | | - // 2. Let promise be F.[[Promise]]. | 394 | | - const promise = | 395 | | - *ContextSlot(context, PromiseResolvingFunctionContextSlot::kPromiseSlot); | 396 | | - | 397 | | - // 3. Let alreadyResolved be F.[[AlreadyResolved]]. | 398 | | - const alreadyResolved = *ContextSlot( | 399 | | - context, PromiseResolvingFunctionContextSlot::kAlreadyResolvedSlot); | 400 | | - | 401 | | - // 4. If alreadyResolved.[[Value]] is true, return undefined. | 402 | | - if (alreadyResolved == True) { | 403 | | - return Undefined; | | 393 | + // 2. Let promise be promiseOrEmpty.[[Value]]. | | 394 | + const promiseOrEmpty = | | 395 | + *ContextSlot( | | 396 | + context, PromiseResolvingFunctionContextSlot::kPromiseIfNotResolvedSlot); | | 397 | + | | 398 | + // 1. If promiseOrEmpty.[[Value]] is ~empty~, return undefined. | | 399 | + let promise: JSPromise; | | 400 | + typeswitch (promiseOrEmpty) { | | 401 | + case (Undefined): { | | 402 | + return Undefined; | | 403 | + } | | 404 | + case (p: JSPromise): { | | 405 | + promise = p; | | 406 | + } | 404 | 407 | } | 405 | 408 |
| 406 | | - // 5. Set alreadyResolved.[[Value]] to true. | | 409 | + // 3. Set promiseOrEmpty.[[Value]] to ~empty~. | 407 | 410 | *ContextSlot( | 408 | | - context, PromiseResolvingFunctionContextSlot::kAlreadyResolvedSlot) = | 409 | | - True; | | 411 | + context, PromiseResolvingFunctionContextSlot::kPromiseIfNotResolvedSlot) = | | 412 | + Undefined; | 410 | 413 |
| 411 | | - // 6. Return RejectPromise(promise, reason). | | 414 | + // 4. Perform RejectPromise(promise, reason). | | 415 | + // 5. Return undefined. | 412 | 416 | const debugEvent = *ContextSlot( | 413 | 417 | context, PromiseResolvingFunctionContextSlot::kDebugEventSlot); | 414 | 418 | return RejectPromise(promise, reason, debugEvent); | @@ -418,23 +422,26 @@ transitioning javascript builtin PromiseCapabilityDefaultReject( | 418 | 422 | transitioning javascript builtin PromiseCapabilityDefaultResolve( | 419 | 423 | js-implicit context: Context, receiver: JSAny)(resolution: JSAny): JSAny { | 420 | 424 | const context = %RawDownCast<PromiseResolvingFunctionContext>(context); | 421 | | - // 2. Let promise be F.[[Promise]]. | 422 | | - const promise: JSPromise = | 423 | | - *ContextSlot(context, PromiseResolvingFunctionContextSlot::kPromiseSlot); | 424 | | - | 425 | | - // 3. Let alreadyResolved be F.[[AlreadyResolved]]. | 426 | | - const alreadyResolved: Boolean = *ContextSlot( | 427 | | - context, PromiseResolvingFunctionContextSlot::kAlreadyResolvedSlot); | 428 | | - | 429 | | - // 4. If alreadyResolved.[[Value]] is true, return undefined. | 430 | | - if (alreadyResolved == True) { | 431 | | - return Undefined; | | 425 | + // 2. Let promise be promiseOrEmpty.[[Value]]. | | 426 | + const promiseOrEmpty = | | 427 | + *ContextSlot( | | 428 | + context, PromiseResolvingFunctionContextSlot::kPromiseIfNotResolvedSlot); | | 429 | + | | 430 | + // 1. If promiseOrEmpty.[[Value]] is ~empty~, return undefined. | | 431 | + let promise: JSPromise; | | 432 | + typeswitch (promiseOrEmpty) { | | 433 | + case (Undefined): { | | 434 | + return Undefined; | | 435 | + } | | 436 | + case (p: JSPromise): { | | 437 | + promise = p; | | 438 | + } | 432 | 439 | } | 433 | 440 |
| 434 | | - // 5. Set alreadyResolved.[[Value]] to true. | | 441 | + // 3. Set promiseOrEmpty.[[Value]] to ~empty~. | 435 | 442 | *ContextSlot( | 436 | | - context, PromiseResolvingFunctionContextSlot::kAlreadyResolvedSlot) = | 437 | | - True; | | 443 | + context, PromiseResolvingFunctionContextSlot::kPromiseIfNotResolvedSlot) = | | 444 | + Undefined; | 438 | 445 |
| 439 | 446 | // The rest of the logic (and the catch prediction) is | 440 | 447 | // encapsulated in the dedicated ResolvePromise builtin. | |
Collapse file Copy file name to clipboardExpand all lines: deps/v8/src/builtins/promise-all.tq +3-6Lines changed: 3 additions & 6 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -63,17 +63,14 @@ macro CreatePromiseResolvingFunctionsContext( | 63 | 63 | nativeContext, | 64 | 64 | PromiseResolvingFunctionContextSlot::kPromiseContextLength)); | 65 | 65 | InitContextSlot( | 66 | | - resolveContext, PromiseResolvingFunctionContextSlot::kPromiseSlot, | 67 | | - promise); | 68 | | - InitContextSlot( | 69 | | - resolveContext, PromiseResolvingFunctionContextSlot::kAlreadyResolvedSlot, | 70 | | - False); | | 66 | + resolveContext, | | 67 | + PromiseResolvingFunctionContextSlot::kPromiseIfNotResolvedSlot, promise); | 71 | 68 | InitContextSlot( | 72 | 69 | resolveContext, PromiseResolvingFunctionContextSlot::kDebugEventSlot, | 73 | 70 | debugEvent); | 74 | 71 | static_assert( | 75 | 72 | PromiseResolvingFunctionContextSlot::kPromiseContextLength == | 76 | | - ContextSlot::MIN_CONTEXT_SLOTS + 3); | | 73 | + ContextSlot::MIN_CONTEXT_SLOTS + 2); | 77 | 74 | return resolveContext; | 78 | 75 | } | 79 | 76 |
| |
Collapse file Copy file name to clipboardExpand all lines: deps/v8/src/compiler/js-call-reducer.cc +2-4Lines changed: 2 additions & 4 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -2543,10 +2543,8 @@ TNode<Object> PromiseBuiltinReducerAssembler::ReducePromiseConstructor( | 2543 | 2543 | // Allocate a promise context for the closures below. | 2544 | 2544 | TNode<Context> promise_context = CreateFunctionContext( | 2545 | 2545 | native_context, context, PromiseBuiltins::kPromiseContextLength); | 2546 | | - StoreContextNoCellSlot(promise_context, PromiseBuiltins::kPromiseSlot, | 2547 | | - promise); | 2548 | | - StoreContextNoCellSlot(promise_context, PromiseBuiltins::kAlreadyResolvedSlot, | 2549 | | - FalseConstant()); | | 2546 | + StoreContextNoCellSlot(promise_context, | | 2547 | + PromiseBuiltins::kPromiseIfNotResolvedSlot, promise); | 2550 | 2548 | StoreContextNoCellSlot(promise_context, PromiseBuiltins::kDebugEventSlot, | 2551 | 2549 | TrueConstant()); | 2552 | 2550 |
| |
Collapse file Copy file name to clipboardExpand all lines: deps/v8/src/execution/isolate.cc +6-3Lines changed: 6 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -1253,9 +1253,12 @@ void CaptureAsyncStackTrace(Isolate* isolate, DirectHandle<JSPromise> promise, | 1253 | 1253 | DirectHandle<JSFunction> function( | 1254 | 1254 | Cast<JSFunction>(reaction->fulfill_handler()), isolate); | 1255 | 1255 | DirectHandle<Context> context(function->context(), isolate); | 1256 | | - promise = direct_handle( | 1257 | | - Cast<JSPromise>(context->GetNoCell(PromiseBuiltins::kPromiseSlot)), | 1258 | | - isolate); | | 1256 | + Tagged<Object> promise_or_undefined = | | 1257 | + context->GetNoCell(PromiseBuiltins::kPromiseIfNotResolvedSlot); | | 1258 | + if (!TryCast(direct_handle(promise_or_undefined, isolate), &promise)) { | | 1259 | + DCHECK(IsUndefined(promise_or_undefined)); | | 1260 | + return; | | 1261 | + } | 1259 | 1262 | } else { | 1260 | 1263 | // We have some generic promise chain here, so try to | 1261 | 1264 | // continue with the chained promise on the reaction | |
Collapse file Copy file name to clipboardExpand all lines: deps/v8/test/cctest/test-code-stub-assembler.cc +4-2Lines changed: 4 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -3037,7 +3037,8 @@ TEST(CreatePromiseResolvingFunctionsContext) { | 3037 | 3037 | DirectHandle<Context> context_js = Cast<Context>(result); | 3038 | 3038 | CHECK_EQ(isolate->root(RootIndex::kEmptyScopeInfo), context_js->scope_info()); | 3039 | 3039 | CHECK_EQ(*isolate->native_context(), context_js->native_context()); | 3040 | | - CHECK(IsJSPromise(context_js->GetNoCell(PromiseBuiltins::kPromiseSlot))); | | 3040 | + CHECK(IsJSPromise( | | 3041 | + context_js->GetNoCell(PromiseBuiltins::kPromiseIfNotResolvedSlot))); | 3041 | 3042 | CHECK_EQ(ReadOnlyRoots(isolate).false_value(), | 3042 | 3043 | context_js->GetNoCell(PromiseBuiltins::kDebugEventSlot)); | 3043 | 3044 | } | @@ -3246,7 +3247,8 @@ TEST(NewPromiseCapability) { | 3246 | 3247 | CHECK_EQ(*isolate->native_context(), callback_context->native_context()); | 3247 | 3248 | CHECK_EQ(PromiseBuiltins::kPromiseContextLength, | 3248 | 3249 | callback_context->length()); | 3249 | | - CHECK_EQ(callback_context->GetNoCell(PromiseBuiltins::kPromiseSlot), | | 3250 | + CHECK_EQ(callback_context->GetNoCell( | | 3251 | + PromiseBuiltins::kPromiseIfNotResolvedSlot), | 3250 | 3252 | result->promise()); | 3251 | 3253 | } | 3252 | 3254 | } | |
Collapse file Copy file name to clipboard +26Lines changed: 26 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +// Copyright 2026 the V8 project authors. All rights reserved. | | 2 | +// Use of this source code is governed by a BSD-style license that can be | | 3 | +// found in the LICENSE file. | | 4 | + | | 5 | +// Flags: --expose-gc | | 6 | + | | 7 | +const pending = new Promise(() => {}); | | 8 | + | | 9 | +(async function () { | | 10 | + let wr; | | 11 | + | | 12 | + await (async function () { | | 13 | + const payload = { }; | | 14 | + wr = new WeakRef(payload); | | 15 | + const resolved = Promise.resolve(payload); | | 16 | + // The pending Promise should not prevent GC of the race Promise once the race settles. | | 17 | + await Promise.race([pending, resolved]); | | 18 | + })(); | | 19 | + | | 20 | + await gc({ type: 'major', execution: 'async' }); | | 21 | + | | 22 | + assertEquals(undefined, wr.deref()); | | 23 | +})().catch((e) => { | | 24 | + console.error(e); | | 25 | + quit(1); | | 26 | +}); |
|