From aaa2cabfbcb8d9997ce67e166f796f46d5b72342 Mon Sep 17 00:00:00 2001 From: Kevin Liu Date: Tue, 15 Sep 2026 18:40:08 +0000 Subject: [PATCH] Disable V8 optimization paths affected by array sort bugs (#45760) ## Why The pinned V8 can inline `Array.prototype.sort` with incompatible element kinds when a comparator mutates the array, allowing an object to be stored in an integer-elements array. ## What changed Disable Maglev, Turbolev, and TurboFan array builtin inlining during code-mode runtime initialization until the V8 artifacts include the upstream fix. ## Testing Add an integration regression test that requests top-tier and Maglev optimization, checks element kinds after comparator mutation, and verifies ordinary numeric sorting still returns `[1,2,3]`. GitOrigin-RevId: cea38e920245d6a133a5263118dc664fb3e61838 --- codex-rs/code-mode-runtime/src/v8_init.rs | 5 ++ .../code-mode-runtime/tests/array_sort.rs | 84 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 codex-rs/code-mode-runtime/tests/array_sort.rs diff --git a/codex-rs/code-mode-runtime/src/v8_init.rs b/codex-rs/code-mode-runtime/src/v8_init.rs index 0d00d9fad5..016992c932 100644 --- a/codex-rs/code-mode-runtime/src/v8_init.rs +++ b/codex-rs/code-mode-runtime/src/v8_init.rs @@ -42,6 +42,11 @@ pub(crate) fn ensure_v8_initialized() -> Result<(), String> { fn initialize_v8_with_mode(jit_mode: V8JitMode) -> Result { v8::icu::set_common_data_77(deno_core_icudata::ICU_DATA) .map_err(|error_code| format!("failed to initialize ICU data: {error_code}"))?; + // The pinned V8 can inline Array.prototype.sort with incompatible element kinds. + // Disable the affected paths in TurboFan and the Maglev/Turbolev frontend until + // our V8 artifacts include the upstream fix for mixed-element sorting: + // https://github.com/v8/v8/commit/e0562d87ad9c17042b581582c99237d798572e67 + v8::V8::set_flags_from_string("--no-maglev --no-turbolev --no-turbo-inline-array-builtins"); match jit_mode { V8JitMode::Enabled => {} V8JitMode::Disabled => v8::V8::set_flags_from_string("--jitless"), diff --git a/codex-rs/code-mode-runtime/tests/array_sort.rs b/codex-rs/code-mode-runtime/tests/array_sort.rs new file mode 100644 index 0000000000..ca9039d6df --- /dev/null +++ b/codex-rs/code-mode-runtime/tests/array_sort.rs @@ -0,0 +1,84 @@ +//! Checks array element kinds when a sort comparator mutates its receiver. + +use codex_code_mode_runtime::ExecuteRequest; +use codex_code_mode_runtime::FunctionCallOutputContentItem; +use codex_code_mode_runtime::InProcessCodeModeSession; +use codex_code_mode_runtime::NoopCodeModeSessionDelegate; +use codex_code_mode_runtime::RuntimeResponse; +use pretty_assertions::assert_eq; +use std::sync::Arc; + +#[tokio::test] +async fn array_sort_preserves_element_kinds_after_comparator_mutation() { + // Native syntax is process-wide, so keep this in its own integration target. + // Request Turbolev so initialization must also disable its Maglev frontend. + v8::V8::set_flags_from_string("--allow-natives-syntax --turbolev"); + let service = InProcessCodeModeSession::new(); + let started = service + .execute( + ExecuteRequest { + tool_call_id: "call_1".to_string(), + enabled_tools: Vec::new(), + source: r#" +function sortTopTier(values) { + return values.sort(() => { + values.fill(0); + return 0; + }); +} +function sortMaglev(values) { + return values.sort(() => { + values.fill(0); + return 0; + }); +} +function prepare(sort) { + %PrepareFunctionForOptimization(sort); + for (let i = 0; i < 100; ++i) { + sort([1, 2]); + sort([{}, {}]); + } +} +function check(sort) { + sort([1, 2]); + const object = {}; + const values = [object, {}]; + sort(values); + if (%HasSmiElements(values) && values[0] === object) { + throw new Error("sort stored an object in an integer-elements array"); + } +} +prepare(sortTopTier); +%OptimizeFunctionOnNextCall(sortTopTier); +check(sortTopTier); +prepare(sortMaglev); +%OptimizeMaglevOnNextCall(sortMaglev); +check(sortMaglev); +text(JSON.stringify([3, 1, 2].sort((a, b) => a - b))); +"# + .to_string(), + yield_time_ms: None, + max_output_tokens: None, + }, + Arc::new(NoopCodeModeSessionDelegate), + ) + .await + .expect("start code-mode cell"); + let cell_id = started.cell_id.clone(); + let response = started + .initial_response() + .await + .expect("execute code-mode cell"); + + assert_eq!( + response, + RuntimeResponse::Result { + code_mode_host_duration: None, + cell_id, + content_items: vec![FunctionCallOutputContentItem::InputText { + text: "[1,2,3]".to_string(), + }], + error_text: None, + } + ); +}