Skip to content

fix(sqlite): complete Node 26 parity - #6896

Merged
proggeramlug merged 17 commits into
mainfrom
fix/sqlite-node26-parity
Jul 30, 2026
Merged

fix(sqlite): complete Node 26 parity#6896
proggeramlug merged 17 commits into
mainfrom
fix/sqlite-node26-parity

Conversation

@TheHypnoo

@TheHypnoo TheHypnoo commented Jul 27, 2026

Copy link
Copy Markdown
Member

Summary

Complete node:sqlite parity with Node.js 26.5.0.

Changes

  • Match Node binding, database, aggregate, and iterator behavior.
  • Reject Symbol statement parameters with the Node-compatible error.
  • Add a regression test for Symbol parameter classification.

Related issue

Closes #6776

Test plan

  • cargo build --release -p perry
  • cargo test -p perry-stdlib symbols_are_not_named_parameter_objects --lib
  • PATH=/opt/homebrew/Cellar/node/26.5.0/bin:$PATH ./run_parity_tests.sh --suite node-suite --module sqlite

Checklist

  • I have NOT bumped the workspace version or edited CLAUDE.md / CHANGELOG.md (maintainer handles these at merge)
  • My commits follow the loose feat: / fix: / docs: / chore: prefix convention used in the log
  • I've read CONTRIBUTING.md and agree to the Code of Conduct

Summary by CodeRabbit

  • New Features

    • Added Node.js 26-compatible SQLite support, including database serialization and deserialization.
    • Added SQLite limit property access and improved statement iteration behavior.
    • Added support for TypedArray and zero-length buffer parameter binding.
    • Enabled configurable SQLite double-quoted string behavior.
  • Bug Fixes

    • Improved finalized-statement detection and iterator invalidation.
    • Corrected named and positional parameter handling.
    • Strengthened validation for SQLite options, aggregate settings, symbols, and invalid SQL input.

@TheHypnoo TheHypnoo added the type:bug Bug fix label Jul 27, 2026
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR extends Node.js SQLite compatibility with serialization, deserialization, typed-array binding, limits properties, DQS configuration, iterator invalidation, and validation changes. It also makes loop GC safepoint analysis include control expressions and updates HTTP dispatch feature gates.

Changes

node:sqlite parity

Layer / File(s) Summary
Database surface and serialization
crates/perry-stdlib/src/sqlite/..., crates/perry-stdlib/src/common/dispatch/..., crates/perry-codegen/src/lower_call/native_table/databases.rs
Adds DatabaseSync serialization methods, SQLite type metadata, limits property names, stricter path and SQL handling, DQS configuration, and dispatch wiring.
Statement iteration invalidation
crates/perry-runtime/src/array/iter_object.rs, crates/perry-stdlib/src/sqlite.rs, crates/perry-stdlib/src/sqlite/node_stmt_session.rs, crates/perry-stdlib/src/sqlite/connection.rs, crates/perry-stdlib/src/sqlite/bind.rs
Adds statement epochs, invalidates iterators after execution or finalization, and returns SQLite-specific iterator results.
SQLite bindings and validation
crates/perry-stdlib/src/sqlite/bind.rs, crates/perry-stdlib/src/sqlite/node_db.rs, crates/perry-stdlib/src/sqlite/options.rs, changelog.d/6896-sqlite-node26-parity.md
Updates typed-array and buffer binding, positional parameters, aggregate finalization, SQL errors, option validation, symbol handling, tests, and changelog metadata.

Loop GC safepoints

Layer / File(s) Summary
Controls-aware safepoint analysis
crates/perry-codegen/src/stmt/loops.rs
Passes loop conditions and updates into allocation analysis for for, while, and do..while safepoint decisions.

HTTP dispatch gate cleanup

Layer / File(s) Summary
HTTP dispatch gate updates
crates/perry-stdlib/src/common/dispatch/init.rs
Removes the internal HTTP-client agent property-set route, moves headers registration to the web-fetch gate, and updates extension routing comments.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DatabaseSync
  participant SQLiteDispatch
  participant DatabaseSerialize
  participant SQLite
  DatabaseSync->>SQLiteDispatch: call serialize(schema)
  SQLiteDispatch->>DatabaseSerialize: dispatch database handle and schema
  DatabaseSerialize->>SQLite: serialize selected database
  SQLite-->>DatabaseSerialize: return serialized image
  DatabaseSerialize-->>DatabaseSync: return Uint8Array-like buffer
Loading

Suggested labels: parity

Suggested reviewers: proggeramlug

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR also changes unrelated loop safepoint logic and non-sqlite dispatch wiring, which are outside the sqlite parity scope. Remove or split out the loop safepoint and http-client/web-fetch dispatch changes into a separate PR unless they are required for sqlite parity.
Docstring Coverage ⚠️ Warning Docstring coverage is 45.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: completing SQLite parity for Node 26.
Description check ✅ Passed The description includes summary, concrete changes, linked issue, test plan, and checklist, matching the template well.
Linked Issues check ✅ Passed The PR addresses the sqlite parity gaps in #6776, including binding, database, options, aggregates, and iterator behavior.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/sqlite-node26-parity

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/perry-stdlib/src/sqlite/bind.rs (1)

251-260: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Don’t treat bare TypedArray/DataView positional values as named-parameter objects.

In bind_node_sqlite_params, this predicate is checked for only the first argument. Bare TypedArray values belong on the direct positional bind path because bind_node_sqlite_value handles them with is_registered_buffer/TypedArrayHeader checks separately. Since is_named_parameter_object only excludes registered buffers and symbols, a lone Uint8Array/DataView is misclassified as named_params and its numeric keys are bound as named parameters instead of as parameter 1.

🐛 Proposed fix
 pub(crate) fn is_named_parameter_object(value: f64) -> bool {
     let js = value_from_f64(value);
     if !js.is_pointer() {
         return false;
     }
     let raw = raw_addr_from_value(value);
     raw >= 0x1000
         && !is_registered_buffer(raw)
+        && perry_runtime::typedarray::lookup_typed_array_kind(raw).is_none()
         && unsafe { perry_runtime::symbol::js_is_symbol(value) == 0 }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/perry-stdlib/src/sqlite/bind.rs` around lines 251 - 260, Update
is_named_parameter_object to exclude all TypedArray and DataView values, not
only registered buffers and symbols. Reuse the existing TypedArrayHeader or
related type-detection logic used by bind_node_sqlite_value, so bare binary
values remain on the direct positional bind path while ordinary objects retain
named-parameter handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@crates/perry-stdlib/src/sqlite/bind.rs`:
- Around line 251-260: Update is_named_parameter_object to exclude all
TypedArray and DataView values, not only registered buffers and symbols. Reuse
the existing TypedArrayHeader or related type-detection logic used by
bind_node_sqlite_value, so bare binary values remain on the direct positional
bind path while ordinary objects retain named-parameter handling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 214fce9f-4d27-4dbd-9cdb-45fbcb1bc121

📥 Commits

Reviewing files that changed from the base of the PR and between b5727f3 and c910a9d.

📒 Files selected for processing (11)
  • crates/perry-codegen/src/lower_call/native_table/databases.rs
  • crates/perry-runtime/src/array/iter_object.rs
  • crates/perry-stdlib/src/common/dispatch/init.rs
  • crates/perry-stdlib/src/common/dispatch/method_dispatch.rs
  • crates/perry-stdlib/src/sqlite.rs
  • crates/perry-stdlib/src/sqlite/bind.rs
  • crates/perry-stdlib/src/sqlite/connection.rs
  • crates/perry-stdlib/src/sqlite/dispatch.rs
  • crates/perry-stdlib/src/sqlite/node_db.rs
  • crates/perry-stdlib/src/sqlite/node_stmt_session.rs
  • crates/perry-stdlib/src/sqlite/options.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
crates/perry-codegen/src/loop_purity.rs (2)

128-130: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Do not classify generic IndexUpdate as allocation-free.

Unlike the typed-array write variants, this arm does not prove a fixed-size receiver or an in-bounds index. A plain array expression such as arr[i]++ can grow/reallocate when i is out of bounds, causing body_may_allocate to suppress the required moving-GC safepoint. Remove this generic arm or restrict it to a statically proven fixed-size/bounds-safe case.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/perry-codegen/src/loop_purity.rs` around lines 128 - 130, Remove the
generic Expr::IndexUpdate arm from the allocation-free classification in
loop_purity.rs, or restrict it only to cases with statically proven fixed-size
receivers and in-bounds indices. Do not treat expr_alloc_free(object) and
expr_alloc_free(index) alone as sufficient; preserve the existing typed-array
write handling.

65-67: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Include loop control expressions in safepoint eligibility checks.

emit_gc_loop_safepoint only receives body, but lower_for/lower_while/lower_do_while invoke it before lowering init/update/condition. An allocating for initializer/update or while/do-while condition can therefore make the loop-body lowerings skip js_gc_loop_safepoint; pass the loop control state through or make the callee check stmt_alloc_free/expr_alloc_free for that control.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/perry-codegen/src/loop_purity.rs` around lines 65 - 67, Update loop
safepoint eligibility around body_may_allocate and emit_gc_loop_safepoint to
account for control expressions and statements, not only the loop body: include
for initializers and updates plus while/do-while conditions when checking
allocation, and pass or inspect that control state before lowering. Preserve
safepoints whenever any loop control component may allocate.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@crates/perry-codegen/src/loop_purity.rs`:
- Around line 128-130: Remove the generic Expr::IndexUpdate arm from the
allocation-free classification in loop_purity.rs, or restrict it only to cases
with statically proven fixed-size receivers and in-bounds indices. Do not treat
expr_alloc_free(object) and expr_alloc_free(index) alone as sufficient; preserve
the existing typed-array write handling.
- Around line 65-67: Update loop safepoint eligibility around body_may_allocate
and emit_gc_loop_safepoint to account for control expressions and statements,
not only the loop body: include for initializers and updates plus while/do-while
conditions when checking allocation, and pass or inspect that control state
before lowering. Preserve safepoints whenever any loop control component may
allocate.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d4987572-5194-4b23-b1e5-43cbfb7c83d0

📥 Commits

Reviewing files that changed from the base of the PR and between 1aa613f and 60fa3c7.

📒 Files selected for processing (1)
  • crates/perry-codegen/src/loop_purity.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/perry-codegen/src/stmt/loops.rs`:
- Around line 5142-5143: Move the safepoint emission in the loop-control flow so
it runs after the update and condition expressions execute, immediately before
re-entering the body; retain controls only for eligibility analysis. Apply the
same ordering in crates/perry-codegen/src/stmt/loops.rs at lines 5142-5143,
7048, and 7106: emit after condition evaluation and before branching to the body
or back to the body.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9ddcb5c7-755d-4dfc-918e-dcc090c9219d

📥 Commits

Reviewing files that changed from the base of the PR and between 60fa3c7 and 1891ace.

📒 Files selected for processing (2)
  • crates/perry-codegen/src/loop_purity.rs
  • crates/perry-codegen/src/stmt/loops.rs

Comment thread crates/perry-codegen/src/stmt/loops.rs Outdated
@proggeramlug
proggeramlug merged commit 093c516 into main Jul 30, 2026
6 checks passed
@proggeramlug
proggeramlug deleted the fix/sqlite-node26-parity branch July 30, 2026 06:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:bug Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[parity] node:sqlite — 13 failing node-suite tests (2026-07-22 baseline)

2 participants