Commit 29290738c1a for nodejs

commit 29290738c1a75495d13697a0e8c9a615f79a2167
Author: Node.js GitHub Bot <github-bot@iojs.org>
Date:   Mon Nov 9 20:05:29 2026 -0500

    deps: patch V8 to 15.6.75.50

    Refs: https://github.com/v8/v8/compare/15.6.75.33...15.6.75.50
    PR-URL: https://github.com/nodejs/node/pull/67335
    Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
    Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
    Reviewed-By: Filip Skokan <panva.ip@gmail.com>
    Reviewed-By: Chengzhong Wu <legendecas@gmail.com>

diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h
index 11e0def9233..0101d125766 100644
--- a/deps/v8/include/v8-version.h
+++ b/deps/v8/include/v8-version.h
@@ -11,7 +11,7 @@
 #define V8_MAJOR_VERSION 15
 #define V8_MINOR_VERSION 6
 #define V8_BUILD_NUMBER 75
-#define V8_PATCH_LEVEL 33
+#define V8_PATCH_LEVEL 50

 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff --git a/deps/v8/src/ast/scopes.cc b/deps/v8/src/ast/scopes.cc
index 725f007719d..67e319c1e1d 100644
--- a/deps/v8/src/ast/scopes.cc
+++ b/deps/v8/src/ast/scopes.cc
@@ -118,9 +118,11 @@ Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type)
   DCHECK(!is_script_scope());
   SetDefaults();
   set_language_mode(outer_scope->language_mode());
-  set_private_name_lookup_skips_outer_class(
-      outer_scope->is_class_scope() &&
-      outer_scope->AsClassScope()->IsParsingHeritage());
+  if (outer_scope->is_class_scope() &&
+      outer_scope->AsClassScope()->IsParsingHeritage()) {
+    set_private_name_lookup_skips_outer_class(true);
+    outer_scope->GetClosureScope()->RecordNeedsPrivateNameContextChainRecalc();
+  }
   outer_scope_->AddInnerScope(this);
 }

@@ -180,6 +182,9 @@ DeclarationScope::DeclarationScope(Zone* zone, Scope* outer_scope,
       params_(4, zone) {
   DCHECK(!is_script_scope());
   SetDefaults();
+  if (V8_UNLIKELY(private_name_lookup_skips_outer_class())) {
+    RecordNeedsPrivateNameContextChainRecalc();
+  }
 }

 ModuleScope::ModuleScope(DeclarationScope* script_scope,
@@ -305,18 +310,14 @@ DeclarationScope::DeclarationScope(Zone* zone, ScopeType scope_type,
     DCHECK(IsClassConstructor(function_kind()));
     set_class_scope_has_private_brand(true);
   }
+  if (V8_UNLIKELY(private_name_lookup_skips_outer_class())) {
+    RecordNeedsPrivateNameContextChainRecalc();
+  }
 }

 Scope::Scope(Zone* zone, const AstRawString* catch_variable_name,
              MaybeAssignedFlag maybe_assigned, Handle<ScopeInfo> scope_info)
-    : outer_scope_(nullptr),
-      variables_(zone),
-      scope_info_(scope_info),
-      scope_type_(CATCH_SCOPE) {
-  SetDefaults();
-#ifdef DEBUG
-  already_resolved_ = true;
-#endif
+    : Scope(zone, CATCH_SCOPE, nullptr, scope_info) {
   // Cache the catch variable, even though it's also available via the
   // scope_info, as the parser expects that a catch scope always has the catch
   // variable as first and only variable.
@@ -326,7 +327,6 @@ Scope::Scope(Zone* zone, const AstRawString* catch_variable_name,
               kCreatedInitialized, maybe_assigned, &was_added);
   DCHECK(was_added);
   AllocateHeapSlot(variable);
-  set_is_hoisted_in_context(scope_info->is_hoisted_in_context());
 }

 void DeclarationScope::SetDefaults() {
@@ -454,9 +454,14 @@ Scope* Scope::DeserializeScopeChain(
       eval_scope->set_start_position(position);
       eval_scope->set_end_position(position);
       eval_scope->set_eval_position(position);
-
       if (current_scope != nullptr) {
+        eval_scope->set_private_name_lookup_skips_outer_class(
+            current_scope->private_name_lookup_skips_outer_class());
+        current_scope->set_private_name_lookup_skips_outer_class(false);
         eval_scope->AddInnerScope(current_scope);
+      } else if (parse_info != nullptr) {
+        eval_scope->set_private_name_lookup_skips_outer_class(
+            parse_info->flags().private_name_lookup_skips_outer_class());
       }
       current_scope = eval_scope;
       if (innermost_scope == nullptr) innermost_scope = current_scope;
@@ -940,6 +945,7 @@ Scope* Scope::FinalizeBlockScope() {
       scope->outer_scope_ = outer_scope();
       if (private_name_lookup_skips_outer_class()) {
         scope->set_private_name_lookup_skips_outer_class(true);
+        scope->GetClosureScope()->RecordNeedsPrivateNameContextChainRecalc();
       }
       if (scope->is_function_scope()) {
         scope->set_is_hoisted_in_context(false);
@@ -997,12 +1003,14 @@ void Scope::Snapshot::Reparent(DeclarationScope* new_parent) {
     for (; inner_scope->sibling() != top_inner_scope_;
          inner_scope = inner_scope->sibling()) {
       inner_scope->outer_scope_ = new_parent;
+      inner_scope->set_private_name_lookup_skips_outer_class(false);
       if (inner_scope->inner_scope_calls_eval()) {
         new_parent->set_inner_scope_calls_eval(true);
       }
       DCHECK_NE(inner_scope, new_parent);
     }
     inner_scope->outer_scope_ = new_parent;
+    inner_scope->set_private_name_lookup_skips_outer_class(false);
     if (inner_scope->inner_scope_calls_eval()) {
       new_parent->set_inner_scope_calls_eval(true);
     }
@@ -1454,7 +1462,12 @@ bool DeclarationScope::AllocateVariables(ParseInfo* info) {
   }

   // Don't allocate variables of preparsed scopes.
-  if (!was_lazily_parsed()) AllocateVariablesRecursively();
+  if (!was_lazily_parsed()) {
+    AllocateVariablesRecursively();
+    if (needs_private_name_context_chain_recalc()) {
+      RecalcPrivateNameContextChain();
+    }
+  }

   return true;
 }
@@ -2924,10 +2937,6 @@ void DeclarationScope::AllocateScopeInfos(ParseInfo* parse_info,
     }
   }

-  if (scope->needs_private_name_context_chain_recalc()) {
-    scope->RecalcPrivateNameContextChain();
-  }
-
   Tagged<WeakFixedArray> infos = script->infos();
   std::unordered_map<int, Handle<ScopeInfo>> scope_infos_to_reuse;
   if (infos->ulength().value() != 0) {
diff --git a/deps/v8/src/ast/scopes.h b/deps/v8/src/ast/scopes.h
index fa13cc9a176..183700b6a1b 100644
--- a/deps/v8/src/ast/scopes.h
+++ b/deps/v8/src/ast/scopes.h
@@ -1512,6 +1512,7 @@ void Scope::RecordEvalCall() {
     GetDeclarationScope()->RecordDeclarationScopeEvalCall();
   }
   RecordInnerScopeEvalCall();
+  GetClosureScope()->RecordNeedsPrivateNameContextChainRecalc();
   // The eval contents might access "super" (if it's inside a function that
   // binds super).
   DeclarationScope* receiver_scope = GetReceiverScope();
diff --git a/deps/v8/src/codegen/arm64/assembler-arm64-inl.h b/deps/v8/src/codegen/arm64/assembler-arm64-inl.h
index fc8b4c83ff8..abd4c5e63e8 100644
--- a/deps/v8/src/codegen/arm64/assembler-arm64-inl.h
+++ b/deps/v8/src/codegen/arm64/assembler-arm64-inl.h
@@ -983,7 +983,7 @@ Instr Assembler::SF(Register rd) {
 }

 Instr Assembler::ImmAddSub(int imm) {
-  DCHECK(IsImmAddSub(imm));
+  CHECK(IsImmAddSub(imm));
   if (is_uint12(imm)) {  // No shift required.
     imm <<= ImmAddSub_offset;
   } else {
diff --git a/deps/v8/src/codegen/arm64/assembler-arm64.cc b/deps/v8/src/codegen/arm64/assembler-arm64.cc
index e3a6685ede1..af1c92fca71 100644
--- a/deps/v8/src/codegen/arm64/assembler-arm64.cc
+++ b/deps/v8/src/codegen/arm64/assembler-arm64.cc
@@ -4043,7 +4043,7 @@ void Assembler::AddSub(const Register& rd, const Register& rn,
   DCHECK(!operand.NeedsRelocation(this));
   if (operand.IsImmediate()) {
     int64_t immediate = operand.ImmediateValue();
-    DCHECK(IsImmAddSub(immediate));
+    CHECK(IsImmAddSub(immediate));
     Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd);
     Emit(SF(rd) | AddSubImmediateFixed | op | Flags(S) |
          ImmAddSub(static_cast<int>(immediate)) | dest_reg | RnSP(rn));
diff --git a/deps/v8/src/codegen/arm64/macro-assembler-arm64.cc b/deps/v8/src/codegen/arm64/macro-assembler-arm64.cc
index a79bd6d3186..26a3110f8f0 100644
--- a/deps/v8/src/codegen/arm64/macro-assembler-arm64.cc
+++ b/deps/v8/src/codegen/arm64/macro-assembler-arm64.cc
@@ -979,11 +979,11 @@ void MacroAssembler::LoadStoreMacroComplex(const CPURegister& rt,
     // Post-index beyond unscaled addressing range.
     DCHECK(!is_imm_unscaled);
     LoadStore(rt, MemOperand(addr.base()), op);
-    add(addr.base(), addr.base(), offset);
+    Add(addr.base(), addr.base(), offset);
   } else {
     // Pre-index beyond unscaled addressing range.
     DCHECK(!is_imm_unscaled && addr.IsPreIndex());
-    add(addr.base(), addr.base(), offset);
+    Add(addr.base(), addr.base(), offset);
     LoadStore(rt, MemOperand(addr.base()), op);
   }
 }
diff --git a/deps/v8/src/codegen/compiler.cc b/deps/v8/src/codegen/compiler.cc
index 0a3599ee41c..7a965c17292 100644
--- a/deps/v8/src/codegen/compiler.cc
+++ b/deps/v8/src/codegen/compiler.cc
@@ -3320,7 +3320,8 @@ MaybeDirectHandle<JSFunction> Compiler::GetFunctionFromEval(
     DirectHandle<SharedFunctionInfo> outer_info, DirectHandle<Context> context,
     LanguageMode language_mode, ParseRestriction restriction,
     int parameters_end_pos, int eval_position,
-    ParsingWhileDebugging parsing_while_debugging) {
+    ParsingWhileDebugging parsing_while_debugging,
+    bool private_name_lookup_skips_outer_class) {
   // The cache lookup key needs to be aware of the separation between the
   // parameters and the body to prevent this valid invocation:
   //   Function("", "function anonymous(\n/**/) {\n}");
@@ -3376,6 +3377,8 @@ MaybeDirectHandle<JSFunction> Compiler::GetFunctionFromEval(
         v8_flags.lazy_eval);
     flags.set_is_eval(true);
     flags.set_parsing_while_debugging(parsing_while_debugging);
+    flags.set_private_name_lookup_skips_outer_class(
+        private_name_lookup_skips_outer_class);
     DCHECK(!flags.is_module());
     flags.set_parse_restriction(restriction);

diff --git a/deps/v8/src/codegen/compiler.h b/deps/v8/src/codegen/compiler.h
index cfa6af01010..bab8d706884 100644
--- a/deps/v8/src/codegen/compiler.h
+++ b/deps/v8/src/codegen/compiler.h
@@ -166,7 +166,8 @@ class V8_EXPORT_PRIVATE Compiler : public AllStatic {
                       ParseRestriction restriction, int parameters_end_pos,
                       int eval_position,
                       ParsingWhileDebugging parsing_while_debugging =
-                          ParsingWhileDebugging::kNo);
+                          ParsingWhileDebugging::kNo,
+                      bool private_name_lookup_skips_outer_class = false);

   // Create a function that results from wrapping |source| in a function,
   // with |arguments| being a list of parameters for that function.
diff --git a/deps/v8/src/compiler/backend/arm64/code-generator-arm64.cc b/deps/v8/src/compiler/backend/arm64/code-generator-arm64.cc
index f4efe50f64d..a1fda89d75d 100644
--- a/deps/v8/src/compiler/backend/arm64/code-generator-arm64.cc
+++ b/deps/v8/src/compiler/backend/arm64/code-generator-arm64.cc
@@ -4674,7 +4674,7 @@ void CodeGenerator::Pop(InstructionOperand* dest, MachineRepresentation rep) {
 void CodeGenerator::PopTempStackSlots() {
   if (temp_slots_ > 0) {
     frame_access_state()->IncreaseSPDelta(-temp_slots_);
-    __ add(sp, sp, Operand(temp_slots_ * kSystemPointerSize));
+    __ Add(sp, sp, Operand(temp_slots_ * kSystemPointerSize));
     temp_slots_ = 0;
   }
 }
diff --git a/deps/v8/src/compiler/backend/code-generator.cc b/deps/v8/src/compiler/backend/code-generator.cc
index 28faaf10951..97678a75401 100644
--- a/deps/v8/src/compiler/backend/code-generator.cc
+++ b/deps/v8/src/compiler/backend/code-generator.cc
@@ -1695,8 +1695,8 @@ void CodeGenerator::AddTranslationForOperand(Instruction* instr,
       default:
         UNREACHABLE();
     }
-    if (literal.object().equals(info()->closure()) &&
-        info()->function_context_specializing()) {
+    if (info()->function_context_specializing() &&
+        literal.IsObject(info()->closure())) {
       translations_.StoreJSFrameFunction();
     } else {
       int literal_id = DefineDeoptimizationLiteral(literal);
diff --git a/deps/v8/src/compiler/wasm-load-elimination.cc b/deps/v8/src/compiler/wasm-load-elimination.cc
index 3ab300bb0e1..75d7f83f08a 100644
--- a/deps/v8/src/compiler/wasm-load-elimination.cc
+++ b/deps/v8/src/compiler/wasm-load-elimination.cc
@@ -84,7 +84,40 @@ Reduction WasmLoadElimination::UpdateState(Node* node,
 std::tuple<Node*, Node*> WasmLoadElimination::TruncateAndExtendOrType(
     Node* value, Node* effect, Node* control, wasm::ValueType field_type,
     bool is_signed) {
+  if (value->opcode() == IrOpcode::kDead ||
+      value->opcode() == IrOpcode::kDeadValue) {
+    return {dead(), dead()};
+  }
+
+  // The value might be untyped or have a non-Wasm type (e.g. Type::None() from
+  // DeadCodeElimination, or a JS node in case of Wasm inlined into JS). Without
+  // a concrete Wasm type we cannot verify representation compatibility.
+  if (!NodeProperties::IsTyped(value)) {
+    return {nullptr, nullptr};
+  }
+
+  Type value_type = NodeProperties::GetType(value);
+  if (!value_type.IsWasm()) {
+    return {nullptr, nullptr};
+  }
+
+  wasm::TypeInModule node_type = value_type.AsWasm();
+  if (node_type.type.is_top()) {
+    return {nullptr, nullptr};
+  }
+
+  wasm::ValueType unpacked_field_type = field_type.Unpacked();
+  if (node_type.type.is_uninhabited() ||
+      TypesUnrelated(node_type.type, unpacked_field_type, node_type.module)) {
+    // Uninhabited or unrelated types can occur as a result of unreachable code.
+    // Example: Storing a value x of type A in a struct, then casting the struct
+    // to a different struct type to then load type B from the same offset
+    // results in trying to replace the load with value x.
+    return {dead(), dead()};
+  }
+
   if (field_type == wasm::kWasmI8 || field_type == wasm::kWasmI16) {
+    DCHECK_EQ(node_type.type, wasm::kWasmI32);
     Node* ret = nullptr;
     if (is_signed) {
       int shift = 32 - 8 * field_type.value_kind_size();
@@ -98,30 +131,10 @@ std::tuple<Node*, Node*> WasmLoadElimination::TruncateAndExtendOrType(
                              jsgraph()->Int32Constant(mask));
     }

-    NodeProperties::SetType(ret, NodeProperties::GetType(value));
+    NodeProperties::SetType(ret, value_type);
     return {ret, effect};
   }

-  // The value might be untyped in case of wasm inlined into JS if the value
-  // comes from a JS node.
-  if (!NodeProperties::IsTyped(value)) {
-    return {value, effect};
-  }
-
-  Type value_type = NodeProperties::GetType(value);
-  if (!value_type.IsWasm()) {
-    return {value, effect};
-  }
-
-  wasm::TypeInModule node_type = value_type.AsWasm();
-
-  if (TypesUnrelated(node_type.type, field_type, node_type.module)) {
-    // Unrelated types can occur as a result of unreachable code.
-    // Example: Storing a value x of type A in a struct, then casting the struct
-    // to a different struct type to then load type B from the same offset
-    // results in trying to replace the load with value x.
-    return {dead(), dead()};
-  }
   if (!wasm::IsSubtypeOf(node_type.type, field_type, node_type.module)) {
     Type type = Type::Wasm({field_type, node_type.module}, graph()->zone());
     Node* ret =
@@ -233,10 +246,12 @@ Reduction WasmLoadElimination::ReduceWasmStructGet(Node* node) {
       node->Kill();
       return Replace(dead());
     }
-    ReplaceWithValue(node, std::get<0>(replacement), std::get<1>(replacement),
-                     control);
-    node->Kill();
-    return Replace(std::get<0>(replacement));
+    if (std::get<0>(replacement) != nullptr) {
+      ReplaceWithValue(node, std::get<0>(replacement), std::get<1>(replacement),
+                       control);
+      node->Kill();
+      return Replace(std::get<0>(replacement));
+    }
   }

   half_state = half_state->AddField(field_info.field_index, object, node);
diff --git a/deps/v8/src/compiler/wasm-load-elimination.h b/deps/v8/src/compiler/wasm-load-elimination.h
index fe404181f3b..204af4f23a4 100644
--- a/deps/v8/src/compiler/wasm-load-elimination.h
+++ b/deps/v8/src/compiler/wasm-load-elimination.h
@@ -138,7 +138,9 @@ class V8_EXPORT_PRIVATE WasmLoadElimination final
   AbstractState const* ComputeLoopState(Node* node,
                                         AbstractState const* state) const;
   // Returns the replacement value and effect for a load given an initial value
-  // node, after optional {TypeGuard}ing and i8/i16 adaptation to i32.
+  // node, after optional {TypeGuard}ing and i8/i16 adaptation to i32. Returns
+  // {dead(), dead()} if the types prove the load is unreachable, or
+  // {nullptr, nullptr} if replacement must be skipped.
   std::tuple<Node*, Node*> TruncateAndExtendOrType(Node* value, Node* effect,
                                                    Node* control,
                                                    wasm::ValueType field_type,
diff --git a/deps/v8/src/d8/d8.cc b/deps/v8/src/d8/d8.cc
index 8d325f418e3..2f7517743e8 100644
--- a/deps/v8/src/d8/d8.cc
+++ b/deps/v8/src/d8/d8.cc
@@ -4768,8 +4768,10 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
   global_template->Set(Symbol::GetToStringTag(isolate),
                        String::NewFromUtf8Literal(isolate, "global"));
   global_template->Set(isolate, "onerror", v8::Null(isolate));
-  global_template->Set(isolate, "version",
-                       FunctionTemplate::New(isolate, Version));
+  Local<FunctionTemplate> version_func_template =
+      FunctionTemplate::New(isolate, Version);
+  version_func_template->SetAcceptAnyReceiver(false);
+  global_template->Set(isolate, "version", version_func_template);

   global_template->Set(isolate, "print", FunctionTemplate::New(isolate, Print));
   global_template->Set(isolate, "printErr",
diff --git a/deps/v8/src/debug/debug.cc b/deps/v8/src/debug/debug.cc
index def10a51cd7..62b24a590e6 100644
--- a/deps/v8/src/debug/debug.cc
+++ b/deps/v8/src/debug/debug.cc
@@ -40,6 +40,7 @@
 #include "src/snapshot/embedded/embedded-data.h"

 #if V8_ENABLE_WEBASSEMBLY
+#include "src/wasm/wasm-code-manager.h"
 #include "src/wasm/wasm-debug.h"
 #include "src/wasm/wasm-objects-inl.h"
 #endif  // V8_ENABLE_WEBASSEMBLY
@@ -2973,6 +2974,60 @@ void Debug::HandleDebugBreak(IgnoreBreakMode ignore_break_mode,
           return;
         }
       }
+#if V8_ENABLE_WEBASSEMBLY
+    } else if (!it.done() && it.frame()->is_wasm()) {
+#if V8_ENABLE_DRUMBRAKE
+      if (!it.frame()->is_wasm_interpreter_entry())
+#endif  // V8_ENABLE_DRUMBRAKE
+      {
+        WasmFrame* wasm_frame = WasmFrame::cast(it.frame());
+        wasm::WasmCodeRefScope code_ref_scope;
+        // Optimized Wasm frames cannot be deoptimized on-stack at loop stack
+        // checks. Defer the pause to the next function call (or return to a
+        // debuggable caller frame) so that JavaScript executed during the
+        // pause cannot invalidate load-eliminated state in the optimized Wasm
+        // frame.
+        if (!wasm_frame->wasm_code()->is_liftoff()) {
+          if (ignore_events()) return;
+          thread_local_.scheduled_break_on_next_function_call_.Add(
+              break_reasons);
+          SetBreakOnNextFunctionCall();
+          for (it.Advance(); !it.done(); it.Advance()) {
+            if (it.frame()->is_wasm()) {
+#if V8_ENABLE_DRUMBRAKE
+              if (it.frame()->is_wasm_interpreter_entry()) continue;
+#endif  // V8_ENABLE_DRUMBRAKE
+              WasmFrame* caller_wasm = WasmFrame::cast(it.frame());
+              if (!caller_wasm->wasm_code()->is_inspectable()) continue;
+              wasm::DebugInfo* debug_info =
+                  caller_wasm->native_module()->GetDebugInfo();
+              if (debug_info->IsFrameBlackboxed(caller_wasm)) continue;
+              debug_info->PrepareStepOutTo(caller_wasm);
+              break;
+            }
+            JavaScriptFrame* js_frame = JavaScriptFrame::cast(it.frame());
+            if (js_frame->is_optimized()) {
+              Deoptimizer::DeoptimizeFunction(js_frame->function(),
+                                              LazyDeoptimizeReason::kDebugger,
+                                              js_frame->LookupCode());
+            }
+            HandleScope inner_scope(isolate_);
+            std::vector<Handle<SharedFunctionInfo>> infos;
+            js_frame->GetFunctions(&infos);
+            bool flooded = false;
+            for (; !infos.empty(); infos.pop_back()) {
+              Handle<SharedFunctionInfo> info = infos.back();
+              if (IsBlackboxed(info)) continue;
+              FloodWithOneShot(info);
+              flooded = true;
+              break;
+            }
+            if (flooded) break;
+          }
+          return;
+        }
+      }
+#endif  // V8_ENABLE_WEBASSEMBLY
     }
   }

diff --git a/deps/v8/src/debug/debug.h b/deps/v8/src/debug/debug.h
index 4a093800e6d..1c8f80db04d 100644
--- a/deps/v8/src/debug/debug.h
+++ b/deps/v8/src/debug/debug.h
@@ -460,6 +460,9 @@ class V8_EXPORT_PRIVATE Debug {
   bool scheduled_break_on_function_call() const {
     return !thread_local_.scheduled_break_on_next_function_call_.empty();
   }
+  v8::debug::BreakReasons scheduled_break_on_next_function_call() const {
+    return thread_local_.scheduled_break_on_next_function_call_;
+  }

   bool IsRestartFrameScheduled() const {
     return thread_local_.restart_frame_id_ != StackFrameId::NO_ID;
diff --git a/deps/v8/src/execution/isolate.cc b/deps/v8/src/execution/isolate.cc
index 7ef444669c8..e6f2f3506d3 100644
--- a/deps/v8/src/execution/isolate.cc
+++ b/deps/v8/src/execution/isolate.cc
@@ -3299,6 +3299,7 @@ Tagged<Object> Isolate::UnwindAndFindHandler() {
         break;
       }
       case StackFrame::INTERNAL: {
+        if (!catchable_by_js) break;
         auto code = frame->GcSafeLookupCode();
         if (code->builtin_id() ==
             Builtin::kDeoptimizationEntry_LazyAfterFastCall) {
@@ -4629,8 +4630,7 @@ void Isolate::SwitchStacks(wasm::StackMemory* from, wasm::StackMemory* to,
   stack_guard()->SetStackLimitForStackSwitching(limit);

   // Update the central stack info.
-  if (!thread_local_top()->is_on_central_stack_flag_ &&
-      to->jmpbuf()->is_on_central_stack) {
+  if (to->jmpbuf()->is_on_central_stack) {
     DCHECK(is_suspend || is_return);
     DCHECK_EQ(expected_target_state, wasm::JumpBuffer::Inactive);
     thread_local_top()->is_on_central_stack_flag_ = true;
@@ -4640,8 +4640,7 @@ void Isolate::SwitchStacks(wasm::StackMemory* from, wasm::StackMemory* to,
 #endif
     thread_local_top()->central_stack_limit_ =
         reinterpret_cast<Address>(to->jmpbuf()->stack_limit);
-  } else if (thread_local_top()->is_on_central_stack_flag_ &&
-             !to->jmpbuf()->is_on_central_stack) {
+  } else if (thread_local_top()->is_on_central_stack_flag_) {
     thread_local_top()->is_on_central_stack_flag_ = false;
     if (is_resume) {
       // Record the current central stack SP, we will switch back to it for
@@ -5543,9 +5542,23 @@ void Isolate::NotifyExceptionPropagationCallback() {
     // "C++ -> JS" or "C++ -> Api callback" boundary.
     return;
   }
-  if (it.done() ||
-      (ext_callback_scope &&
-       ext_callback_scope->JSStackComparableAddress() < it.frame()->fp())) {
+  bool is_direct_api_throw = it.done();
+  if (!is_direct_api_throw && ext_callback_scope != nullptr) {
+    Address comparable_fp = it.frame()->fp();
+#if V8_ENABLE_WEBASSEMBLY
+    if (!IsOnCentralStack(comparable_fp)) {
+      // The topmost frame is on a Wasm secondary stack, whereas
+      // |ext_callback_scope| is always on the central stack. Compare against
+      // the central-stack SP saved when switching to the secondary stack.
+      comparable_fp = thread_local_top()->central_stack_sp_;
+      DCHECK_NE(comparable_fp, kNullAddress);
+      DCHECK(IsOnCentralStack(comparable_fp));
+    }
+#endif  // V8_ENABLE_WEBASSEMBLY
+    is_direct_api_throw =
+        ext_callback_scope->JSStackComparableAddress() < comparable_fp;
+  }
+  if (is_direct_api_throw) {
     // There were no crossings of "C++ -> JS" boundary at all or they happened
     // earlier than the last crossing of the  "C++ -> Api callback" boundary.
     // In this case all the data about Api callback is available in the
@@ -5656,6 +5669,9 @@ void Isolate::NotifyExceptionPropagationCallback() {
       // These frames are not created yet.
       UNREACHABLE();
     case StackFrame::TURBOFAN_JS:
+#if V8_ENABLE_WEBASSEMBLY
+    case StackFrame::WASM_TO_JS:
+#endif  // V8_ENABLE_WEBASSEMBLY
       // This must be a fast Api call.
       CHECK(it.frame()->InFastCCall());
       // TODO(ishell): support fast Api calls.
@@ -5666,6 +5682,7 @@ void Isolate::NotifyExceptionPropagationCallback() {
       return;
 #if V8_ENABLE_WEBASSEMBLY
     case StackFrame::WASM:
+    case StackFrame::WASM_EXIT:
     case StackFrame::WASM_SEGMENT_START:
       // No more info.
       return;
@@ -8055,6 +8072,9 @@ void Isolate::DetachGlobal(DirectHandle<NativeContext> env) {
   // Set security token back to default (unique) state making sure that only
   // accesses from the same native context are allowed.
   env->set_security_token(env->global_object());
+  // Invalidate LoadGlobalIC/StoreGlobalIC handlers to enforce access checks
+  // for the rewired global proxy from the detached context.
+  JSObject::InvalidatePrototypeValidityCell(env->global_object());
 }

 void Isolate::SetIsLoading(bool is_loading) {
diff --git a/deps/v8/src/heap/factory.cc b/deps/v8/src/heap/factory.cc
index d2a5f284e01..acaf95db3ab 100644
--- a/deps/v8/src/heap/factory.cc
+++ b/deps/v8/src/heap/factory.cc
@@ -4005,15 +4005,15 @@ DirectHandle<SourceTextModule> Factory::NewSourceTextModule(
       New(source_text_module_map(), AllocationType::kOld));
   DisallowGarbageCollection no_gc;
   module->set_code(*sfi);
+  module->set_status(Module::kUnlinked);
+  module->set_module_namespace(roots.undefined_value(), SKIP_WRITE_BARRIER);
+  module->set_deferred_module_namespace(roots.undefined_value(),
+                                        SKIP_WRITE_BARRIER);
   module->set_exports(*exports);
   module->set_regular_exports(*regular_exports);
   module->set_regular_imports(*regular_imports);
   module->set_hash(isolate()->GenerateIdentityHash(Smi::kMaxValue));
-  module->set_module_namespace(roots.undefined_value(), SKIP_WRITE_BARRIER);
-  module->set_deferred_module_namespace(roots.undefined_value(),
-                                        SKIP_WRITE_BARRIER);
   module->set_requested_modules(*requested_modules);
-  module->set_status(Module::kUnlinked);
   module->set_exception(roots.the_hole_value(), SKIP_WRITE_BARRIER);
   module->set_top_level_capability(roots.undefined_value(), SKIP_WRITE_BARRIER);
   module->set_import_meta(roots.the_hole_value(), kReleaseStore,
diff --git a/deps/v8/src/ic/accessor-assembler.cc b/deps/v8/src/ic/accessor-assembler.cc
index c262e24e75f..0dfd75a4649 100644
--- a/deps/v8/src/ic/accessor-assembler.cc
+++ b/deps/v8/src/ic/accessor-assembler.cc
@@ -1554,7 +1554,7 @@ void AccessorAssembler::HandleStoreICHandlerCase(
     ICMode ic_mode, ElementSupport support_elements) {
   Label if_smi_handler(this), if_nonsmi_handler(this);
   Label if_proto_handler(this), call_handler(this),
-      store_transition_or_global_or_accessor(this);
+      store_transition_or_accessor(this);

   Branch(TaggedIsSmi(handler), &if_smi_handler, &if_nonsmi_handler);

@@ -1685,8 +1685,7 @@ void AccessorAssembler::HandleStoreICHandlerCase(
   BIND(&if_nonsmi_handler);
   {
     TNode<HeapObjectReference> ref_handler = CAST(handler);
-    GotoIf(IsWeakOrCleared(ref_handler),
-           &store_transition_or_global_or_accessor);
+    GotoIf(IsWeakOrCleared(ref_handler), &store_transition_or_accessor);
     TNode<HeapObject> strong_handler = CAST(handler);
     TNode<Map> handler_map = LoadMap(strong_handler);
     Branch(IsCodeMap(handler_map), &call_handler, &if_proto_handler);
@@ -1711,39 +1710,17 @@ void AccessorAssembler::HandleStoreICHandlerCase(
     }
   }

-  BIND(&store_transition_or_global_or_accessor);
+  BIND(&store_transition_or_accessor);
   {
     // Load value or miss if the {handler} weak cell is cleared.
     CSA_DCHECK(this, IsWeakOrCleared(handler));
     TNode<HeapObject> strong_handler = GetHeapObjectAssumeWeak(handler, miss);

-    Label store_global(this), store_transition(this), store_accessor(this);
+    Label store_transition(this), store_accessor(this);
     TNode<Map> strong_handler_map = LoadMap(strong_handler);
-    GotoIf(IsPropertyCellMap(strong_handler_map), &store_global);
     Branch(IsAccessorPairMap(strong_handler_map), &store_accessor,
            &store_transition);

-    BIND(&store_global);
-    {
-      if (p->IsDefineNamedOwn()) {
-        // The global proxy has its attributes set in the global object,
-        // which can't be handled by StoreGlobalIC_PropertyCellCase when
-        // defining public fields. Handle it in runtime.
-        GotoIf(IsJSGlobalProxy(CAST(p->receiver())), &if_slow);
-      } else if (p->IsDefineKeyedOwn()) {
-        Label proceed_defining(this);
-        // StoreGlobalIC_PropertyCellCase doesn't support definition
-        // of private fields, so handle them in runtime.
-        GotoIfNot(IsSymbol(CAST(p->name())), &proceed_defining);
-        Branch(IsAnyPrivateName(CAST(p->name())), &if_slow, &proceed_defining);
-        BIND(&proceed_defining);
-      }
-
-      TNode<PropertyCell> property_cell = CAST(strong_handler);
-      ExitPoint direct_exit(this);
-      StoreGlobalIC_PropertyCellCase(property_cell, p->value(), &direct_exit,
-                                     miss);
-    }
     BIND(&store_accessor);
     {
       TNode<AccessorPair> pair = CAST(strong_handler);
diff --git a/deps/v8/src/ic/handler-configuration.cc b/deps/v8/src/ic/handler-configuration.cc
index 63dbf68c790..9b12fe2aec9 100644
--- a/deps/v8/src/ic/handler-configuration.cc
+++ b/deps/v8/src/ic/handler-configuration.cc
@@ -508,11 +508,6 @@ Handle<StoreHandler> StoreHandler::StoreInterceptorHolderIsReceiver(
   return handler;
 }

-// static
-MaybeObjectHandle StoreHandler::StoreGlobal(Handle<PropertyCell> cell) {
-  return MaybeObjectHandle::Weak(cell);
-}
-
 // static
 Handle<Object> StoreHandler::StoreProxy(Isolate* isolate,
                                         DirectHandle<Map> receiver_map,
diff --git a/deps/v8/src/ic/handler-configuration.h b/deps/v8/src/ic/handler-configuration.h
index 6e85b8f06f6..5883a357073 100644
--- a/deps/v8/src/ic/handler-configuration.h
+++ b/deps/v8/src/ic/handler-configuration.h
@@ -369,10 +369,6 @@ V8_OBJECT class StoreHandler final : public DataHandler {
                                    Handle<JSProxy> proxy,
                                    DirectHandle<JSReceiver> receiver);

-  // Creates a handler for storing a property to the property cell of a global
-  // object.
-  static MaybeObjectHandle StoreGlobal(Handle<PropertyCell> cell);
-
   // Creates a Smi-handler for storing a property to a global proxy object.
   static inline DirectHandle<Smi> StoreGlobalProxy(Isolate* isolate);

diff --git a/deps/v8/src/ic/ic-inl.h b/deps/v8/src/ic/ic-inl.h
index e19ce57f2e9..842a9412897 100644
--- a/deps/v8/src/ic/ic-inl.h
+++ b/deps/v8/src/ic/ic-inl.h
@@ -30,8 +30,7 @@ bool IC::IsHandler(Tagged<MaybeObject> object) {
   Tagged<HeapObject> heap_object;
   return (IsSmi(object) && (object.ptr() != kNullAddress)) ||
          (object.GetHeapObjectIfWeak(&heap_object) &&
-          (IsMap(heap_object) || IsPropertyCell(heap_object) ||
-           IsAccessorPair(heap_object))) ||
+          (IsMap(heap_object) || IsAccessorPair(heap_object))) ||
          (object.GetHeapObjectIfStrong(&heap_object) &&
           (IsDataHandler(heap_object) || IsCode(heap_object)));
 }
diff --git a/deps/v8/src/ic/ic.cc b/deps/v8/src/ic/ic.cc
index 681dac659f1..f6e7d6422a2 100644
--- a/deps/v8/src/ic/ic.cc
+++ b/deps/v8/src/ic/ic.cc
@@ -1098,6 +1098,18 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) {
         TraceIC("LoadGlobalIC", lookup->name());
         return;
       }
+      // Own DATA properties above are accessed directly via PropertyCell on the
+      // JSGlobalObject and don't involve the JSGlobalProxy. For anything else
+      // (e.g. prototype accessors), the handler would substitute global_proxy
+      // as the receiver without performing an access check on it, and
+      // LookupIterator didn't fail an access check because JSGlobalObject
+      // belongs to the current (detached) native context while its global_proxy
+      // may have been rebound to a new cross-origin context.
+      if (Cast<JSGlobalObject>(*lookup->GetReceiver())->IsDetached()) {
+        SetCache(lookup->GetName(), LoadHandler::LoadSlow(isolate()));
+        TraceIC("LoadGlobalIC", lookup->GetName());
+        return;
+      }
     }
     handler = ComputeHandler(lookup);
     CHECK(lookup->state() == LookupIterator::STRING_LOOKUP_START_OBJECT ||
@@ -2416,6 +2428,16 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, DirectHandle<Object> value,
         TraceIC("StoreGlobalIC", lookup->GetName());
         return;
       }
+      // See comment in LoadIC::UpdateCaches: own DATA properties above use
+      // PropertyCell on the JSGlobalObject directly, whereas other handlers
+      // (e.g. prototype accessors) substitute global_proxy as the receiver,
+      // which may have been rebound to a cross-origin context upon detachment.
+      if (Cast<JSGlobalObject>(*lookup->GetReceiver())->IsDetached()) {
+        set_slow_stub_reason("detached global object");
+        SetCache(lookup->GetName(), StoreHandler::StoreSlow(isolate()));
+        TraceIC("StoreGlobalIC", lookup->GetName());
+        return;
+      }
     }
     handler = ComputeHandler(lookup);
   } else {
@@ -2436,16 +2458,6 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
       if (IsJSGlobalObject(*store_target)) {
         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalTransitionDH);

-        if (IsJSGlobalObject(*lookup_start_object_map())) {
-          DCHECK(IsStoreGlobalIC());
-#ifdef DEBUG
-          DirectHandle<JSObject> holder = lookup->GetHolder<JSObject>();
-          DCHECK_EQ(*lookup->GetReceiver(), *holder);
-          DCHECK_EQ(*store_target, *holder);
-#endif
-          return StoreHandler::StoreGlobal(
-              indirect_handle(lookup->transition_cell(), isolate()));
-        }
         if (IsDefineKeyedOwnIC()) {
           // Private field can't be deleted from this global object and can't
           // be overwritten, so install slow handler in order to make store IC
@@ -2662,9 +2674,19 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
       }
       if (lookup->is_dictionary_holder()) {
         if (IsJSGlobalObject(*holder)) {
+          DCHECK(!IsStoreGlobalIC());
+          DCHECK(IsJSGlobalProxy(*receiver));
+          if (IsAnyDefineOwn()) {
+            TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+            return MaybeObjectHandle(StoreHandler::StoreSlow(isolate()));
+          }
           TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalDH);
-          return MaybeObjectHandle(StoreHandler::StoreGlobal(
-              indirect_handle(lookup->GetPropertyCell(), isolate())));
+          DirectHandle<Smi> smi_handler =
+              StoreHandler::StoreGlobalProxy(isolate());
+          Handle<Object> handler = StoreHandler::StoreThroughPrototype(
+              isolate(), lookup_start_object_map(), holder, *smi_handler,
+              MaybeObjectDirectHandle::Weak(lookup->GetPropertyCell()));
+          return MaybeObjectHandle(handler);
         }
         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormalDH);
         DCHECK(holder.is_identical_to(receiver));
diff --git a/deps/v8/src/interpreter/bytecode-flags-and-tokens.h b/deps/v8/src/interpreter/bytecode-flags-and-tokens.h
index 0adacdcd93d..d9956be2e8b 100644
--- a/deps/v8/src/interpreter/bytecode-flags-and-tokens.h
+++ b/deps/v8/src/interpreter/bytecode-flags-and-tokens.h
@@ -97,6 +97,23 @@ class StoreLookupSlotFlags {
   DISALLOW_IMPLICIT_CONSTRUCTORS(StoreLookupSlotFlags);
 };

+class ResolveEvalFlags {
+ public:
+  using LanguageModeBit = base::BitField<LanguageMode, 0, 1>;
+  using PrivateNameLookupSkipsOuterClassBit = LanguageModeBit::Next<bool, 1>;
+  static_assert(LanguageModeSize <= LanguageModeBit::kNumValues);
+
+  static int Encode(LanguageMode language_mode,
+                    bool private_name_lookup_skips_outer_class) {
+    return LanguageModeBit::encode(language_mode) |
+           PrivateNameLookupSkipsOuterClassBit::encode(
+               private_name_lookup_skips_outer_class);
+  }
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ResolveEvalFlags);
+};
+
 enum class TryFinallyContinuationToken: int {
   // Fixed value tokens for paths we know we need.
   // Fallthrough is set to -1 to make it the fallthrough case of the jump table,
diff --git a/deps/v8/src/interpreter/bytecode-generator.cc b/deps/v8/src/interpreter/bytecode-generator.cc
index b6b59326301..f6651020361 100644
--- a/deps/v8/src/interpreter/bytecode-generator.cc
+++ b/deps/v8/src/interpreter/bytecode-generator.cc
@@ -3691,7 +3691,10 @@ void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr, Register name) {
     DCHECK_EQ(ClassBoilerplate::kFirstDynamicArgumentIndex,
               args.register_count());

-    VisitForAccumulatorValueOrTheHole(expr->extends());
+    {
+      ClassScope::HeritageParsingScope heritage(expr->scope());
+      VisitForAccumulatorValueOrTheHole(expr->extends());
+    }
     builder()->StoreAccumulatorInRegister(super_class);

     VisitFunctionLiteral(expr->constructor());
@@ -7061,16 +7064,24 @@ void BytecodeGenerator::VisitCall(Call* expr) {
       builder()->MoveRegister(args[receiver_arg_count], runtime_call_args[1]);
     }
     Scope* scope_with_context = current_scope();
+    bool private_name_lookup_skips_outer_class = false;
     if (!scope_with_context->NeedsContext()) {
+      private_name_lookup_skips_outer_class =
+          scope_with_context->private_name_lookup_skips_outer_class();
       scope_with_context = scope_with_context->GetOuterScopeWithContext();
+    } else if (scope_with_context->is_class_scope()) {
+      private_name_lookup_skips_outer_class =
+          scope_with_context->AsClassScope()->IsParsingHeritage();
     }
     if (scope_with_context) {
       eval_calls_.emplace_back(expr, scope_with_context);
     }
+    int eval_flags = ResolveEvalFlags::Encode(
+        language_mode(), private_name_lookup_skips_outer_class);
     builder()
         ->MoveRegister(callee, runtime_call_args[0])
         .MoveRegister(Register::function_closure(), runtime_call_args[2])
-        .LoadLiteral(Smi::FromEnum(language_mode()))
+        .LoadLiteral(Smi::FromInt(eval_flags))
         .StoreAccumulatorInRegister(runtime_call_args[3])
         .LoadLiteral(Smi::FromInt(expr->eval_scope_info_index()))
         .StoreAccumulatorInRegister(runtime_call_args[4])
diff --git a/deps/v8/src/maglev/maglev-graph-builder.cc b/deps/v8/src/maglev/maglev-graph-builder.cc
index d9ed8b2c9fb..05a3fa8fcb5 100644
--- a/deps/v8/src/maglev/maglev-graph-builder.cc
+++ b/deps/v8/src/maglev/maglev-graph-builder.cc
@@ -278,14 +278,31 @@ MaglevGraphBuilder::LazyDeoptResultLocationScope::
   builder_->lazy_deopt_result_location_scope_ = previous_;
 }

-class MaglevGraphBuilder::MaglevSubGraphBuilder::LoopLabel {
+class V8_NODISCARD MaglevGraphBuilder::MaglevSubGraphBuilder::LoopLabel {
  public:
+  LoopLabel(const LoopLabel&) = delete;
+  LoopLabel(LoopLabel&&) = delete;
+  LoopLabel& operator=(const LoopLabel&) = delete;
+  LoopLabel& operator=(LoopLabel&&) = delete;
+
+  ~LoopLabel() {
+    if (merge_state_ != nullptr) {
+      // An early abort exited the subgraph before EndLoop was reached.
+      DCHECK_NULL(sub_builder_->builder_->current_block());
+      merge_state_->MergeDeadLoop(*sub_builder_->dummy_unit_);
+    }
+  }
+
  private:
-  explicit LoopLabel(LoopMergePointInterpreterFrameState* merge_state,
-                     BasicBlock* loop_header)
-      : merge_state_(merge_state), loop_header_(loop_header) {}
+  LoopLabel(MaglevSubGraphBuilder* sub_builder,
+            LoopMergePointInterpreterFrameState* merge_state,
+            BasicBlock* loop_header)
+      : sub_builder_(sub_builder),
+        merge_state_(merge_state),
+        loop_header_(loop_header) {}

   friend class MaglevSubGraphBuilder;
+  MaglevSubGraphBuilder* sub_builder_;
   LoopMergePointInterpreterFrameState* merge_state_ = nullptr;
   BasicBlock* loop_header_;
 };
@@ -420,7 +437,7 @@ MaglevGraphBuilder::MaglevSubGraphBuilder::BeginLoop(
   builder_->ProcessMergePointPredecessors(*loop_state, loop_header_ref);
   builder_->StartNewBlock(nullptr, loop_state, loop_header_ref);

-  return LoopLabel{loop_state, loop_header_ref.block_ptr()};
+  return LoopLabel{this, loop_state, loop_header_ref.block_ptr()};
 }

 template <typename ControlNodeT, typename... Args>
@@ -477,8 +494,12 @@ void MaglevGraphBuilder::MaglevSubGraphBuilder::MergeDeadInterpreterFrameState(
 }

 void MaglevGraphBuilder::MaglevSubGraphBuilder::EndLoop(LoopLabel* loop_label) {
+  // Ensure EndLoop is called only once and disarm ~LoopLabel().
+  LoopMergePointInterpreterFrameState* merge_state = loop_label->merge_state_;
+  DCHECK_NOT_NULL(merge_state);
+  loop_label->merge_state_ = nullptr;
   if (builder_->current_block() == nullptr) {
-    loop_label->merge_state_->MergeDeadLoop(*dummy_unit_);
+    merge_state->MergeDeadLoop(*dummy_unit_);
     return;
   }

@@ -486,11 +507,11 @@ void MaglevGraphBuilder::MaglevSubGraphBuilder::EndLoop(LoopLabel* loop_label) {
       builder_->FinishBlockNoAbort<JumpLoop>({}, loop_label->loop_header_);
   {
     BorrowParentKnownNodeAspectsAndVOs borrow(this);
-    loop_label->merge_state_->MergeLoop(
-        builder_->graph(), builder_->is_tracing(), *dummy_unit_,
-        variable_frame_, block, builder_->GetLatestCheckpointedFrame());
+    merge_state->MergeLoop(builder_->graph(), builder_->is_tracing(),
+                           *dummy_unit_, variable_frame_, block,
+                           builder_->GetLatestCheckpointedFrame());
   }
-  block->set_predecessor_id(loop_label->merge_state_->predecessor_count() - 1);
+  block->set_predecessor_id(merge_state->predecessor_count() - 1);
 }

 void MaglevGraphBuilder::MaglevSubGraphBuilder::Bind(Label* label) {
@@ -9011,19 +9032,12 @@ MaybeReduceResult MaglevGraphBuilder::TryReduceFunctionPrototypeCall(

 MaybeReduceResult MaglevGraphBuilder::TryReduceFunctionPrototypeApply(
     compiler::JSFunctionRef target, CallArguments& args) {
-  compiler::OptionalHeapObjectRef maybe_receiver;
-  if (current_speculation_feedback().IsValid()) {
-    const compiler::ProcessedFeedback& processed_feedback =
-        broker()->GetFeedbackForCall(current_speculation_feedback());
-    DCHECK_EQ(processed_feedback.kind(), compiler::ProcessedFeedback::kCall);
-    const compiler::CallFeedback& call_feedback = processed_feedback.AsCall();
-    if (call_feedback.call_feedback_content() ==
-        CallFeedbackContent::kReceiver) {
-      maybe_receiver = call_feedback.target();
-    }
-  }
+  // We should have taken the `BuildCallWithFeedback` path for the typical
+  // Function.prototype.apply speculation-based optimization. If we are on this
+  // code path, we must be inside an apply inside another inlining and shouldn't
+  // use the feedback receiver.
   return TryReduceFunctionPrototypeApplyCallWithReceiver(
-      maybe_receiver, args, current_speculation_feedback());
+      {}, args, current_speculation_feedback());
 }

 namespace {
@@ -11533,7 +11547,7 @@ MaybeReduceResult MaglevGraphBuilder::TryReduceCallForNewClosure(

 MaybeReduceResult
 MaglevGraphBuilder::TryReduceFunctionPrototypeApplyCallWithReceiver(
-    compiler::OptionalHeapObjectRef maybe_receiver, CallArguments& args,
+    compiler::OptionalJSFunctionRef maybe_receiver, CallArguments& args,
     const compiler::FeedbackSource& feedback_source) {
   if (args.mode() != CallArguments::kDefault) return {};

diff --git a/deps/v8/src/maglev/maglev-graph-builder.h b/deps/v8/src/maglev/maglev-graph-builder.h
index a439094bb6d..f3d9c57f189 100644
--- a/deps/v8/src/maglev/maglev-graph-builder.h
+++ b/deps/v8/src/maglev/maglev-graph-builder.h
@@ -309,7 +309,7 @@ class MaglevGraphBuilder {
     using Label = Base::Label;
     using LabelForTrackingInterpreterFrameState =
         Base::LabelForTrackingInterpreterFrameState;
-    class LoopLabel;
+    class V8_NODISCARD LoopLabel;

     MaglevSubGraphBuilder(MaglevGraphBuilder* builder, int variable_count);
     LoopLabel BeginLoop(std::initializer_list<Variable*> loop_vars);
@@ -1072,7 +1072,7 @@ class MaglevGraphBuilder {
       compiler::OptionalSharedFunctionInfoRef maybe_shared,
       CallArguments& args);
   MaybeReduceResult TryReduceFunctionPrototypeApplyCallWithReceiver(
-      compiler::OptionalHeapObjectRef maybe_receiver, CallArguments& args,
+      compiler::OptionalJSFunctionRef maybe_receiver, CallArguments& args,
       const compiler::FeedbackSource& feedback_source);

   template <typename CallNode, typename... Args>
diff --git a/deps/v8/src/maglev/maglev-graph-optimizer.cc b/deps/v8/src/maglev/maglev-graph-optimizer.cc
index a78420a1338..e0e64964a52 100644
--- a/deps/v8/src/maglev/maglev-graph-optimizer.cc
+++ b/deps/v8/src/maglev/maglev-graph-optimizer.cc
@@ -591,6 +591,20 @@ bool MaglevGraphOptimizer::IsRangeLessEqual(ValueNode* lhs, ValueNode* rhs) {
   return ranges_->IsLessEqualConstraint(reducer_.current_block(), lhs, rhs);
 }

+ProcessResult MaglevGraphOptimizer::OverwriteWith(Opcode opcode) {
+  TRACE(TraceColor::kDarkGreen << "Overwriting "
+                               << PrintNodeLabel(current_node()) << " with "
+                               << opcode);
+
+  current_node()->OverwriteWith(opcode);
+
+  // Since we've changed the type of the node, we need to trigger a revisit,
+  // otherwise the next processors would see a stale static type for this node
+  // and will thus wrongly treat it as a node of the old type instead of the new
+  // one.
+  return ProcessResult::kRevisit;
+}
+
 ProcessResult MaglevGraphOptimizer::ReplaceWith(ValueNode* node) {
   // If current node is not a value node, we shouldn't try to replace it.
   CHECK(current_node()->Cast<ValueNode>());
@@ -2697,7 +2711,7 @@ UNTAGGING_CASE(UnsafeNumberOrOddballToHoleyFloat64, HoleyFloat64,
     REPLACE_AND_RETURN_IF_DONE(GetUntaggedValueWithRepresentation(    \
         node->input_node(0), UseRepresentation::k##Repr, ConvType));  \
     if (reducer_.CheckType(node->input_node(0), ConvType)) {          \
-      node->OverwriteWith(Opcode::k##UnsafeNode);                     \
+      return OverwriteWith(Opcode::k##UnsafeNode);                    \
     }                                                                 \
     return ProcessResult::kContinue;                                  \
   }
@@ -2749,7 +2763,7 @@ ProcessResult MaglevGraphOptimizer::VisitCheckedSmiUntag(
   // }
   // DCHECK(maybe_input.IsFail());
   if (reducer_.CheckType(node->input_node(0), NodeType::kSmi)) {
-    node->OverwriteWith(Opcode::kUnsafeSmiUntag);
+    return OverwriteWith(Opcode::kUnsafeSmiUntag);
   }
   return ProcessResult::kContinue;
 }
@@ -2771,7 +2785,7 @@ ProcessResult MaglevGraphOptimizer::VisitCheckedNumberToFloat64(
     return ProcessResult::kTruncateBlock;
   }
   if (reducer_.CheckType(node->input_node(0), NodeType::kNumber)) {
-    node->OverwriteWith(Opcode::kUnsafeNumberToFloat64);
+    return OverwriteWith(Opcode::kUnsafeNumberToFloat64);
   }
   return ProcessResult::kContinue;
 }
@@ -2795,7 +2809,7 @@ ProcessResult MaglevGraphOptimizer::VisitUnsafeFloat64ToHoleyFloat64(
   // undefined NaN since the widen was chosen, and widening those would give
   // them back their meaning.
   if (node->ValueInput().node()->MayBeHoleOrUndefinedNan()) {
-    node->OverwriteWith(Opcode::kChangeFloat64ToHoleyFloat64);
+    return OverwriteWith(Opcode::kChangeFloat64ToHoleyFloat64);
   }
   return ProcessResult::kContinue;
 }
@@ -3975,7 +3989,7 @@ ProcessResult MaglevGraphOptimizer::VisitTruncateCheckedNumberAsSafeIntToInt32(
     return ReplaceWith(node->input_node(0)->input_node(0));
   }
   if (reducer_.CheckType(node->input_node(0), NodeType::kNumber)) {
-    node->OverwriteWith(Opcode::kTruncateUnsafeNumberAsSafeIntToInt32);
+    return OverwriteWith(Opcode::kTruncateUnsafeNumberAsSafeIntToInt32);
   }
   return ProcessResult::kContinue;
 }
diff --git a/deps/v8/src/maglev/maglev-graph-optimizer.h b/deps/v8/src/maglev/maglev-graph-optimizer.h
index 7e98d1059f2..56b77b7055a 100644
--- a/deps/v8/src/maglev/maglev-graph-optimizer.h
+++ b/deps/v8/src/maglev/maglev-graph-optimizer.h
@@ -179,6 +179,8 @@ class V8_EXPORT_PRIVATE MaglevGraphOptimizer {
   template <typename FixedArrayT, typename NodeT>
   MaybeReduceResult AbortIfInvalidFixedArrayIndex(NodeT* node);

+  ProcessResult OverwriteWith(Opcode opcode);
+
   ProcessResult ReplaceWith(ValueNode* node);

   template <typename NodeT, typename... Args>
diff --git a/deps/v8/src/maglev/maglev-ir.h b/deps/v8/src/maglev/maglev-ir.h
index c9adf3113ae..a2badf6c94c 100644
--- a/deps/v8/src/maglev/maglev-ir.h
+++ b/deps/v8/src/maglev/maglev-ir.h
@@ -5420,7 +5420,9 @@ class CreateArrayLiteral : public FixedInputValueNodeT<0, CreateArrayLiteral> {
   static constexpr OpProperties kProperties =
       OpProperties::Call() | OpProperties::CanAllocate() |
       OpProperties::CanThrow() | OpProperties::LazyDeopt() |
-      OpProperties::NotIdempotent();
+      OpProperties::NotIdempotent() |
+      // The runtime call may make prototype maps fast.
+      OpProperties::CanWrite();

   int MaxCallStackArgs() const;
   void SetValueLocationConstraints();
@@ -5488,7 +5490,9 @@ class CreateObjectLiteral
   static constexpr OpProperties kProperties =
       OpProperties::Call() | OpProperties::CanAllocate() |
       OpProperties::CanThrow() | OpProperties::LazyDeopt() |
-      OpProperties::NotIdempotent();
+      OpProperties::NotIdempotent() |
+      // The runtime call may make prototype maps fast.
+      OpProperties::CanWrite();

   int MaxCallStackArgs() const;
   void SetValueLocationConstraints();
diff --git a/deps/v8/src/maglev/maglev-known-node-aspects.h b/deps/v8/src/maglev/maglev-known-node-aspects.h
index dd1ce8cc385..7b64d3b57c0 100644
--- a/deps/v8/src/maglev/maglev-known-node-aspects.h
+++ b/deps/v8/src/maglev/maglev-known-node-aspects.h
@@ -460,12 +460,10 @@ class KnownNodeAspects {
   }

   const NodeInfo* TryGetInfoFor(ValueNode* node) const {
-    node = node->Unwrap();
     return const_cast<KnownNodeAspects*>(this)->TryGetInfoFor(node);
   }

   NodeInfo* TryGetInfoFor(ValueNode* node) {
-    node = node->Unwrap();
     auto info_it = FindInfo(node);
     if (!IsValid(info_it)) return nullptr;
     return &info_it->second;
@@ -481,8 +479,8 @@ class KnownNodeAspects {

   NodeInfo* GetOrCreateInfoFor(compiler::JSHeapBroker* broker,
                                ValueNode* node) {
-    node = node->Unwrap();
-    auto info_it = FindInfo(node);
+    node = UnwrapNode(node);
+    auto info_it = node_infos_.find(node);
     if (IsValid(info_it)) return &info_it->second;
     auto res = &node_infos_.emplace(node, NodeInfo()).first->second;
     res->IntersectType(node->GetStaticType(broker));
@@ -490,7 +488,6 @@ class KnownNodeAspects {
   }

   ValueNode* TryGetAlternativeFor(ValueNode* node, UseRepresentation repr) {
-    node = node->Unwrap();
     auto info_it = FindInfo(node);
     if (!IsValid(info_it)) return nullptr;
     return info_it->second.alternative().get(repr);
@@ -1018,12 +1015,58 @@ class KnownNodeAspects {
     return it->second->UnwrapIdentities();
   }

+  // Only unwrap conversions that preserve `NodeType` invariants across
+  // representations (e.g. `kSmi` means Smi-tagged for tagged values, but only
+  // Smi-sized for untagged values).
+  // TODO(496266449): Remove once `kTagged` is split into `kSmi` and
+  // `kTaggedPointer` representations.
+  static ValueNode* UnwrapNode(ValueNode* node) {
+    while (true) {
+      if (node->Is<Identity>() || node->Is<ReturnedValue>()) {
+        node = node->input_node(0);
+        continue;
+      }
+      if (!node->is_conversion()) break;
+      switch (node->opcode()) {
+        case Opcode::kCheckedNumberToInt32:
+        case Opcode::kCheckedNumberToFloat64:
+        case Opcode::kUnsafeNumberToFloat64:
+        case Opcode::kCheckedObjectToIndex:
+        case Opcode::kUnsafeInt32ToUint32:
+          return node;
+        // kForceHeapNumber allocates a HeapNumber even for Smi-sized inputs.
+        case Opcode::kInt32ToNumber:
+          if (node->Cast<Int32ToNumber>()->conversion_mode() ==
+              NumberConversionMode::kForceHeapNumber) {
+            return node;
+          }
+          break;
+        case Opcode::kFloat64ToTagged:
+          if (node->Cast<Float64ToTagged>()->conversion_mode() ==
+              NumberConversionMode::kForceHeapNumber) {
+            return node;
+          }
+          break;
+        case Opcode::kHoleyFloat64ToTagged:
+          if (node->Cast<HoleyFloat64ToTagged>()->conversion_mode() ==
+              NumberConversionMode::kForceHeapNumber) {
+            return node;
+          }
+          break;
+        default:
+          break;
+      }
+      node = node->input_node(0);
+    }
+    return node;
+  }
+
   NodeInfos::iterator FindInfo(ValueNode* node) {
-    node = node->Unwrap();
+    node = UnwrapNode(node);
     return node_infos_.find(node);
   }
   NodeInfos::const_iterator FindInfo(ValueNode* node) const {
-    node = node->Unwrap();
+    node = UnwrapNode(node);
     return node_infos_.find(node);
   }
   bool IsValid(NodeInfos::iterator& it) { return it != node_infos_.end(); }
diff --git a/deps/v8/src/maglev/maglev-reducer-inl.h b/deps/v8/src/maglev/maglev-reducer-inl.h
index 41371336573..50d7d226378 100644
--- a/deps/v8/src/maglev/maglev-reducer-inl.h
+++ b/deps/v8/src/maglev/maglev-reducer-inl.h
@@ -836,6 +836,8 @@ ReduceResult MaglevReducer<BaseT>::BuildInitializeStore_Tagged(
   }

   DCHECK(value->is_tagged());
+  RETURN_IF_ABORT(BuildStoreTaggedField(object, value, desc.offset, store_mode,
+                                        PropertyKey::None(), maybe_assigned));
   if (InlinedAllocation* inlined_value = value->TryCast<InlinedAllocation>()) {
     // Add to the escape set.
     auto escape_deps = graph()->allocations_escape_map().find(object);
@@ -845,11 +847,10 @@ ReduceResult MaglevReducer<BaseT>::BuildInitializeStore_Tagged(
     auto& elided_map = graph()->allocations_elide_map();
     auto elided_deps = elided_map.try_emplace(inlined_value, zone()).first;
     elided_deps->second.push_back(object);
-    inlined_value->AddNonEscapingUses();
+    AddNonEscapingUses(inlined_value, 1);
   }

-  return BuildStoreTaggedField(object, value, desc.offset, store_mode,
-                               PropertyKey::None(), maybe_assigned);
+  return ReduceResult::Done();
 }

 template <typename BaseT>
diff --git a/deps/v8/src/objects/deoptimization-data.h b/deps/v8/src/objects/deoptimization-data.h
index bd956028244..b63f4e4a6d5 100644
--- a/deps/v8/src/objects/deoptimization-data.h
+++ b/deps/v8/src/objects/deoptimization-data.h
@@ -92,7 +92,10 @@ class DeoptimizationLiteral {
     return literal;
   }

-  IndirectHandle<Object> object() const { return object_; }
+  bool IsObject(IndirectHandle<Object> object) const {
+    return kind_ == DeoptimizationLiteralKind::kObject &&
+           object_.equals(object);
+  }

   bool operator==(const DeoptimizationLiteral& other) const {
     if (kind_ != other.kind_) {
diff --git a/deps/v8/src/objects/module-inl.h b/deps/v8/src/objects/module-inl.h
index fb9d42c9ba8..e7097827097 100644
--- a/deps/v8/src/objects/module-inl.h
+++ b/deps/v8/src/objects/module-inl.h
@@ -8,6 +8,7 @@
 #include "src/objects/module.h"
 // Include the non-inl header before the rest of the headers.

+#include "src/objects/cell-inl.h"
 #include "src/objects/js-promise-inl.h"
 #include "src/objects/oddball-predicates-inl.h"
 #include "src/objects/scope-info.h"
@@ -172,6 +173,7 @@ void SourceTextModule::DecrementPendingAsyncDependencies() {

 Tagged<ObjectHashTable> Module::exports() const { return exports_.load(); }
 void Module::set_exports(Tagged<ObjectHashTable> value, WriteBarrierMode mode) {
+  CHECK(!ExportsFinalized());
   exports_.store(this, value, mode);
 }

@@ -197,6 +199,16 @@ void Module::set_deferred_module_namespace(
   deferred_module_namespace_.store(this, value, mode);
 }

+bool Module::ExportsFinalized() const {
+  bool res =
+      (!IsUndefined(module_namespace()) &&
+       IsJSModuleNamespace(Cast<Cell>(module_namespace())->value())) ||
+      (!IsUndefined(deferred_module_namespace()) &&
+       IsJSModuleNamespace(Cast<Cell>(deferred_module_namespace())->value()));
+  DCHECK_IMPLIES(res, status() >= kLinking);
+  return res;
+}
+
 Tagged<Module> JSModuleNamespace::module() const { return module_.load(); }

 void JSModuleNamespace::set_module(Tagged<Module> value,
diff --git a/deps/v8/src/objects/module.h b/deps/v8/src/objects/module.h
index 925b7d36166..43118f6e11a 100644
--- a/deps/v8/src/objects/module.h
+++ b/deps/v8/src/objects/module.h
@@ -110,6 +110,11 @@ V8_OBJECT class Module : public HeapObject {
   inline void set_exception(Tagged<Object> value,
                             WriteBarrierMode mode = UPDATE_WRITE_BARRIER);

+  // Once a module namespace (normal or deferred) has been created in
+  // GetModuleNamespace, all star exports have been fetched and {exports} is
+  // finalized (must not be mutated or rehashed as ICs index into it).
+  inline bool ExportsFinalized() const;
+
   inline Tagged<UnionOf<JSPromise, Undefined>> top_level_capability() const;
   inline void set_top_level_capability(
       Tagged<UnionOf<JSPromise, Undefined>> value,
diff --git a/deps/v8/src/objects/source-text-module.cc b/deps/v8/src/objects/source-text-module.cc
index 0c50a5139d6..8a9cb6cda8a 100644
--- a/deps/v8/src/objects/source-text-module.cc
+++ b/deps/v8/src/objects/source-text-module.cc
@@ -371,11 +371,14 @@ MaybeHandle<Cell> SourceTextModule::ResolveExportUsingStarExports(

     if (!unique_cell.is_null()) {
       // Found a unique star export for this name.
-      Handle<ObjectHashTable> exports(module->exports(), isolate);
-      DCHECK(IsTheHole(exports->Lookup(export_name)));
-      exports =
-          ObjectHashTable::Put(isolate, exports, export_name, unique_cell);
-      module->set_exports(*exports);
+      if (module->status() <= kLinking) {
+        DCHECK(!module->ExportsFinalized());
+        Handle<ObjectHashTable> exports(module->exports(), isolate);
+        DCHECK(IsTheHole(exports->Lookup(export_name)));
+        exports =
+            ObjectHashTable::Put(isolate, exports, export_name, unique_cell);
+        module->set_exports(*exports);
+      }
       return unique_cell;
     }
   }
@@ -773,8 +776,7 @@ void SourceTextModule::FetchStarExports(Isolate* isolate,
   DCHECK_GE(module->status(), Module::kLinking);

   // Shortcut.
-  if (!IsUndefined(module->module_namespace()) &&
-      IsJSModuleNamespace(Cast<Cell>(module->module_namespace())->value())) {
+  if (module->ExportsFinalized()) {
     return;
   }

diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc
index 388e4f1c96e..c853b24dc73 100644
--- a/deps/v8/src/parsing/parser.cc
+++ b/deps/v8/src/parsing/parser.cc
@@ -744,12 +744,20 @@ void Parser::ParseProgram(Isolate* isolate, DirectHandle<Script> script,
   }

   scanner_.Initialize();
+  std::optional<ClassScope::HeritageParsingScope> heritage;
+  if (V8_UNLIKELY(flags().private_name_lookup_skips_outer_class() &&
+                  original_scope_->is_class_scope())) {
+    heritage.emplace(original_scope_->AsClassScope());
+  }
   FunctionLiteral* result =
       DoParseProgram(isolate, info, script->eval_from_position());
   if (flags().allow_heap_allocation()) {
     HandleDebugMagicComments(isolate, script);
   }
   if (result == nullptr) return;
+  if (V8_UNLIKELY(flags().private_name_lookup_skips_outer_class())) {
+    result->scope()->RecordNeedsPrivateNameContextChainRecalc();
+  }
   result->scope()->set_is_hoisted_in_context(
       info->flags().is_hoisted_in_context());
   if (flags().allow_heap_allocation()) {
@@ -1252,6 +1260,9 @@ FunctionLiteral* Parser::DoParseFunction(Isolate* isolate, ParseInfo* info,
     }

     if (has_error()) return nullptr;
+    if (V8_UNLIKELY(flags().private_name_lookup_skips_outer_class())) {
+      result->scope()->RecordNeedsPrivateNameContextChainRecalc();
+    }
     result->set_requires_instance_members_initializer(
         flags().requires_instance_members_initializer());
     result->set_class_scope_has_private_brand(
diff --git a/deps/v8/src/runtime/runtime-compiler.cc b/deps/v8/src/runtime/runtime-compiler.cc
index e998c4d59f4..f195b42d310 100644
--- a/deps/v8/src/runtime/runtime-compiler.cc
+++ b/deps/v8/src/runtime/runtime-compiler.cc
@@ -13,6 +13,7 @@
 #include "src/execution/arguments-inl.h"
 #include "src/execution/frames-inl.h"
 #include "src/execution/isolate-inl.h"
+#include "src/interpreter/bytecode-flags-and-tokens.h"
 #include "src/objects/abstract-code-inl.h"
 #include "src/objects/js-array-buffer-inl.h"
 #include "src/objects/objects-inl.h"
@@ -826,7 +827,8 @@ RUNTIME_FUNCTION(Runtime_LogOrTraceOptimizedOSREntry) {
 static Tagged<Object> CompileGlobalEval(
     Isolate* isolate, Handle<i::Object> source_object,
     DirectHandle<SharedFunctionInfo> outer_info, LanguageMode language_mode,
-    int eval_scope_info_index, int eval_position) {
+    int eval_scope_info_index, int eval_position,
+    bool private_name_lookup_skips_outer_class) {
   DirectHandle<NativeContext> native_context = isolate->native_context();

   // Check if native context allows code generation from
@@ -865,7 +867,8 @@ static Tagged<Object> CompileGlobalEval(
       isolate, compiled,
       Compiler::GetFunctionFromEval(
           isolate, source.ToHandleChecked(), outer_info, context, language_mode,
-          restriction, kNoSourcePosition, eval_position),
+          restriction, kNoSourcePosition, eval_position,
+          ParsingWhileDebugging::kNo, private_name_lookup_skips_outer_class),
       ReadOnlyRoots(isolate).exception());
   return *compiled;
 }
@@ -882,13 +885,17 @@ RUNTIME_FUNCTION(Runtime_ResolvePossiblyDirectEval) {
     return *callee;
   }

-  DCHECK(is_valid_language_mode(args.smi_value_at(3)));
-  LanguageMode language_mode = static_cast<LanguageMode>(args.smi_value_at(3));
+  int eval_flags = args.smi_value_at(3);
+  LanguageMode language_mode =
+      interpreter::ResolveEvalFlags::LanguageModeBit::decode(eval_flags);
+  bool private_name_lookup_skips_outer_class = interpreter::ResolveEvalFlags::
+      PrivateNameLookupSkipsOuterClassBit::decode(eval_flags);
   DirectHandle<SharedFunctionInfo> outer_info(args.at<JSFunction>(2)->shared(),
                                               isolate);
   return CompileGlobalEval(isolate, args.at<Object>(1), outer_info,
                            language_mode, args.smi_value_at(4),
-                           args.smi_value_at(5));
+                           args.smi_value_at(5),
+                           private_name_lookup_skips_outer_class);
 }

 #ifdef V8_ENABLE_SPARKPLUG_PLUS
diff --git a/deps/v8/src/runtime/runtime-wasm.cc b/deps/v8/src/runtime/runtime-wasm.cc
index c7a5cfee4b1..ef593decb3c 100644
--- a/deps/v8/src/runtime/runtime-wasm.cc
+++ b/deps/v8/src/runtime/runtime-wasm.cc
@@ -1025,9 +1025,11 @@ bool ExecuteWasmDebugBreaks(
   if (debug_info->IsStepping(frame) && !debug_info->IsFrameBlackboxed(frame)) {
     debug_info->ClearStepping(isolate);
     StepAction step_action = isolate->debug()->last_step_action();
+    v8::debug::BreakReasons break_reasons =
+        isolate->debug()->scheduled_break_on_next_function_call();
     isolate->debug()->ClearStepping();
     isolate->debug()->OnDebugBreak(isolate->factory()->empty_fixed_array(),
-                                   step_action);
+                                   step_action, break_reasons);
     return true;
   }

diff --git a/deps/v8/src/wasm/wasm-debug.cc b/deps/v8/src/wasm/wasm-debug.cc
index 2a45a67074f..1679c9c87a7 100644
--- a/deps/v8/src/wasm/wasm-debug.cc
+++ b/deps/v8/src/wasm/wasm-debug.cc
@@ -490,7 +490,12 @@ class DebugInfoImpl {

   bool IsStepping(WasmFrame* frame) {
     Isolate* isolate = frame->isolate();
-    if (isolate->debug()->last_step_action() == StepInto) return true;
+    if (isolate->debug()->last_step_action() == StepInto ||
+        isolate->debug()->break_on_next_function_call() ||
+        isolate->debug()->scheduled_break_on_function_call()) {
+      return true;
+    }
+    if (isolate->debug()->last_step_action() == StepNone) return false;
     base::MutexGuard guard(&mutex_);
     auto it = per_isolate_data_.find(isolate);
     return it != per_isolate_data_.end() &&
diff --git a/deps/v8/test/cctest/compiler/test-code-generator.cc b/deps/v8/test/cctest/compiler/test-code-generator.cc
index 004525919d8..bf91b4ca89d 100644
--- a/deps/v8/test/cctest/compiler/test-code-generator.cc
+++ b/deps/v8/test/cctest/compiler/test-code-generator.cc
@@ -1126,7 +1126,8 @@ constexpr int TestEnvironment::kDoubleConstantCount;
 class CodeGeneratorTester {
  public:
   explicit CodeGeneratorTester(TestEnvironment* environment,
-                               int extra_stack_space = 0)
+                               int extra_stack_space = 0,
+                               int scratch_spill_slots = 0)
       : zone_(environment->main_zone()),
         info_(base::ArrayVector("test"), environment->main_zone(),
               CodeKind::FOR_TESTING),
@@ -1161,6 +1162,11 @@ class CodeGeneratorTester {
         i++;
       }
     }
+    if (scratch_spill_slots > 0) {
+      int end_slot = frame_.AllocateSpillSlot(
+          scratch_spill_slots * kSystemPointerSize, kSimd128Size);
+      first_scratch_spill_slot_ = end_slot - scratch_spill_slots + 1;
+    }

     constexpr size_t kMaxUnoptimizedFrameHeight = 0;
     constexpr size_t kMaxPushedArgumentCount = 0;
@@ -1342,6 +1348,8 @@ class CodeGeneratorTester {
     return Finalize();
   }

+  int first_scratch_spill_slot() const { return first_scratch_spill_slot_; }
+
  private:
   Zone* zone_;
   OptimizedCompilationInfo info_;
@@ -1350,6 +1358,7 @@ class CodeGeneratorTester {
   CodeGenerator* generator_;
   // List of operands to be moved from stack parameters to spill slots.
   std::vector<std::pair<LocationOperand, LocationOperand>> spill_slots_;
+  int first_scratch_spill_slot_ = 0;
 };

 // The following fuzz tests will assemble a lot of moves, wrap them in
@@ -1639,6 +1648,54 @@ TEST(AssembleTailCallGap) {
   }
 }

+TEST(PopTempStackSlots) {
+  if (kSystemPointerSize == 8 && !TestSimd128Moves()) return;
+
+  constexpr MachineRepresentation kTwoSlotRep =
+      kSystemPointerSize == 8 ? MachineRepresentation::kSimd128
+                              : MachineRepresentation::kFloat64;
+
+  TestEnvironment env;
+  Handle<FixedArray> state_in = env.GenerateInitialState();
+
+  // Test both a small number of temporary stack slots and a larger count whose
+  // byte size exceeds 4095 and is not a multiple of 4096.
+  for (int num_cycles : {4, 260}) {
+    const int scratch_slots = num_cycles * 4;
+    CodeGeneratorTester c(&env, 0, scratch_slots);
+    ParallelMove* moves = env.main_zone()->New<ParallelMove>(env.main_zone());
+
+    for (int i = 0; i < num_cycles; i++) {
+      int base = c.first_scratch_spill_slot() + i * 4;
+      AllocatedOperand pair_lo(LocationOperand::STACK_SLOT, kTwoSlotRep,
+                               base + 1);
+      AllocatedOperand pair_hi(LocationOperand::STACK_SLOT, kTwoSlotRep,
+                               base + 3);
+      AllocatedOperand slot_0(LocationOperand::STACK_SLOT,
+                              MachineRepresentation::kTagged, base + 0);
+      AllocatedOperand slot_1(LocationOperand::STACK_SLOT,
+                              MachineRepresentation::kTagged, base + 1);
+      AllocatedOperand slot_2(LocationOperand::STACK_SLOT,
+                              MachineRepresentation::kTagged, base + 2);
+      AllocatedOperand slot_3(LocationOperand::STACK_SLOT,
+                              MachineRepresentation::kTagged, base + 3);
+      moves->AddMove(pair_lo, pair_hi);
+      moves->AddMove(slot_2, slot_0);
+      moves->AddMove(slot_3, slot_1);
+    }
+
+    c.CheckAssembleMoves(moves);
+
+    Handle<Code> test = c.FinalizeForExecuting();
+    if (v8_flags.print_code) {
+      Print(*test);
+    }
+
+    DirectHandle<FixedArray> actual = env.Run(test, state_in);
+    env.CheckState(actual, state_in);
+  }
+}
+
 #if V8_TARGET_ARCH_X64
 TEST(TurboFanFrameSlotAlignment) {
   FLAG_SCOPE(enforce_x64_16byte_alignment);
diff --git a/deps/v8/test/cctest/test-api-interceptors.cc b/deps/v8/test/cctest/test-api-interceptors.cc
index 452bc8dfa2d..acb34f9d864 100644
--- a/deps/v8/test/cctest/test-api-interceptors.cc
+++ b/deps/v8/test/cctest/test-api-interceptors.cc
@@ -6,6 +6,7 @@

 #include <optional>

+#include "include/v8-fast-api-calls.h"
 #include "include/v8-function.h"
 #include "src/api/api-inl.h"
 #include "src/codegen/compilation-cache.h"
@@ -6373,6 +6374,371 @@ TEST(PreprocessExceptionFromInterceptorsWithDescriptorCallback) {
                                           is_descriptor_callback_available);
 }

+#if V8_ENABLE_WEBASSEMBLY && !defined(V8_ENABLE_CET_SHADOW_STACK)
+namespace {
+
+void InvokeArgAndMaybeThrowCallback(
+    const v8::FunctionCallbackInfo<v8::Value>& info) {
+  v8::Isolate* isolate = info.GetIsolate();
+  if (info.Length() > 0 && info[0]->IsFunction()) {
+    v8::Local<v8::Context> context = isolate->GetCurrentContext();
+    std::ignore = info[0].As<v8::Function>()->Call(context, context->Global(),
+                                                   0, nullptr);
+  }
+  if (info.Length() > 1 && info[1]->IsTrue()) {
+    isolate->ThrowError("Direct callback error.");
+  }
+}
+
+v8::Intercepted UnwindInnerStackThenThrowGetter(
+    v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
+  v8::Isolate* isolate = info.GetIsolate();
+  v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
+  CompileRun(ctx, "try { globalThis.stress_throw(); } catch {}")
+      .ToLocalChecked();
+  isolate->ThrowError("After nested unwind.");
+  return v8::Intercepted::kYes;
+}
+
+void SecondaryStackFastApiCallback(v8::Local<v8::Object> receiver, int32_t mode,
+                                   v8::FastApiCallbackOptions& options) {
+  v8::Isolate* isolate = options.isolate;
+  v8::HandleScope handle_scope(isolate);
+  if (mode == 1 || mode == 3) {
+    v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
+    const char* holder_name =
+        mode == 1 ? "interceptor_obj" : "unwind_interceptor_obj";
+    v8::Local<v8::Object> obj = ctx->Global()
+                                    ->Get(ctx, v8_str(holder_name))
+                                    .ToLocalChecked()
+                                    .As<v8::Object>();
+    std::ignore = obj->Get(ctx, v8_str("prop"));
+  } else if (mode == 2) {
+    isolate->ThrowError("Fast API error.");
+  }
+}
+
+#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
+v8::AnyCType SecondaryStackFastApiCallbackPatch(v8::AnyCType receiver,
+                                                v8::AnyCType mode,
+                                                v8::AnyCType options) {
+  v8::AnyCType ret;
+  SecondaryStackFastApiCallback(receiver.object_value, mode.int32_value,
+                                *options.options_value);
+  return ret;
+}
+#endif  // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
+
+void SecondaryStackSlowApiCallback(
+    const v8::FunctionCallbackInfo<v8::Value>& info) {
+  v8::Isolate* isolate = info.GetIsolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
+  int32_t mode = info[0]->Int32Value(ctx).FromJust();
+  CHECK(mode == 1 || mode == 3);
+  const char* holder_name =
+      mode == 1 ? "interceptor_obj" : "unwind_interceptor_obj";
+  v8::Local<v8::Object> obj = ctx->Global()
+                                  ->Get(ctx, v8_str(holder_name))
+                                  .ToLocalChecked()
+                                  .As<v8::Object>();
+  std::ignore = obj->Get(ctx, v8_str("prop"));
+}
+
+void RunPreprocessExceptionOnWasmSecondaryStackTest(v8::Isolate* isolate,
+                                                    void* reserved_pages,
+                                                    size_t reserve_size) {
+  v8::HandleScope handle_scope(isolate);
+  isolate->SetExceptionPropagationCallback(PreprocessExceptionTestCallback);
+
+  v8::Local<v8::FunctionTemplate> ctor =
+      v8::FunctionTemplate::New(isolate, InvokeArgAndMaybeThrowCallback);
+  ctor->SetClassName(v8_str("MyClass"));
+
+  PreprocessExceptionTestConfig pet_config;
+  pet_config.getter_should_throw = true;
+  v8::Local<v8::FunctionTemplate> interceptor_ctor =
+      v8::FunctionTemplate::New(isolate);
+  interceptor_ctor->SetClassName(v8_str("InterceptorHolder"));
+  interceptor_ctor->InstanceTemplate()->SetHandler(
+      v8::NamedPropertyHandlerConfiguration(PETNamedGetter, nullptr, nullptr,
+                                            nullptr, nullptr,
+                                            MakeData(isolate, &pet_config)));
+
+  v8::Local<v8::FunctionTemplate> unwind_interceptor_ctor =
+      v8::FunctionTemplate::New(isolate);
+  unwind_interceptor_ctor->SetClassName(v8_str("UnwindHolder"));
+  unwind_interceptor_ctor->InstanceTemplate()->SetHandler(
+      v8::NamedPropertyHandlerConfiguration(UnwindInnerStackThenThrowGetter));
+
+#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
+  v8::CFunction c_func = v8::CFunction::Make(
+      SecondaryStackFastApiCallback, SecondaryStackFastApiCallbackPatch);
+#else
+  v8::CFunction c_func = v8::CFunction::Make(SecondaryStackFastApiCallback);
+#endif
+  v8::Local<v8::FunctionTemplate> fast_api_tpl = v8::FunctionTemplate::New(
+      isolate, SecondaryStackSlowApiCallback, v8::Local<v8::Value>(),
+      v8::Local<v8::Signature>(), 1, v8::ConstructorBehavior::kThrow,
+      v8::SideEffectType::kHasSideEffect, &c_func);
+
+  v8::Local<v8::Context> ctx = v8::Context::New(isolate);
+  v8::Context::Scope context_scope(ctx);
+
+  v8::Local<v8::Object> global = ctx->Global();
+  global->Set(ctx, v8_str("MyClass"), ctor->GetFunction(ctx).ToLocalChecked())
+      .FromJust();
+  global
+      ->Set(ctx, v8_str("interceptor_obj"),
+            interceptor_ctor->InstanceTemplate()
+                ->NewInstance(ctx)
+                .ToLocalChecked())
+      .FromJust();
+  global
+      ->Set(ctx, v8_str("unwind_interceptor_obj"),
+            unwind_interceptor_ctor->InstanceTemplate()
+                ->NewInstance(ctx)
+                .ToLocalChecked())
+      .FromJust();
+  global
+      ->Set(ctx, v8_str("fast_api"),
+            fast_api_tpl->GetFunction(ctx).ToLocalChecked())
+      .FromJust();
+
+  CompileRun(
+      ctx,
+      "const vec = (...b) => [b.length, ...b];"
+      "const str = s => vec(...Array.from(s, c => c.charCodeAt(0)));"
+      "const bytes = new Uint8Array(["
+      "  0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,"
+      "  1, ...vec(5,"
+      "    0x60, 1, 0x6f, 0,"              // 0: (externref) -> ()
+      "    0x60, 2, 0x6f, 0x7f, 1, 0x7f,"  // 1: (externref, i32) -> i32
+      "    0x60, 1, 0x7f, 0,"              // 2: (i32) -> ()
+      "    0x60, 2, 0x6f, 0x6f, 1, 0x7f,"  // 3: (externref, externref) -> i32
+      "    0x60, 1, 0x7f, 1, 0x6f),"       // 4: (i32) -> externref
+      "  2, ...vec(3,"
+      "    ...str('m'), ...str('tag'), 4, 0, 0,"
+      "    ...str('wasm:js-string'), ...str('charCodeAt'), 0, 1,"
+      "    ...str('m'), ...str('fast_api'), 0, 2),"
+      "  3, ...vec(2, 3, 4),"
+      "  7, ...vec(2,"
+      "    ...str('probe'), 0, 2,"
+      "    ...str('call_fast'), 0, 3),"
+      "  10, ...vec(2,"
+      // probe(exn, s): charCodeAt(s, 0) + (try_table { throw exn },
+      // charCodeAt(s, 0))
+      "    ...vec(0,"
+      "      0x20, 1, 0x41, 0, 0x10, 0,"
+      "      0x02, 0x40, 0x1f, 0x40, 1, 0x02, 0,"
+      "        0x20, 0, 0x08, 0,"
+      "      0x0b, 0x0b,"
+      "      0x20, 1, 0x41, 0, 0x10, 0,"
+      "      0x6a, 0x0b),"
+      // call_fast(mode): try_table (catch tag 0) { fast_api(mode) }
+      "    ...vec(0,"
+      "      0x02, 0x6f, 0x1f, 0x40, 1, 0x00, 0, 0,"
+      "        0x20, 0, 0x10, 1,"
+      "      0x0b, 0xd0, 0x6f, 0x0b, 0x0b))"
+      "]);"
+      "const mod = new WebAssembly.Module(bytes, {builtins: ['js-string']});"
+      "const inst = new WebAssembly.Instance(mod, {"
+      "  m: {tag: WebAssembly.JSTag, fast_api: globalThis.fast_api}"
+      "});"
+      "globalThis.probe_raw = inst.exports.probe;"
+      "globalThis.promising_probe = WebAssembly.promising(inst.exports.probe);"
+      "globalThis.promising_call_fast ="
+      "    WebAssembly.promising(inst.exports.call_fast);")
+      .ToLocalChecked();
+
+  if (!i::v8_flags.liftoff_only && !i::v8_flags.disable_optimizing_compilers) {
+    CompileRun(ctx, "%WasmTierUpFunction(globalThis.probe_raw);")
+        .ToLocalChecked();
+  }
+
+  if (reserved_pages != nullptr) {
+    CHECK(
+        i::GetPlatformPageAllocator()->FreePages(reserved_pages, reserve_size));
+  }
+
+  // 1. Wasm `throw` caught locally on a JSPI secondary stack inside an API
+  // callback must NOT trigger ExceptionPropagationCallback (nor run JS getters
+  // that transition `s` into a ThinString mid-function).
+  CompileRun(ctx,
+             "globalThis.getter_ran = false;"
+             "const key = {['A'.repeat(32)]: 1};"
+             "const s = String.fromCharCode(...new Array(32).fill(65));"
+             "%SimulateNewspaceFull();"
+             "const exn = {"
+             "  get message() {"
+             "    ({})[s];"
+             "    globalThis.getter_ran = true;"
+             "    return 'wasm error';"
+             "  }"
+             "};"
+             "globalThis.probe_result = -1;"
+             "new MyClass(() => {"
+             "  promising_probe(exn, s).then(v => {"
+             "    globalThis.probe_result = v;"
+             "  });"
+             "}, false);")
+      .ToLocalChecked();
+  isolate->PerformMicrotaskCheckpoint();
+  CHECK(CompileRun(ctx, "!globalThis.getter_ran")
+            .ToLocalChecked()
+            ->BooleanValue(isolate));
+  CHECK_EQ(130, CompileRun(ctx, "globalThis.probe_result")
+                    .ToLocalChecked()
+                    ->Int32Value(ctx)
+                    .FromJust());
+
+  // 2. An exception thrown directly by the API callback on the central stack
+  // after the JSPI call returns must still be preprocessed.
+  {
+    v8::TryCatch try_catch(isolate);
+    std::ignore = CompileRun(
+        ctx,
+        "new MyClass(() => promising_probe({message: 'inner'}, 'B'.repeat(32)),"
+        "            true);");
+    CheckMessage(try_catch, ":MyClass:Constructor: Direct callback error.");
+  }
+
+  // 3. An API interceptor invoked from C++ while the topmost V8 frame is on a
+  // JSPI secondary stack must still have its direct exception preprocessed.
+  CompileRun(ctx,
+             "globalThis.caught_msg = '';"
+             "new MyClass(() => {"
+             "  promising_call_fast(1).then(e => {"
+             "    globalThis.caught_msg = e.message;"
+             "  });"
+             "}, false);")
+      .ToLocalChecked();
+  isolate->PerformMicrotaskCheckpoint();
+  {
+    v8::Local<v8::Value> msg =
+        CompileRun(ctx, "globalThis.caught_msg").ToLocalChecked();
+    v8::String::Utf8Value utf8(isolate, msg);
+    CHECK_EQ(std::string(*utf8),
+             std::string(
+                 "InterceptorHolder:prop:NamedGetter: Named getter failed."));
+  }
+
+#ifdef V8_ENABLE_TURBOFAN
+  // 4. A direct ThrowError inside a Wasm Fast API call (WASM_TO_JS frame on the
+  // JSPI secondary stack) must not crash or be misattributed to an outer API
+  // callback.
+  if (i::v8_flags.turbo_fast_api_calls) {
+    CompileRun(ctx,
+               "globalThis.caught_msg = '';"
+               "new MyClass(() => {"
+               "  promising_call_fast(2).then(e => {"
+               "    globalThis.caught_msg = e.message;"
+               "  });"
+               "}, false);")
+        .ToLocalChecked();
+    isolate->PerformMicrotaskCheckpoint();
+    v8::Local<v8::Value> msg =
+        CompileRun(ctx, "globalThis.caught_msg").ToLocalChecked();
+    v8::String::Utf8Value utf8(isolate, msg);
+    CHECK_EQ(std::string(*utf8), std::string("Fast API error."));
+  }
+#endif  // V8_ENABLE_TURBOFAN
+
+  // 5. Unwinding an inner secondary stack across a stack boundary via
+  // UnwindAndFindHandler() inside an API callback must restore
+  // thread_local_top()->central_stack_sp_ to the outer secondary stack's entry
+  // SP, so a subsequent direct throw from that API callback is still
+  // preprocessed.
+  {
+    i::FlagScope<bool> stress_switch(&i::v8_flags.stress_wasm_stack_switching,
+                                     true);
+    CompileRun(
+        ctx,
+        "const stress_bytes = new Uint8Array(["
+        "  0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,"
+        "  1, ...vec(1, 0x60, 0, 0),"
+        "  3, ...vec(1, 0),"
+        "  7, ...vec(1, ...str('stress_throw'), 0, 0),"
+        "  10, ...vec(1, ...vec(0, 0x00, 0x0b))"
+        "]);"
+        "globalThis.stress_throw ="
+        "    new WebAssembly.Instance(new WebAssembly.Module(stress_bytes))"
+        "        .exports.stress_throw;"
+        "globalThis.caught_msg = '';"
+        "new MyClass(() => {"
+        "  promising_call_fast(3).then(e => {"
+        "    globalThis.caught_msg = e.message;"
+        "  });"
+        "}, false);")
+        .ToLocalChecked();
+    isolate->PerformMicrotaskCheckpoint();
+    v8::Local<v8::Value> msg =
+        CompileRun(ctx, "globalThis.caught_msg").ToLocalChecked();
+    v8::String::Utf8Value utf8(isolate, msg);
+    CHECK_EQ(
+        std::string(*utf8),
+        std::string("UnwindHolder:prop:NamedGetter: After nested unwind."));
+  }
+
+  isolate->SetExceptionPropagationCallback(nullptr);
+}
+
+class WasmSecondaryStackExceptionThread
+    : public v8::internal::SandboxableThread {
+ public:
+  WasmSecondaryStackExceptionThread(void* reserved_pages, size_t reserve_size)
+      : SandboxableThread(
+            Options("WasmSecondaryStackExceptionThread", 16 * 1024 * 1024)),
+        reserved_pages_(reserved_pages),
+        reserve_size_(reserve_size) {}
+
+  void Run() override {
+    v8::Isolate::CreateParams create_params;
+    create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+    v8::Isolate* isolate = v8::Isolate::New(create_params);
+    {
+      v8::Isolate::Scope isolate_scope(isolate);
+      RunPreprocessExceptionOnWasmSecondaryStackTest(isolate, reserved_pages_,
+                                                     reserve_size_);
+    }
+    isolate->Dispose();
+  }
+
+ private:
+  void* reserved_pages_;
+  size_t reserve_size_;
+};
+
+}  // namespace
+
+TEST(PreprocessExceptionOnWasmSecondaryStack) {
+  if (i::v8_flags.jitless || i::v8_flags.wasm_jitless) return;
+
+  FLAG_SCOPE(experimental_report_exceptions_from_callbacks);
+  FLAG_SCOPE(allow_natives_syntax);
+  FLAG_SCOPE(wasm_unsafe_fast_api_wrapper);
+#ifdef DEBUG
+  FLAG_SCOPE(turboshaft_verify_load_elimination);
+#endif
+
+  // Test on a worker thread after freeing reserved pages above its stack,
+  // placing the JSPI secondary stack at a higher address than the central stack
+  // (reproducing crbug.com/575939904).
+  v8::PageAllocator* allocator = i::GetPlatformPageAllocator();
+  size_t page_size = allocator->AllocatePageSize();
+  size_t reserve_size = 16 * 1024 * 1024;
+  void* reserved_pages = allocator->AllocatePages(
+      nullptr, reserve_size, page_size, v8::PageAllocator::kNoAccess);
+  WasmSecondaryStackExceptionThread thread(reserved_pages, reserve_size);
+  CHECK(thread.Start());
+  thread.Join();
+
+  // Also test with the JSPI secondary stack mapped below the main thread's
+  // central stack.
+  RunPreprocessExceptionOnWasmSecondaryStackTest(CcTest::isolate(), nullptr, 0);
+}
+#endif  // V8_ENABLE_WEBASSEMBLY && !defined(V8_ENABLE_CET_SHADOW_STACK)
+
 namespace {

 template <typename T>
diff --git a/deps/v8/test/inspector/inspector.status b/deps/v8/test/inspector/inspector.status
index 4041d4a5052..a72ba8c9f1d 100644
--- a/deps/v8/test/inspector/inspector.status
+++ b/deps/v8/test/inspector/inspector.status
@@ -74,6 +74,7 @@
   'debugger/wasm-*': [SKIP],
   'cpu-profiler/console-profile-wasm': [SKIP],
   'runtime/get-properties': [SKIP],
+  'regress/regress-577352626': [SKIP],
   'regress/regress-crbug-349248170': [SKIP],
 }],  # not has_webassembly or variant == jitless

diff --git a/deps/v8/test/inspector/regress/regress-577352626-expected.txt b/deps/v8/test/inspector/regress/regress-577352626-expected.txt
new file mode 100644
index 00000000000..67f324a184b
--- /dev/null
+++ b/deps/v8/test/inspector/regress/regress-577352626-expected.txt
@@ -0,0 +1,7 @@
+Regression test for crbug.com/577352626.
+paused in: $f
+go(1) returned: 11
+paused in: jsCaller
+jsCaller() returned: 11
+paused in: jsCallerViaWasm
+jsCallerViaWasm() returned: 11
diff --git a/deps/v8/test/inspector/regress/regress-577352626.js b/deps/v8/test/inspector/regress/regress-577352626.js
new file mode 100644
index 00000000000..9d48b2a35cc
--- /dev/null
+++ b/deps/v8/test/inspector/regress/regress-577352626.js
@@ -0,0 +1,211 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --liftoff
+
+const {session, contextGroup, Protocol} =
+    InspectorTest.start('Regression test for crbug.com/577352626.');
+
+contextGroup.addScript(utils.read('test/mjsunit/wasm/wasm-module-builder.js'));
+
+contextGroup.addScript(`
+function setup() {
+  console.log('setup');
+  inspector.runNestedMessageLoop();
+}
+
+function jsCaller() {
+  return instanceA.exports.goAllInlined(1);
+}
+
+function jsCallerViaWasm() {
+  return instanceA.exports.wasmCaller(1);
+}
+
+const builderA = new WasmModuleBuilder();
+const sig = builderA.addType(kSig_i_v);
+const $setup = builderA.addImport('env', 'setup', kSig_v_v);
+const table = builderA.addTable(kWasmAnyFunc, 1, 1).exportAs('T');
+
+// Place 'collide' at untagged globals offset 20 (ByteArray offset 28), which
+// matches WasmDispatchTable::kEntriesOffset + WasmDispatchTable::kTargetBias.
+builderA.addGlobal(kWasmI64, true, false, wasmI64Const(0x41414141n));
+builderA.addGlobal(kWasmI64, true, false, wasmI64Const(0x42424242n));
+builderA.addGlobal(kWasmI32, true, false, wasmI32Const(0x43434343));
+const collide = builderA.addGlobal(kWasmI32, true, false, wasmI32Const(0));
+
+const f = builderA.addFunction('f', sig)
+  .addBody([kExprI32Const, 11])
+  .exportFunc();
+
+builderA.addActiveElementSegment(table.index, wasmI32Const(0), [f.index]);
+
+// Case 1: 'go' has a speculatively-inlined call_indirect before the loop and a
+// non-inlined call_indirect after the loop. The pause at the loop stack check
+// must be deferred to the non-inlined Liftoff callee '$f'.
+builderA.addFunction('go', kSig_i_i)
+  .addLocals(kWasmI32, 1)
+  .addBody([
+    kExprLocalGet, 0,
+    kExprIf, kWasmVoid,
+      kExprCallFunction, $setup,
+    kExprEnd,
+    // Call #1: monomorphic (A.f), speculatively inlined by Turboshaft.
+    kExprI32Const, 0,
+    kExprCallIndirect, sig, table.index,
+    kExprDrop,
+    // Loop with stack check where the pending Debugger.pause interrupt fires.
+    kExprI32Const, 5,
+    kExprLocalSet, 1,
+    kExprLoop, kWasmVoid,
+      kExprLocalGet, 1,
+      kExprI32Const, 1,
+      kExprI32Sub,
+      kExprLocalTee, 1,
+      kExprBrIf, 0,
+    kExprEnd,
+    // Store at ByteArray offset 28, invalidating only the cached target.
+    kExprI32Const, 1,
+    kExprGlobalSet, collide.index,
+    // Call #2: must not use a stale cached implicit_arg with a mutated target.
+    kExprLocalGet, 0,
+    kExprIf, kWasmI32,
+      kExprI32Const, 0,
+      kExprCallIndirect, sig, table.index,
+    kExprElse,
+      kExprI32Const, 0,
+    kExprEnd,
+  ]).exportFunc();
+
+// Case 2: 'goAllInlined' warms up both call_indirect sites so both are
+// speculatively inlined. When it makes no further calls, the pause at the loop
+// stack check must be deferred until it returns to its caller frame.
+const goAllInlined = builderA.addFunction('goAllInlined', kSig_i_i)
+  .addLocals(kWasmI32, 1)
+  .addBody([
+    kExprLocalGet, 0,
+    kExprIf, kWasmVoid,
+      kExprCallFunction, $setup,
+    kExprEnd,
+    kExprI32Const, 0,
+    kExprCallIndirect, sig, table.index,
+    kExprDrop,
+    kExprI32Const, 5,
+    kExprLocalSet, 1,
+    kExprLoop, kWasmVoid,
+      kExprLocalGet, 1,
+      kExprI32Const, 1,
+      kExprI32Sub,
+      kExprLocalTee, 1,
+      kExprBrIf, 0,
+    kExprEnd,
+    kExprI32Const, 1,
+    kExprGlobalSet, collide.index,
+    kExprI32Const, 0,
+    kExprCallIndirect, sig, table.index,
+  ]).exportFunc();
+
+builderA.addFunction('wasmCaller', kSig_i_i)
+  .addBody([
+    kExprLocalGet, 0,
+    kExprCallFunction, goAllInlined.index,
+  ]).exportFunc();
+
+const instanceA = builderA.instantiate({env: {setup}});
+
+const builderC = new WasmModuleBuilder();
+const sigC = builderC.addType(kSig_i_v);
+const g0C = builderC.addGlobal(kWasmI32, true, false, wasmI32Const(0x1337));
+builderC.addFunction('g', sigC)
+  .addBody([kExprGlobalGet, g0C.index])
+  .exportFunc();
+const instanceC = builderC.instantiate();
+
+// Collect call_indirect feedback in Liftoff and tier up 'go' synchronously.
+instanceA.exports.go(0);
+%WasmTierUpFunction(instanceA.exports.go);
+`);
+
+Protocol.Debugger.onPaused(async message => {
+  const topFrame = message.params.callFrames[0];
+  InspectorTest.log('paused in: ' + topFrame.functionName);
+  await Protocol.Runtime.evaluate({
+    expression: 'instanceA.exports.T.set(0, instanceC.exports.g)',
+  });
+  await Protocol.Debugger.resume();
+});
+
+(async () => {
+  await Protocol.Runtime.enable();
+
+  // Test 1: Pause is deferred from optimized '$go' to Liftoff callee '$f'.
+  let consolePromise = Protocol.Runtime.onceConsoleAPICalled();
+  let evalPromise = Protocol.Runtime.evaluate({
+    expression: 'instanceA.exports.go(1)',
+    returnByValue: true,
+  });
+
+  await consolePromise;
+  await Protocol.Debugger.enable();
+  Protocol.Debugger.pause();
+  await Protocol.Runtime.runIfWaitingForDebugger();
+
+  let {result: {result}} = await evalPromise;
+  InspectorTest.log('go(1) returned: ' + result.value);
+  await Protocol.Debugger.disable();
+
+  // Reset T[0] back to A.f, collect call_indirect feedback for both sites, and
+  // tier up 'goAllInlined' synchronously.
+  await Protocol.Runtime.evaluate({
+    expression: `
+      instanceA.exports.T.set(0, instanceA.exports.f);
+      instanceA.exports.goAllInlined(0);
+      %WasmTierUpFunction(instanceA.exports.goAllInlined);
+    `,
+  });
+
+  // Test 2: When both calls in '$goAllInlined' are inlined and it makes no
+  // further calls, pause is deferred until return to its JS caller ('jsCaller').
+  consolePromise = Protocol.Runtime.onceConsoleAPICalled();
+  evalPromise = Protocol.Runtime.evaluate({
+    expression: 'jsCaller()',
+    returnByValue: true,
+  });
+
+  await consolePromise;
+  await Protocol.Debugger.enable();
+  Protocol.Debugger.pause();
+  await Protocol.Runtime.runIfWaitingForDebugger();
+
+  ({result: {result}} = await evalPromise);
+  InspectorTest.log('jsCaller() returned: ' + result.value);
+  await Protocol.Debugger.disable();
+
+  // Reset T[0] back to A.f and ensure 'goAllInlined' is tiered up, leaving
+  // 'wasmCaller' in non-debugging Liftoff so flooding skips '$wasmCaller' and
+  // floods 'jsCallerViaWasm'.
+  await Protocol.Runtime.evaluate({
+    expression: `
+      instanceA.exports.T.set(0, instanceA.exports.f);
+      instanceA.exports.goAllInlined(0);
+      %WasmTierUpFunction(instanceA.exports.goAllInlined);
+    `,
+  });
+
+  // Test 3: Same as Test 2, with a non-inspectable Wasm caller in between.
+  consolePromise = Protocol.Runtime.onceConsoleAPICalled();
+  evalPromise = Protocol.Runtime.evaluate({
+    expression: 'jsCallerViaWasm()',
+    returnByValue: true,
+  });
+
+  await consolePromise;
+  await Protocol.Debugger.enable();
+  Protocol.Debugger.pause();
+  await Protocol.Runtime.runIfWaitingForDebugger();
+
+  ({result: {result}} = await evalPromise);
+  InspectorTest.log('jsCallerViaWasm() returned: ' + result.value);
+  InspectorTest.completeTest();
+})();
diff --git a/deps/v8/test/mjsunit/es6/regress-private-name-heritage-recalc.js b/deps/v8/test/mjsunit/es6/regress-private-name-heritage-recalc.js
new file mode 100644
index 00000000000..682b3aae66f
--- /dev/null
+++ b/deps/v8/test/mjsunit/es6/regress-private-name-heritage-recalc.js
@@ -0,0 +1,90 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Test 1: Nested class in heritage expression with lazy method compilation
+// and PreparseData.
+{
+  class B {
+    #x = "from B";
+    static {
+      class C extends (class D {
+        static m() {
+          return (() => function(o) { return o.#x; })();
+        }
+      }) {
+        #x = "from C";
+      }
+      assertEquals("from B", C.m()(new B()));
+      assertThrows(() => C.m()(new C()), TypeError);
+    }
+  }
+}
+
+// Test 2: Direct eval in heritage expression of a class that does not allocate
+// a context.
+{
+  let f;
+  class B {
+    #x = "from B";
+    [(class extends (f = (o) => eval("o.#x"), Object) {})];
+  }
+  assertEquals("from B", f(new B()));
+}
+
+// Test 3: Direct eval in nested function inside heritage expression where
+// the outer heritage function does not allocate a context.
+{
+  class B {
+    #x = "from B";
+    static test(b) {
+      let f;
+      class C extends (() => {
+        f = (o) => eval("o.#x");
+        return Object;
+      })() {
+        #x = "from C";
+      }
+      assertThrows(() => f(new C()), TypeError);
+      return f(b);
+    }
+  }
+  assertEquals("from B", B.test(new B()));
+}
+
+// Test 4: Nested class with its own private field inside a lazy heritage
+// function that does not allocate a context, using direct eval.
+{
+  class B {
+    #x = "from B";
+    static {
+      let f;
+      class C extends (f = () => class D {
+        #y = "from D";
+        static m(o) {
+          return eval("o.#x");
+        }
+      }, Object) {
+        #x = "from C";
+      }
+      assertEquals("from B", f().m(new B()));
+      assertThrows(() => f().m(new C()), TypeError);
+    }
+  }
+}
+
+// Test 5: Nested class with its own private field inside heritage expression
+// of an anonymous class that does not allocate a context, using direct eval.
+{
+  let D_cls;
+  class B {
+    #x = "from B";
+    [(class extends (D_cls = class D {
+      #y = "from D";
+      static m(o) {
+        return eval("o.#x");
+      }
+    }) {})];
+  }
+  assertEquals("from B", D_cls.m(new B()));
+}
diff --git a/deps/v8/test/mjsunit/harmony/regress-private-name-heritage-catch-eval.js b/deps/v8/test/mjsunit/harmony/regress-private-name-heritage-catch-eval.js
new file mode 100644
index 00000000000..5d27d38bb37
--- /dev/null
+++ b/deps/v8/test/mjsunit/harmony/regress-private-name-heritage-catch-eval.js
@@ -0,0 +1,131 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Test private name resolution in class heritage clauses across catch scopes
+// and direct eval calls.
+
+class Outer {
+  #x = 'outer';
+
+  testCatchInHeritage() {
+    let f1, f2, evalRes;
+    class Inner extends (() => {
+      try {
+        throw null;
+      } catch (e) {
+        f1 = () => this.#x;
+        f2 = () => () => this.#x;
+        evalRes = eval('this.#x');
+      }
+      return Object;
+    })() {
+      #x = 'inner';
+    }
+    assertEquals('outer', f1());
+    assertEquals('outer', f2()());
+    assertEquals('outer', evalRes);
+  }
+
+  testDirectEvalInHeritage() {
+    let res1, res2, bodyFn;
+    class D1 extends (res1 = eval('this.#x'), Object) {
+      [(
+        assertThrows(() => eval('this.#x'), TypeError),
+        bodyFn = (o) => eval('o.#x'),
+        'prop'
+      )] = 1;
+      #x = 'D1';
+    }
+    assertEquals('outer', res1);
+    assertEquals('D1', bodyFn(new D1()));
+    assertThrows(() => bodyFn(this), TypeError);
+
+    class D2 extends (() => {
+      res2 = eval('this.#x');
+      return Object;
+    })() {
+      #x = 'D2';
+    }
+    assertEquals('outer', res2);
+  }
+
+  testNestedEvalAndLazyFunctionsInHeritage() {
+    let nested1, nested2, lazyFn1, lazyFn2, lazyArrow1, lazyArrow2;
+    class D1 extends (
+      nested1 = eval("eval('this.#x')"),
+      lazyFn1 = eval('(function() { return this.#x; })'),
+      lazyArrow1 = eval('(() => () => this.#x)()'),
+      Object
+    ) {
+      #x = 'D1';
+    }
+    assertEquals('outer', nested1);
+    assertEquals('outer', lazyFn1.call(this));
+    assertEquals('outer', lazyArrow1());
+
+    class D2 extends (() => {
+      nested2 = eval("eval('this.#x')");
+      lazyFn2 = eval('(function() { return this.#x; })');
+      lazyArrow2 = eval('(() => () => this.#x)()');
+      return Object;
+    })() {
+      #x = 'D2';
+    }
+    assertEquals('outer', nested2);
+    assertEquals('outer', lazyFn2.call(this));
+    assertEquals('outer', lazyArrow2());
+  }
+
+  testContextlessClassInHeritage() {
+    let res1, res2;
+    class D extends (
+      class {
+        static [res1 = eval('this.#x')] = 1;
+      },
+      class extends (res2 = eval('this.#x'), Object) {},
+      Object
+    ) {
+      #x = 'D';
+    }
+    assertEquals('outer', res1);
+    assertEquals('outer', res2);
+
+    let bodyFn;
+    class E {
+      #x = 'E';
+      static [class extends (bodyFn = (o) => eval('o.#x'), Object) {}] = 1;
+    }
+    assertEquals('E', bodyFn(new E()));
+    assertThrows(() => bodyFn(this), TypeError);
+  }
+
+  testArrowParamReparentInHeritage() {
+    class Middle {
+      #x = 'middle';
+      run() {
+        let res;
+        class Inner extends ((
+          a = class {
+            #y = 1;
+            static [res = this.#x] = 2;
+          }
+        ) => {
+          () => a;
+          return Object;
+        })() {
+          #x = 'inner';
+        }
+        return res;
+      }
+    }
+    assertEquals('middle', new Middle().run());
+  }
+}
+
+const outer = new Outer();
+outer.testCatchInHeritage();
+outer.testDirectEvalInHeritage();
+outer.testNestedEvalAndLazyFunctionsInHeritage();
+outer.testContextlessClassInHeritage();
+outer.testArrowParamReparentInHeritage();
diff --git a/deps/v8/test/mjsunit/maglev/regress-577305517.js b/deps/v8/test/mjsunit/maglev/regress-577305517.js
new file mode 100644
index 00000000000..3795d5ca3e1
--- /dev/null
+++ b/deps/v8/test/mjsunit/maglev/regress-577305517.js
@@ -0,0 +1,76 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+([].values()).foo = 1;
+const smi_obj = {p: 42};
+
+function nop() {}
+%NeverOptimizeFunction(nop);
+
+// Test early abort right after MaglevSubGraphBuilder::BeginLoop in
+// Array.prototype.sort.
+(function testSort() {
+  const sort = Array.prototype.sort;
+  function cmp(a, b) {
+    return a - b;
+  }
+  function inner(iter, arr, skip) {
+    if (skip) return 0;
+    let v = iter.p;
+    return sort.call(arr, cmp);
+  }
+  function test(arr, skip) {
+    let iter = arr.values();
+    nop();
+    let elem = arr[0];
+    return inner(iter, arr, skip);
+  }
+
+  %PrepareFunctionForOptimization(cmp);
+  %PrepareFunctionForOptimization(inner);
+  %PrepareFunctionForOptimization(test);
+  for (let i = 0; i < 10; ++i) {
+    inner(smi_obj, [2, 1], false);
+    test([2, 1], true);
+  }
+  %OptimizeMaglevOnNextCall(test);
+  assertEquals(0, test([2, 1], true));
+  assertEquals([1, 2], test([2, 1], false));
+})();
+
+// Test the same early abort in Array.prototype.forEach
+// (TryReduceArrayIteratingBuiltin).
+(function testForEach() {
+  const forEach = Array.prototype.forEach;
+  let sum = 0;
+  function cb(x) {
+    sum += x;
+  }
+  function inner(iter, arr, skip) {
+    if (skip) return 0;
+    let v = iter.p;
+    return forEach.call(arr, cb);
+  }
+  function test(arr, skip) {
+    let iter = arr.values();
+    nop();
+    let elem = arr[0];
+    return inner(iter, arr, skip);
+  }
+
+  %PrepareFunctionForOptimization(cb);
+  %PrepareFunctionForOptimization(inner);
+  %PrepareFunctionForOptimization(test);
+  for (let i = 0; i < 10; ++i) {
+    inner(smi_obj, [2, 1], false);
+    test([2, 1], true);
+  }
+  sum = 0;
+  %OptimizeMaglevOnNextCall(test);
+  assertEquals(0, test([2, 1], true));
+  assertEquals(undefined, test([2, 1], false));
+  assertEquals(3, sum);
+})();
diff --git a/deps/v8/test/mjsunit/maglev/regress-578322433.js b/deps/v8/test/mjsunit/maglev/regress-578322433.js
new file mode 100644
index 00000000000..513a436420e
--- /dev/null
+++ b/deps/v8/test/mjsunit/maglev/regress-578322433.js
@@ -0,0 +1,81 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --expose-gc --maglev-non-eager-inlining
+// Flags: --max-maglev-eager-inlined-bytecode-size=0
+
+function zero() {
+  return 0;
+}
+%PrepareFunctionForOptimization(zero);
+
+// CheckedNumberToInt32 must not propagate Smi range back to its tagged input.
+let v_int32 = 0;
+v_int32 = %AllocateHeapNumberWithValue(0);
+let v_smi1 = 1;
+let v_smi2 = 1;
+
+function foo_int32(x) {
+  v_int32 = x;
+  let y = x + zero();
+  v_smi1 = y;
+  v_smi2 = x;
+}
+
+function read_smi2() {
+  return v_smi2 + 1;
+}
+
+%PrepareFunctionForOptimization(foo_int32);
+%PrepareFunctionForOptimization(read_smi2);
+foo_int32(0);
+assertEquals(1, read_smi2());
+%OptimizeMaglevOnNextCall(read_smi2);
+assertEquals(1, read_smi2());
+
+// Tenure v_smi2's ContextCell before allocating a young HeapNumber(0.0) so an
+// elided write barrier also leaves an unrecorded old-to-new pointer.
+gc();
+let hn0_int32 = %AllocateHeapNumberWithValue(0);
+
+%OptimizeMaglevOnNextCall(foo_int32);
+foo_int32(hn0_int32);
+gc({type: 'minor'});
+assertEquals(1, read_smi2());
+assertEquals(0, v_smi1);
+assertEquals(0, v_smi2);
+
+// CheckedNumberToFloat64 must not propagate Smi range back to its tagged input.
+let v_f64 = 0;
+v_f64 = 1.5;
+let v_f64_smi1 = 1;
+let v_f64_smi2 = 1;
+
+function foo_f64(x) {
+  v_f64 = x;
+  let y = x + zero();
+  v_f64_smi1 = y;
+  v_f64_smi2 = x;
+}
+
+function read_f64_smi2() {
+  return v_f64_smi2 + 1;
+}
+
+%PrepareFunctionForOptimization(foo_f64);
+%PrepareFunctionForOptimization(read_f64_smi2);
+foo_f64(0);
+assertEquals(1, read_f64_smi2());
+%OptimizeMaglevOnNextCall(read_f64_smi2);
+assertEquals(1, read_f64_smi2());
+
+gc();
+let hn0_f64 = %AllocateHeapNumberWithValue(0);
+
+%OptimizeMaglevOnNextCall(foo_f64);
+foo_f64(hn0_f64);
+gc({type: 'minor'});
+assertEquals(1, read_f64_smi2());
+assertEquals(0, v_f64_smi1);
+assertEquals(0, v_f64_smi2);
diff --git a/deps/v8/test/mjsunit/maglev/regress-579313083.js b/deps/v8/test/mjsunit/maglev/regress-579313083.js
new file mode 100644
index 00000000000..b70e9e59773
--- /dev/null
+++ b/deps/v8/test/mjsunit/maglev/regress-579313083.js
@@ -0,0 +1,56 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --maglev
+
+const sinWithApply = Math.sin;
+sinWithApply.call = Function.prototype.apply;
+
+function inner(fn, cond, breakCond) {
+  let x = true;
+  while (cond) {
+    // Inner loop resets `x`'s known type in KNA to the unfinalized outer loop
+    // Phi type (`kUnknown`) before `fn.call(x)`, while `FinishLoop` later types
+    // the outer Phi as `kBoolean` before `!x`.
+    for (let k = 0; k < 0; k++) {}
+    fn.call(x);
+    if (breakCond) break;
+    x = false;
+  }
+  return !x;
+}
+
+function outer(breakCond) {
+  return inner(Function.prototype.apply, true, breakCond);
+}
+
+%PrepareFunctionForOptimization(inner);
+%PrepareFunctionForOptimization(outer);
+
+// 1. Calling `fn.call` when it is `Function.prototype.apply` on `Math.sin`
+// records `Weak(Math.sin)` with `CallFeedbackContent::kReceiver`.
+inner(sinWithApply, true, true);
+
+// 2. Calling `fn.call` when `fn` is `Function.prototype.apply` transitions the
+// slot to `many_closures_cell` while `CallFeedbackContent::kReceiver` remains
+// set. When `outer` inlines `inner` with constant `Function.prototype.apply`,
+// reducing `fn.call(x)` reduces `Function.prototype.apply` and must not
+// speculate that `x` equals `many_closures_cell`.
+assertThrows(() => outer(false), TypeError);
+
+%OptimizeFunctionOnNextCall(outer);
+assertThrows(() => outer(false), TypeError);
+
+// Nested `Function.prototype.apply.apply(target)` records `kReceiver` with
+// `Function.prototype.apply` for the outer `apply` call; the inner `apply`
+// reduction must not reuse that feedback for `target` and deopt.
+function nestedApply(target) {
+  return Function.prototype.apply.apply(target);
+}
+
+%PrepareFunctionForOptimization(nestedApply);
+assertEquals(42, nestedApply(() => 42));
+%OptimizeFunctionOnNextCall(nestedApply);
+assertEquals(42, nestedApply(() => 42));
+assertOptimized(nestedApply);
diff --git a/deps/v8/test/mjsunit/regress/regress-568633429.js b/deps/v8/test/mjsunit/regress/regress-568633429.js
new file mode 100644
index 00000000000..b36f5753245
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-568633429.js
@@ -0,0 +1,25 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --turbolev --allow-natives-syntax
+
+function outer() {
+  try {
+    throw 1;
+  } catch (e) {}
+
+  function inner(arg1, arg2) {
+    for (let i = 0; i < 5; i++) {
+      Number.isNaN(Math.log10(arg2), inner);
+      arg2 = arg1;
+    }
+  }
+  inner(inner, inner);
+}
+
+%PrepareFunctionForOptimization(outer);
+outer();
+outer();
+%OptimizeFunctionOnNextCall(outer);
+outer();
diff --git a/deps/v8/test/mjsunit/regress/regress-572988453.js b/deps/v8/test/mjsunit/regress/regress-572988453.js
new file mode 100644
index 00000000000..f0dd7bcd2a4
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-572988453.js
@@ -0,0 +1,34 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-gc --stress-flush-code
+
+class Outer {
+  #a = 'outer_a';
+  #b = 'outer_b';
+
+  static make() {
+    let fn;
+    class Inner extends (() => {
+      try {
+        throw null;
+      } catch (e) {
+        fn = (function(o) {
+          return o.#a + ':' + o.#b;
+        });
+      }
+      return Object;
+    })() {
+      #a() {}
+      #b() {}
+    }
+    return {fn, Inner};
+  }
+}
+
+const {fn, Inner} = Outer.make();
+assertEquals('outer_a:outer_b', fn(new Outer()));
+for (let i = 0; i < 4; i++) gc();
+assertEquals('outer_a:outer_b', fn(new Outer()));
+assertThrows(() => fn(new Inner()), TypeError);
diff --git a/deps/v8/test/mjsunit/regress/regress-573962535.js b/deps/v8/test/mjsunit/regress/regress-573962535.js
new file mode 100644
index 00000000000..29db88a4be5
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-573962535.js
@@ -0,0 +1,44 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-gc --no-compilation-cache --stress-flush-code
+// Flags: --stress-lazy-source-positions
+
+class B {
+  #x = 'B';
+  static makeHeritageEvalFunction() {
+    let g;
+    let h;
+    let nested;
+    let nestedEval;
+    class C extends (
+      g = eval('0, function(o) { return o.#x; }'),
+      h = eval('(() => (o) => o.#x)()'),
+      nested = eval('(() => { let ctx = 1; return (o) => { () => ctx; return o.#x; }; })()'),
+      nestedEval = eval("eval('0, function(o) { return o.#x; }')"),
+      Object
+    ) {
+      #x = 'C';
+    }
+    return {g, h, nested, nestedEval, C};
+  }
+}
+
+const {g, h, nested, nestedEval, C} = B.makeHeritageEvalFunction();
+
+// Drop the eval's top-level SharedFunctionInfo and flush bytecode before
+// lazy compilation.
+for (let i = 0; i < 4; i++) gc();
+
+assertEquals('B', g(new B()));
+assertThrows(() => g(new C()), TypeError);
+
+assertEquals('B', h(new B()));
+assertThrows(() => h(new C()), TypeError);
+
+assertEquals('B', nested(new B()));
+assertThrows(() => nested(new C()), TypeError);
+
+assertEquals('B', nestedEval(new B()));
+assertThrows(() => nestedEval(new C()), TypeError);
diff --git a/deps/v8/test/mjsunit/regress/regress-574038247.js b/deps/v8/test/mjsunit/regress/regress-574038247.js
new file mode 100644
index 00000000000..d35372f23ef
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-574038247.js
@@ -0,0 +1,68 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --bundle
+
+// JS_BUNDLE_MODULE:c1.mjs
+export const x = 1;
+
+// JS_BUNDLE_MODULE:c2.mjs
+export const x = 2;
+
+// JS_BUNDLE_MODULE:p.mjs
+export * from "n.mjs";
+export * from "c1.mjs";
+
+// JS_BUNDLE_MODULE:n.mjs
+export * from "p.mjs";
+
+// JS_BUNDLE_MODULE:outer.mjs
+export * from "m.mjs";
+export * from "p.mjs";
+export * from "c2.mjs";
+
+// JS_BUNDLE_MODULE:m.mjs
+const a = 1;
+export { a, a as b, a as c, a as d, a as e };
+export * from "outer.mjs";
+export * from "n.mjs";
+
+// JS_BUNDLE_MODULE:trigger.mjs
+import { x } from "outer.mjs";
+
+// JS_BUNDLE_MODULE:outer_no_ns.mjs
+export * from "m_no_ns.mjs";
+export * from "p.mjs";
+export * from "c2.mjs";
+
+// JS_BUNDLE_MODULE:m_no_ns.mjs
+export const a = 1;
+export * from "outer_no_ns.mjs";
+export * from "n.mjs";
+
+// JS_BUNDLE_MODULE:trigger_no_ns.mjs
+import { x } from "outer_no_ns.mjs";
+
+// JS_BUNDLE_MODULE:import_x_from_m_no_ns.mjs
+import { x } from "m_no_ns.mjs";
+
+// JS_BUNDLE_MODULE_ENTRYPOINT
+import * as ns from "m.mjs";
+import { a } from "m_no_ns.mjs";
+
+assertEquals(1, a);
+
+function read(o) {
+  return o.a + o.b + o.c + o.d + o.e;
+}
+
+for (let i = 0; i < 12; i++) {
+  assertEquals(5, read(ns));
+}
+
+await assertThrowsAsync(import("trigger.mjs"), SyntaxError);
+assertEquals(5, read(ns));
+
+await assertThrowsAsync(import("trigger_no_ns.mjs"), SyntaxError);
+await assertThrowsAsync(import("import_x_from_m_no_ns.mjs"), SyntaxError);
diff --git a/deps/v8/test/mjsunit/regress/regress-574222006.js b/deps/v8/test/mjsunit/regress/regress-574222006.js
new file mode 100644
index 00000000000..6a012345028
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-574222006.js
@@ -0,0 +1,28 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+const realm = Realm.create();
+Realm.eval(realm, `
+  var x = 1;
+  function store(o) { o.x = 2; }
+  const objs = [{a: 1}, {b: 1}, {c: 1}, {d: 1}, {e: 1}];
+  for (let i = 0; i < 10; i++) {
+    for (const o of objs) store(o);
+  }
+  store(globalThis);
+`);
+
+const target = Realm.global(realm);
+
+function write(o) {
+  o.x = 42;
+}
+const objs = [{a: 1}, {b: 1}, {c: 1}, {d: 1}, {e: 1}];
+for (let i = 0; i < 10; i++) {
+  for (const o of objs) write(o);
+}
+
+Realm.eval(realm, 'store(globalThis);');
+assertThrows(() => write(target), TypeError);
+assertEquals(2, Realm.eval(realm, 'x'));
diff --git a/deps/v8/test/mjsunit/regress/regress-575524702.js b/deps/v8/test/mjsunit/regress/regress-575524702.js
new file mode 100644
index 00000000000..a2b5244c579
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-575524702.js
@@ -0,0 +1,61 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Case 1: StoreGlobalIC / LoadGlobalIC warmed up BEFORE cross-origin
+// Realm.navigate().
+(function TestPreNavigationWarmup() {
+  const r1 = Realm.createAllowCrossRealmAccess();
+
+  const [setLeak, getLeak, RealmTypeError] = Realm.eval(r1, `
+    Object.defineProperty(Object.prototype, "leak", {
+      get: version,
+      set: version,
+      configurable: true
+    });
+    function setLeak(v) {
+      leak = v;
+    }
+    function getLeak() {
+      return leak;
+    }
+    for (let i = 0; i < 10; i++) {
+      setLeak(i);
+      getLeak();
+    }
+    [setLeak, getLeak, TypeError];
+  `);
+
+  Realm.navigate(r1);
+
+  assertThrows(() => setLeak(1), RealmTypeError, "no access");
+  assertThrows(() => getLeak(), RealmTypeError, "no access");
+})();
+
+// Case 2: StoreGlobalIC / LoadGlobalIC warmed up AFTER cross-origin
+// Realm.navigate().
+(function TestPostNavigationWarmup() {
+  const r2 = Realm.createAllowCrossRealmAccess();
+
+  const [setLeak, getLeak, RealmTypeError] = Realm.eval(r2, `
+    Object.defineProperty(Object.prototype, "leak2", {
+      get: version,
+      set: version,
+      configurable: true
+    });
+    function setLeak(v) {
+      leak2 = v;
+    }
+    function getLeak() {
+      return leak2;
+    }
+    [setLeak, getLeak, TypeError];
+  `);
+
+  Realm.navigate(r2);
+
+  for (let i = 0; i < 10; i++) {
+    assertThrows(() => setLeak(i), RealmTypeError, "no access");
+    assertThrows(() => getLeak(), RealmTypeError, "no access");
+  }
+})();
diff --git a/deps/v8/test/mjsunit/regress/regress-575525282-1.js b/deps/v8/test/mjsunit/regress/regress-575525282-1.js
new file mode 100644
index 00000000000..4a1f789c7e0
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-575525282-1.js
@@ -0,0 +1,70 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+// The 32-bit word that optimized code hands to script as a tagged pointer (low bit set).
+// Cage base + 0xdead0000 lies 3.48 GiB into V8's 4-GiB pointer-compression
+// cage, far above everything this page allocates there.
+const WORD = 0xdead0001;
+// Compressed address of the read-only string "name".
+const NAME = 0xe29;
+
+// 1. Map setup
+function f(flag) { if (flag) return { a: 1, b: { c: 2 } }; return 0; }
+%PrepareFunctionForOptimization(f);
+f(true);
+f(true);
+const sib = { a: 1, z: 0 };
+
+// Resulting maps:
+//-> M1 (a: smi) -> M2 (a: smi, b: HeapObject)
+//            \
+//             ---> M3 (a: smi, z: smi)
+
+// This deprecates all above maps.
+sib.a = 1.5;
+
+// 2. Object.prototype with more properties, one of them "name" and one element.
+const A = Object.prototype;
+A.name = 'TRUE';
+A[0] = 7;
+
+// 3. Object.prototype goes to dictionary mode: Object.assign from a source of
+// more than 1020 properties normalizes its target first; the first getter
+// throws, so nothing is stored.
+const big = {};
+Object.defineProperty(big, 'g0', { enumerable: true, get() { throw 1; } });
+for (let i = 0; i < 1100; i++) big['p' + i] = i;
+try { Object.assign(A, big); } catch (e) {}
+
+// 4. The function under test:
+// Every double of the array literal holds the two words NAME (low) and
+// WORD (high).
+const dv = new DataView(new ArrayBuffer(8));
+dv.setUint32(0, NAME, true); dv.setUint32(4, WORD, true);
+const h = new Function('A', 'flag',
+    'A[0]; ' + // Map check
+    'f(flag); ' + // Object literal
+    // Big double array
+    'var o = [' +
+    Array(2048).fill(String(dv.getFloat64(0, true))).join(',') +
+    ']; ' +
+    'var x = A.name; ' + // Property load from an object whose map we already
+                         // checked
+    'return [x.length, o];');
+
+// 5. Warm-up without the literal
+%PrepareFunctionForOptimization(h);
+h(A, false);
+%OptimizeMaglevOnNextCall(h);
+
+assertFalse(%HasFastProperties(A));
+
+// 6. One call with the literal.
+h(A, true);
+assertUnoptimized(h);
+
+// Creating the object literal optimized the prototype.
+assertTrue(%HasFastProperties(A));
diff --git a/deps/v8/test/mjsunit/regress/regress-575525282-2.js b/deps/v8/test/mjsunit/regress/regress-575525282-2.js
new file mode 100644
index 00000000000..28d7eb03a03
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-575525282-2.js
@@ -0,0 +1,66 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --maglev
+
+// 1. Map setup
+function f(flag) {
+  if (flag) return {a: 1, b: {c: 2}};
+  return 0;
+}
+%PrepareFunctionForOptimization(f);
+f(true);
+f(true);
+const sib = { a: 1, z: 0 };
+
+// Resulting maps:
+//-> M1 (a: smi) -> M2 (a: smi, b: HeapObject)
+//            \
+//             ---> M3 (a: smi, z: smi)
+
+// This deprecates all above maps.
+sib.a = 1.5;
+
+// 2. Object.prototype with more properties, one of them "x1" and one element.
+//    Populate enough fast properties with ('x1', 'WRONG', 0) triples so that
+//    when Object.prototype later transitions back from dictionary mode to fast
+//    mode, a stale LoadDictionaryField for "x1" reads 'WRONG' in-bounds from
+//    the new PropertyArray instead of 'TRUE'.
+const A = Object.prototype;
+A.x1 = 'TRUE';
+A[0] = 7;
+for (let i = 0; i < 80; i++) {
+  A['k' + i] = (i % 3 === 0) ? 'x1' : (i % 3 === 1 ? 'WRONG' : 0);
+}
+
+// 3. Object.prototype goes to dictionary mode: Object.assign from a source of
+// more than 1020 properties normalizes its target first; the first getter
+// throws, so nothing is stored.
+const big = {};
+Object.defineProperty(big, 'g0', { enumerable: true, get() { throw 1; } });
+for (let i = 0; i < 1100; i++) big['p' + i] = i;
+try { Object.assign(A, big); } catch (e) {}
+
+// 4. The function under test:
+function h(A, flag) {
+  A[0];         // Map check
+  f(flag);      // Object literal
+  return A.x1;  // Property load from an object whose map we already checked
+}
+
+// 5. Warm-up without the literal
+%PrepareFunctionForOptimization(h);
+assertEquals('TRUE', h(A, false));
+%OptimizeMaglevOnNextCall(h);
+assertEquals('TRUE', h(A, false));
+assertMaglevved(h);
+
+assertFalse(%HasFastProperties(A));
+
+// 6. One call with the literal.
+assertEquals('TRUE', h(A, true));
+assertUnoptimized(h);
+
+// Creating the object literal optimized the prototype.
+assertTrue(%HasFastProperties(A));
diff --git a/deps/v8/test/mjsunit/regress/regress-575525282-3.js b/deps/v8/test/mjsunit/regress/regress-575525282-3.js
new file mode 100644
index 00000000000..fda9eadb752
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-575525282-3.js
@@ -0,0 +1,66 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --maglev
+
+// 1. Map setup
+function f(flag) {
+  if (flag) return [{a: 1, b: 2}];
+  return 0;
+}
+%PrepareFunctionForOptimization(f);
+f(true);
+f(true);
+const sib = { a: 1, z: 0 };
+
+// Resulting maps:
+//-> M1 (a: smi) -> M2 (a: smi, b: smi)
+//            \
+//             ---> M3 (a: smi, z: smi)
+
+// This deprecates all above maps.
+sib.a = 1.5;
+
+// 2. Object.prototype with more properties, one of them "x1" and one element.
+//    Populate enough fast properties with ('x1', 'WRONG', 0) triples so that
+//    when Object.prototype later transitions back from dictionary mode to fast
+//    mode, a stale LoadDictionaryField for "x1" reads 'WRONG' in-bounds from
+//    the new PropertyArray instead of 'TRUE'.
+const A = Object.prototype;
+A.x1 = 'TRUE';
+A[0] = 7;
+for (let i = 0; i < 80; i++) {
+  A['k' + i] = (i % 3 === 0) ? 'x1' : (i % 3 === 1 ? 'WRONG' : 0);
+}
+
+// 3. Object.prototype goes to dictionary mode: Object.assign from a source of
+// more than 1020 properties normalizes its target first; the first getter
+// throws, so nothing is stored.
+const big = {};
+Object.defineProperty(big, 'g0', { enumerable: true, get() { throw 1; } });
+for (let i = 0; i < 1100; i++) big['p' + i] = i;
+try { Object.assign(A, big); } catch (e) {}
+
+// 4. The function under test:
+function h(A, flag) {
+  A[0];         // Map check
+  f(flag);      // Array literal with nested object literal
+  return A.x1;  // Property load from an object whose map we already checked
+}
+
+// 5. Warm-up without the literal
+%PrepareFunctionForOptimization(h);
+assertEquals('TRUE', h(A, false));
+%OptimizeMaglevOnNextCall(h);
+assertEquals('TRUE', h(A, false));
+assertMaglevved(h);
+
+assertFalse(%HasFastProperties(A));
+
+// 6. One call with the literal.
+assertEquals('TRUE', h(A, true));
+assertUnoptimized(h);
+
+// Creating the array literal optimized the prototype.
+assertTrue(%HasFastProperties(A));
diff --git a/deps/v8/test/mjsunit/regress/regress-577242082.js b/deps/v8/test/mjsunit/regress/regress-577242082.js
new file mode 100644
index 00000000000..e9e664f056e
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-577242082.js
@@ -0,0 +1,30 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --maglev --allow-natives-syntax
+
+[1].values().extra = 1;
+
+function sink(...args) {}
+%PrepareFunctionForOptimization(sink);
+
+function helper(o, cond) {
+  if (cond) {
+    sink(o.a);
+  }
+}
+%PrepareFunctionForOptimization(helper);
+
+function g(cond) {
+  let iter = [1].values();
+  delete {}.a;
+  helper(iter, cond);
+}
+%PrepareFunctionForOptimization(g);
+
+helper({ a: 42 }, true);
+
+g(false);
+%OptimizeMaglevOnNextCall(g);
+g(false);
diff --git a/deps/v8/test/mjsunit/regress/regress-577627207.js b/deps/v8/test/mjsunit/regress/regress-577627207.js
new file mode 100644
index 00000000000..0c92fe1247c
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-577627207.js
@@ -0,0 +1,34 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --expose-fast-api
+
+const fast_c_api = new d8.test.FastCAPI();
+let deopt = false;
+const obj = {
+  valueOf() {
+    if (deopt) {
+      %DeoptimizeFunction(foo);
+      d8.terminateNow();
+    }
+    return 1;
+  }
+};
+function foo() {
+  try {
+    fast_c_api.call_to_number(obj);
+  } catch (e) {
+  }
+}
+%PrepareFunctionForOptimization(foo);
+foo();
+foo();
+%OptimizeFunctionOnNextCall(foo);
+setTimeout(() => {
+  Promise.resolve().then(() => {
+    deopt = true;
+    foo();
+    assertUnreachable();
+  });
+}, 0);
diff --git a/deps/v8/test/mjsunit/regress/wasm/regress-579313193.js b/deps/v8/test/mjsunit/regress/wasm/regress-579313193.js
new file mode 100644
index 00000000000..fbfe9b3ca20
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/wasm/regress-579313193.js
@@ -0,0 +1,206 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
+
+(function TestImmutableUnrelatedPackedStructGet() {
+  const builder = new WasmModuleBuilder();
+  const superStruct = builder.addStruct([]);
+  const structF64 = builder.addStruct(
+      {fields: [makeField(kWasmF64, false)], supertype: superStruct});
+  const structI8 = builder.addStruct(
+      {fields: [makeField(kWasmI8, false)], supertype: superStruct});
+  const structI16 = builder.addStruct(
+      {fields: [makeField(kWasmI16, false)], supertype: superStruct});
+
+  builder.addFunction('makeStructF64', makeSig([kWasmF64], [kWasmExternRef]))
+      .addBody([
+        kExprLocalGet, 0,
+        kGCPrefix, kExprStructNew, structF64,
+        kGCPrefix, kExprExternConvertAny,
+      ])
+      .exportFunc();
+
+  for (const [name, targetStruct, getOp] of [
+           ['getI8S', structI8, kExprStructGetS],
+           ['getI8U', structI8, kExprStructGetU],
+           ['getI16S', structI16, kExprStructGetS],
+           ['getI16U', structI16, kExprStructGetU],
+       ]) {
+    builder.addFunction(name, makeSig([kWasmExternRef], [kWasmI32]))
+        .addBody([
+          kExprLocalGet, 0,
+          kGCPrefix, kExprAnyConvertExtern,
+          kGCPrefix, kExprRefCast, superStruct,
+          kExprLocalGet, 0,
+          kGCPrefix, kExprAnyConvertExtern,
+          kGCPrefix, kExprRefCast, structF64,
+          kGCPrefix, kExprStructGet, structF64, 0,
+          kExprDrop,
+          kGCPrefix, kExprRefCast, targetStruct,
+          kGCPrefix, getOp, targetStruct, 0,
+        ])
+        .exportFunc();
+  }
+
+  const instance = builder.instantiate();
+  const s = instance.exports.makeStructF64(1.5);
+
+  for (const fn of [
+           instance.exports.getI8S,
+           instance.exports.getI8U,
+           instance.exports.getI16S,
+           instance.exports.getI16U,
+       ]) {
+    const caller = (x) => fn(x) + 1;
+    %PrepareFunctionForOptimization(caller);
+    for (let i = 0; i < 3; i++) {
+      assertTraps(kTrapIllegalCast, () => caller(s));
+    }
+    %OptimizeFunctionOnNextCall(caller);
+    assertTraps(kTrapIllegalCast, () => caller(s));
+  }
+})();
+
+(function TestMutableUnrelatedStructSetToPackedGet() {
+  const builder = new WasmModuleBuilder();
+  const superStruct = builder.addStruct([]);
+  const structF64 = builder.addStruct(
+      {fields: [makeField(kWasmF64, true)], supertype: superStruct});
+  const structF32 = builder.addStruct(
+      {fields: [makeField(kWasmF32, true)], supertype: superStruct});
+  const structI8 = builder.addStruct(
+      {fields: [makeField(kWasmI8, true)], supertype: superStruct});
+  const structI16 = builder.addStruct(
+      {fields: [makeField(kWasmI16, true)], supertype: superStruct});
+
+  builder.addFunction('makeStructF64', makeSig([kWasmF64], [kWasmExternRef]))
+      .addBody([
+        kExprLocalGet, 0,
+        kGCPrefix, kExprStructNew, structF64,
+        kGCPrefix, kExprExternConvertAny,
+      ])
+      .exportFunc();
+
+  builder.addFunction('makeStructF32', makeSig([kWasmF32], [kWasmExternRef]))
+      .addBody([
+        kExprLocalGet, 0,
+        kGCPrefix, kExprStructNew, structF32,
+        kGCPrefix, kExprExternConvertAny,
+      ])
+      .exportFunc();
+
+  builder.addFunction('setF64GetI8S',
+                      makeSig([kWasmExternRef, kWasmF64], [kWasmI32]))
+      .addBody([
+        kExprLocalGet, 0,
+        kGCPrefix, kExprAnyConvertExtern,
+        kGCPrefix, kExprRefCast, superStruct,
+        kExprLocalGet, 0,
+        kGCPrefix, kExprAnyConvertExtern,
+        kGCPrefix, kExprRefCast, structF64,
+        kExprLocalGet, 1,
+        kGCPrefix, kExprStructSet, structF64, 0,
+        kGCPrefix, kExprRefCast, structI8,
+        kGCPrefix, kExprStructGetS, structI8, 0,
+      ])
+      .exportFunc();
+
+  builder.addFunction('setF32GetI16U',
+                      makeSig([kWasmExternRef, kWasmF32], [kWasmI32]))
+      .addBody([
+        kExprLocalGet, 0,
+        kGCPrefix, kExprAnyConvertExtern,
+        kGCPrefix, kExprRefCast, superStruct,
+        kExprLocalGet, 0,
+        kGCPrefix, kExprAnyConvertExtern,
+        kGCPrefix, kExprRefCast, structF32,
+        kExprLocalGet, 1,
+        kGCPrefix, kExprStructSet, structF32, 0,
+        kGCPrefix, kExprRefCast, structI16,
+        kGCPrefix, kExprStructGetU, structI16, 0,
+      ])
+      .exportFunc();
+
+  const instance = builder.instantiate();
+  const sF64 = instance.exports.makeStructF64(2.5);
+  const sF32 = instance.exports.makeStructF32(1.25);
+
+  const callerF64 = (x) => instance.exports.setF64GetI8S(x, 3.5) + 1;
+  %PrepareFunctionForOptimization(callerF64);
+  for (let i = 0; i < 3; i++) {
+    assertTraps(kTrapIllegalCast, () => callerF64(sF64));
+  }
+  %OptimizeFunctionOnNextCall(callerF64);
+  assertTraps(kTrapIllegalCast, () => callerF64(sF64));
+
+  const callerF32 = (x) => instance.exports.setF32GetI16U(x, 2.25) + 1;
+  %PrepareFunctionForOptimization(callerF32);
+  for (let i = 0; i < 3; i++) {
+    assertTraps(kTrapIllegalCast, () => callerF32(sF32));
+  }
+  %OptimizeFunctionOnNextCall(callerF32);
+  assertTraps(kTrapIllegalCast, () => callerF32(sF32));
+})();
+
+(function TestReachablePackedLoadElimination() {
+  const builder = new WasmModuleBuilder();
+  const structPacked = builder.addStruct([
+    makeField(kWasmI8, true),
+    makeField(kWasmI16, true),
+  ]);
+
+  builder.addFunction('makePacked', makeSig([], [kWasmExternRef]))
+      .addBody([
+        kGCPrefix, kExprStructNewDefault, structPacked,
+        kGCPrefix, kExprExternConvertAny,
+      ])
+      .exportFunc();
+
+  for (const [name, fieldIdx, getOp] of [
+           ['setGetI8S', 0, kExprStructGetS],
+           ['setGetI8U', 0, kExprStructGetU],
+           ['setGetI16S', 1, kExprStructGetS],
+           ['setGetI16U', 1, kExprStructGetU],
+       ]) {
+    builder.addFunction(name, makeSig([kWasmExternRef, kWasmI32], [kWasmI32]))
+        .addBody([
+          kExprLocalGet, 0,
+          kGCPrefix, kExprAnyConvertExtern,
+          kGCPrefix, kExprRefCast, structPacked,
+          kExprLocalGet, 1,
+          kGCPrefix, kExprStructSet, structPacked, fieldIdx,
+          kExprLocalGet, 0,
+          kGCPrefix, kExprAnyConvertExtern,
+          kGCPrefix, kExprRefCast, structPacked,
+          kGCPrefix, getOp, structPacked, fieldIdx,
+        ])
+        .exportFunc();
+  }
+
+  const instance = builder.instantiate();
+  const s = instance.exports.makePacked();
+  const {setGetI8S, setGetI8U, setGetI16S, setGetI16U} = instance.exports;
+
+  function roundtrip(ref, v) {
+    return [
+      setGetI8S(ref, v),
+      setGetI8U(ref, v),
+      setGetI16S(ref, v),
+      setGetI16U(ref, v),
+    ];
+  }
+
+  %PrepareFunctionForOptimization(roundtrip);
+  for (let i = 0; i < 3; i++) {
+    assertEquals([-1, 0xff, -1, 0xffff], roundtrip(s, -1));
+  }
+  %OptimizeFunctionOnNextCall(roundtrip);
+  assertEquals([0, 0, 0, 0], roundtrip(s, 0));
+  assertEquals([-1, 0xff, -1, 0xffff], roundtrip(s, -1));
+  assertEquals([-0x80, 0x80, 0x1280, 0x1280], roundtrip(s, 0x11280));
+  assertEquals([0x7f, 0x7f, -0x7f81, 0x807f], roundtrip(s, 0x1807f));
+})();