Skip to content

Conversation

@devsnek
Copy link
Member

@devsnek devsnek commented Dec 10, 2025

denoland/deno_core#1256

the changes in in node-api to what node itself is doing, so it should be alright.

@coderabbitai
Copy link

coderabbitai bot commented Dec 10, 2025

Walkthrough

This pull request updates Deno's dependency resolution and V8 integration. The deno_core workspace dependency switches from a published crate version to a local path reference. A default V8 flag is removed from the CLI arguments. NAPI string extraction methods and web encoding operations are migrated to use v8's newer write helpers (write_v2, write_utf8_v2) with explicit null termination and updated handling of invalid UTF-8 sequences, replacing previous approaches that handled termination differently.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'v8 14.4' directly and clearly indicates the main change: upgrading to V8 version 14.4, which is reflected across all modified files.
Description check ✅ Passed The description provides a link to the related deno_core PR, which contextualizes the changes being made in this pull request.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch v8-144

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ed55de8 and feca054.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • Cargo.toml (1 hunks)
  • cli/args/mod.rs (0 hunks)
  • ext/napi/js_native_api.rs (3 hunks)
  • ext/web/lib.rs (1 hunks)
💤 Files with no reviewable changes (1)
  • cli/args/mod.rs
🧰 Additional context used
📓 Path-based instructions (2)
ext/**/lib.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Extensions should provide ops (operations) exposed to JavaScript in Rust code within ext/<extension_name>/ directories

Files:

  • ext/web/lib.rs
**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.rs: For debugging Rust code, set breakpoints in IDE debuggers (VS Code with rust-analyzer, IntelliJ IDEA) or use lldb directly
Use eprintln!() or dbg!() macros for debug prints in Rust code

Files:

  • ext/web/lib.rs
  • ext/napi/js_native_api.rs

⚙️ CodeRabbit configuration file

Don't worry about coverage of Rust docstrings. Don't be nitpicky about it. Leave it to the author's judgement if such a documentation is necessary.

Files:

  • ext/web/lib.rs
  • ext/napi/js_native_api.rs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: test release linux-aarch64
  • GitHub Check: test release macos-x86_64
  • GitHub Check: test release macos-aarch64
🔇 Additional comments (2)
ext/napi/js_native_api.rs (1)

2176-2188: LGTM! Correct UTF-8 write implementation.

The pattern here is correct: create a buffer with bufsize - 1 capacity, write without auto-null-termination, manually append the null byte, and report the actual copied count. This correctly handles the null terminator accounting.

ext/web/lib.rs (1)

399-406: LGTM! Correctly migrated to write_utf8_v2 API.

The migration from write_utf8 to write_utf8_v2 with kReplaceInvalidUtf8 flag correctly maintains the previous behavior of replacing invalid UTF-8 sequences with the Unicode replacement character (U+FFFD). The nchars capture via the optional parameter is the proper pattern for the new API, correctly storing the number of UTF-16 code units in out_buf[0] and bytes written in out_buf[1].

[workspace.dependencies]
deno_ast = { version = "=0.52.0", features = ["transpiling"] }
deno_core = { version = "0.372.0" }
deno_core = { path = "../deno_core/core" } #version = "0.372.0" }
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Local path dependency should not be merged to main.

This changes deno_core to reference a local path (../deno_core/core) outside the repository. This will break builds for anyone who doesn't have the expected sibling directory structure. The commented-out version suggests this is a temporary development change.

Revert to the versioned dependency before merging, or update to the appropriate published version that includes the V8 14.4 changes.

-deno_core = { path = "../deno_core/core" } #version = "0.372.0" }
+deno_core = "0.372.0"  # Update to version with V8 14.4 support
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
deno_core = { path = "../deno_core/core" } #version = "0.372.0" }
deno_core = "0.372.0" # Update to version with V8 14.4 support
🤖 Prompt for AI Agents
In Cargo.toml at line 66, the deno_core dependency was changed to a local path
reference (deno_core = { path = "../deno_core/core" }) which must not be merged;
revert this to a published version by replacing the path spec with the previous
or appropriate published version (e.g. deno_core = "0.372.0" or the correct
crate version that includes the V8 14.4 changes), remove any stray comment
braces, and run cargo update/cargo generate-lockfile so the lockfile reflects
the published dependency.

Comment on lines +2132 to 2139
let length = value.length().min(bufsize - 1);
let buffer = unsafe { std::slice::from_raw_parts_mut(buf as _, length) };
value.write_one_byte_v2(scope, 0, buffer, v8::WriteFlags::kNullTerminate);
if !result.is_null() {
unsafe {
*result = copied;
*result = length;
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Result length may be incorrect when kNullTerminate consumes a buffer slot.

With kNullTerminate, V8's write_one_byte_v2 writes min(string_length, buffer.len() - 1) characters plus a null terminator. However, the code pre-calculates length = value.length().min(bufsize - 1) and passes a buffer of exactly that size.

If value.length() < bufsize - 1, the buffer has value.length() slots, so V8 writes only value.length() - 1 characters + null, but you report length (which equals value.length()).

Consider matching the UTF-8 implementation pattern: pass the full available buffer and manually append the null terminator, or adjust the result to reflect actual bytes written.

   } else if bufsize != 0 {
-    let length = value.length().min(bufsize - 1);
-    let buffer = unsafe { std::slice::from_raw_parts_mut(buf as _, length) };
-    value.write_one_byte_v2(scope, 0, buffer, v8::WriteFlags::kNullTerminate);
+    let buffer = unsafe { std::slice::from_raw_parts_mut(buf as _, bufsize - 1) };
+    let copied = value.write_one_byte_v2(scope, 0, buffer, v8::WriteFlags::empty());
+    unsafe {
+      buf.add(copied).write(0);
+    }
     if !result.is_null() {
       unsafe {
-        *result = length;
+        *result = copied;
       }
     }
🤖 Prompt for AI Agents
In ext/napi/js_native_api.rs around lines 2132 to 2139, the code precomputes
length and hands a buffer sized to length while also using
v8::WriteFlags::kNullTerminate, which can cause the reported length to be one
too large when V8 consumes a slot for the terminator; instead follow the UTF‑8
pattern: pass the full available buffer to V8 (so it can write up to bufsize-1
chars), capture the actual number of bytes written by the write call (or compute
it from the returned/observed value), then manually append a null terminator at
the next slot and store the actual bytes written into *result; alternatively, if
you must keep kNullTerminate, adjust the reported result to subtract the
terminator slot when V8 consumed it.

Comment on lines +2224 to 2231
let length = value.length().min(bufsize - 1);
let buffer = unsafe { std::slice::from_raw_parts_mut(buf as _, length) };
value.write_v2(scope, 0, buffer, v8::WriteFlags::kNullTerminate);
if !result.is_null() {
unsafe {
*result = copied;
*result = length;
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Same result length issue as latin1 function.

This has the same problem as napi_get_value_string_latin1: when kNullTerminate is used with a buffer of exactly length elements, V8 writes length - 1 characters plus null, but the code reports length as the result.

Apply the same fix pattern as the UTF-8 version.

   } else if bufsize != 0 {
-    let length = value.length().min(bufsize - 1);
-    let buffer = unsafe { std::slice::from_raw_parts_mut(buf as _, length) };
-    value.write_v2(scope, 0, buffer, v8::WriteFlags::kNullTerminate);
+    let buffer = unsafe { std::slice::from_raw_parts_mut(buf, bufsize - 1) };
+    let copied = value.write_v2(scope, 0, buffer, v8::WriteFlags::empty());
+    unsafe {
+      *buf.add(copied) = 0;
+    }
     if !result.is_null() {
       unsafe {
-        *result = length;
+        *result = copied;
       }
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let length = value.length().min(bufsize - 1);
let buffer = unsafe { std::slice::from_raw_parts_mut(buf as _, length) };
value.write_v2(scope, 0, buffer, v8::WriteFlags::kNullTerminate);
if !result.is_null() {
unsafe {
*result = copied;
*result = length;
}
}
let buffer = unsafe { std::slice::from_raw_parts_mut(buf, bufsize - 1) };
let copied = value.write_v2(scope, 0, buffer, v8::WriteFlags::empty());
unsafe {
*buf.add(copied) = 0;
}
if !result.is_null() {
unsafe {
*result = copied;
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants