bun:sqlite: fix lone-surrogate encoding, out-of-range BigInt binding, and stale column names - #32841
bun:sqlite: fix lone-surrogate encoding, out-of-range BigInt binding, and stale column names#32841robobun wants to merge 6 commits into
Conversation
|
Updated 9:43 PM PT - Jul 30th, 2026
✅ @robobun, your commit da34ac88449579fd2ef945da4483a043b65d1ead passed in 🧪 To try this PR locally: bunx bun-pr 32841That installs a local version of the PR into your bun-32841 --bun |
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
|
Found 1 issue this PR may fix:
🤖 Generated with Claude Code |
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThe PR updates SQLite BigInt and UTF-8 binding, lazy symbol loading, prepared-statement metadata refresh, documentation, and schema-change regression tests. ChangesSQLite runtime bindings and refresh
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@docs/runtime/sqlite.mdx`:
- Around line 489-492: The SQLite docs section has a duplicated paragraph about
integer return behavior and the second paragraph uses confusing “use the bigint
type” wording. Remove the redundant paragraph in the docs content near the
sqlite runtime section and keep a single paragraph that clearly says bigint is
supported for inputs while the Database option safeIntegers controls whether
results are returned as bigint instead of number.
In `@test/js/bun/sqlite/sqlite.test.js`:
- Around line 1926-1929: Shorten the multi-line SQLite surrogate warning comment
in the sqlite test so it fits within the 3-line limit without losing the UTF-16
hazard. Keep the note near the bind path logic in sqlite.test.js, and condense
the explanation that lone surrogates must become U+FFFD and must not be passed
raw to SQLite because its decoder can consume following code units or store
ill-formed runs.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: c3417b55-3ebd-4dc1-936c-d6afe8380e35
📒 Files selected for processing (5)
docs/runtime/sqlite.mdxsrc/jsc/bindings/sqlite/JSSQLStatement.cppsrc/jsc/bindings/sqlite/lazy_sqlite3.htest/js/bun/sqlite/sqlite.test.jstest/js/sql/sqlite-sql.test.ts
There was a problem hiding this comment.
I didn't find any bugs, but this touches hot-path native bindings and includes an intentional behavior change (BigInt range-check regardless of safeIntegers) that you've explicitly flagged for maintainer input, so a human should sign off.
Extended reasoning...
Overview
This PR fixes three binding-layer bugs in bun:sqlite by modifying src/jsc/bindings/sqlite/JSSQLStatement.cpp and lazy_sqlite3.h, with corresponding test and doc updates. The three fixes are: (1) replace sqlite3_bind_text16 with WTF-encoded UTF-8 + sqlite3_bind_text so lone surrogates become U+FFFD instead of corrupting stored text; (2) always range-check BigInt parameters and throw RangeError for values outside signed-int64, removing the isSafeInteger parameter from the rebindValue/rebindObject/rebindStatement chain; (3) call sqlite3_stmt_status(stmt, SQLITE_STMTSTATUS_REPREPARE, 1) after each sqlite3_step() to detect transparent re-prepares and refresh cached column names/Structure.
Security risks
None apparent. The changes tighten input validation (rejecting out-of-range BigInts) and improve encoding correctness (no more ill-formed UTF-8 written to disk). No auth, crypto, or permission surfaces are touched.
Level of scrutiny
This warrants human review. It modifies native C++ on the hot path of every parameterized query: every non-ASCII / non-Latin-1-ASCII string now allocates a UTF-8 CString instead of passing UTF-16 directly to SQLite, and every sqlite3_step() is now followed by a sqlite3_stmt_status call. Both look cheap and correct, but a maintainer familiar with the perf characteristics of this module should confirm. More importantly, fix #2 is a deliberate user-visible behavior change — code that previously bound 2n ** 64n silently now throws — and the PR description explicitly asks a maintainer to confirm the old wrapping wasn't intentional. That's a product decision a bot shouldn't make.
Other factors
The implementation is clean and well-tested (22 new/updated test cases covering boundary BigInts, surrogate variants across positional/named/exec paths, and four schema-change scenarios including a second connection). The refactor into updateColumnNamesIfNeeded preserves the existing exception-handling shape at each call site. The lazy_sqlite3.h additions follow the established pattern, and sqlite3_stmt_status has been in SQLite since 3.6.4 so the macOS system dylib will have it. No outstanding reviewer comments. CI is still building.
There was a problem hiding this comment.
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 `@docs/runtime/sqlite.mdx`:
- Line 489: The sqlite documentation text uses an imprecise safe-integer
boundary; update the wording in the `bun:sqlite` section to use the exact
JavaScript safe-integer limit via `Number.MAX_SAFE_INTEGER` or `2^53 - 1`
instead of `2^53`, keeping the `Database`/`safeIntegers` guidance otherwise the
same.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 600f6b4e-147b-4aa7-a528-ba46cc4a30ae
📒 Files selected for processing (3)
docs/runtime/sqlite.mdxsrc/jsc/bindings/sqlite/JSSQLStatement.cpptest/js/bun/sqlite/sqlite.test.js
|
Re the "Out of Scope Changes" warning in CodeRabbit's pre-merge checks: the three fixes were reported together, live in the same two source files, and share one test suite, so they were scoped together from the start. The |
There was a problem hiding this comment.
I didn't find any further issues (thanks for addressing the columnTypes count), but this bundles three behavior changes in core bun:sqlite binding C++ — including the BigInt range-check change you flagged as a maintainer call — so a human should sign off.
Extended reasoning...
Overview
This PR changes src/jsc/bindings/sqlite/JSSQLStatement.cpp (the core bun:sqlite parameter-binding and result-shaping path), lazy_sqlite3.h (adds sqlite3_stmt_status to the macOS dlsym table, removes sqlite3_bind_text16), the safeIntegers docs, and two test files. It fixes three distinct bugs: (1) string parameters now always go through StringView::utf8() → sqlite3_bind_text instead of sqlite3_bind_text16, so lone surrogates become U+FFFD rather than ill-formed UTF-8; (2) out-of-range BigInt parameters now throw RangeError regardless of safeIntegers, instead of silently wrapping mod 2^64; (3) cached column names / result Structures are rebuilt after SQLite transparently re-prepares a statement, detected via sqlite3_stmt_status(SQLITE_STMTSTATUS_REPREPARE) after each sqlite3_step(). A follow-up commit (b1fbe53) moved the sqlite3_column_count read in columnTypes to after the step per my earlier comment.
Security risks
None apparent. Inputs are JS values bound to SQLite statements; the changes tighten encoding correctness and add a range check. No auth, crypto, permissions, filesystem, or network surface is touched. The new dlsym for sqlite3_stmt_status follows the existing pattern for other symbols.
Level of scrutiny
High. rebindValue and the six sqlite3_step() call sites are the hot path for every bun:sqlite query. Two of the three fixes are observable behavior changes: non-ASCII 16-bit strings now take a UTF-8 transcode on bind (correctness over the old zero-copy UTF-16 path), and the BigInt change converts a silent wrap into a thrown RangeError — the author explicitly asked whether the previous wrapping was intentional. The reprepare detection adds a sqlite3_stmt_status(..., 1) call after every step and folds six copies of the cache-refresh check into one helper; the refactor looks faithful but is non-mechanical.
Other factors
The PR is well-tested (24 new/updated cases in sqlite.test.js, including cross-process and second-connection schema changes) and well-documented. CodeRabbit's two minor nits and my columnTypes finding are all resolved. CI for commit 3adfc2e was marked failing in the buildkite comment, which a maintainer should also glance at. Given the scope, the explicit "if this was intentional, say so" on the BigInt change, and the perf-vs-correctness tradeoff on the text16 path, this is a maintainer-level decision rather than a rubber-stamp.
|
CI status for b1fbe53 (build #65440):
The diff is green on every lane that actually ran. Ready for review; the BigInt range-check change (silent wrap → |
b1fbe53 to
b2b7b5f
Compare
There was a problem hiding this comment.
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 `@docs/runtime/sqlite.mdx`:
- Around line 487-489: The SQLite integer range description in the runtime docs
is inaccurate; update the wording in the Database/safeIntegers section to use
JavaScript’s safe-integer bound instead of “52-bit.” Replace the claim about
“signed 52-bit integers” with `Number.MAX_SAFE_INTEGER` (`2^53 - 1`) and keep
the guidance that `bigint` should be used for larger values when referencing
`bun:sqlite` integer handling.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: b0898341-4197-4aef-bb91-4c2090a9f093
📒 Files selected for processing (1)
docs/runtime/sqlite.mdx
There was a problem hiding this comment.
No further issues after the columnTypes fix — deferring to a maintainer for the flagged BigInt wrap→RangeError behavior change and the native-bindings scope.
Extended reasoning...
Overview
This PR fixes three distinct bun:sqlite binding-layer bugs in src/jsc/bindings/sqlite/JSSQLStatement.cpp and lazy_sqlite3.h: (1) lone-surrogate strings now encode to well-formed UTF-8 via WTF::StringView::utf8() instead of being handed to sqlite3_bind_text16; (2) out-of-range BigInt parameters now always throw RangeError rather than silently wrapping modulo 2⁶⁴ when safeIntegers is off; (3) cached column names/result Structure are rebuilt after SQLite transparently re-prepares a statement, detected via sqlite3_stmt_status(SQLITE_STMTSTATUS_REPREPARE). It also moves the columnTypes column-count read to after sqlite3_step() (addressing my earlier inline comment), updates docs, and adds extensive tests.
Security risks
None identified. The changes tighten behavior (reject bad input, sanitize ill-formed text) rather than loosen it. No auth, crypto, filesystem, or permission surfaces are touched. The new sqlite3_stmt_status dlsym entry mirrors the existing pattern for other lazily-loaded symbols.
Level of scrutiny
This warrants human review. It modifies hot-path native C++ in a widely-used built-in module across six sqlite3_step() call sites, removes the safeIntegers parameter from the rebindValue/rebindObject/rebindStatement chain, and changes how all non-ASCII/16-bit strings are bound (always re-encoding to UTF-8 rather than passing UTF-16 through). Most importantly, fix (2) is an intentional breaking behavior change that the author has explicitly flagged for a maintainer decision ("If the silent wrapping was intentional, say so and I will revert this part").
Other factors
The bug-hunting pass found no issues. All prior review threads (CodeRabbit nits, my columnTypes note) are resolved, CI is green on every lane that ran, and test coverage for the new behavior is thorough (boundary BigInts, surrogate cases across positional/named/exec paths, same-process/cross-connection/cross-process schema changes, columnTypes grow/shrink). The implementation looks correct to me, but the combination of a flagged behavior-change decision and ~100 lines of native-bindings refactor puts this outside what I'll approve without a human sign-off.
|
CI status for The 4 red jobs are all unrelated to this change:
I am not pushing a |
|
@robobun benchmark the before/after this PR when loading a large table. Release build. Update PR body |
|
@Jarred-Sumner done, added a Performance section to the PR body with the table, methodology, and the benchmark script. Headline: loading a large table is unchanged within noise.
Release build ( Why the read path is flat: the new Why the 16-bit bind path is flat: Separately, this branch is stale against |
… and stale column names Strings containing a lone surrogate were bound with sqlite3_bind_text16, letting SQLite's UTF-16 decoder pair a lone high surrogate with whatever code unit follows (consuming it) and store trailing ones as ill-formed 3-byte sequences. Always convert to UTF-8 with StringView::utf8(), which replaces lone surrogates with U+FFFD like TextEncoder, and bind with sqlite3_bind_text. sqlite3_bind_text16 is no longer used, so its entry is removed from lazy_sqlite3.h. BigInt parameters were only range-checked when safeIntegers was enabled; the default mode called JSBigInt::toBigInt64, which truncates to 64 bits. Always range-check and throw the same RangeError. The now-unused safeIntegers parameter is removed from the rebind chain. A prepared statement's cached column names only refreshed when a per-connection version counter changed, and the db.run()/exec() path never bumps it, so ALTER/DROP+CREATE issued that way returned values under stale (or wrong) column names. Detect the re-prepare directly via sqlite3_stmt_status(SQLITE_STMTSTATUS_REPREPARE) after each sqlite3_step and fold the six copies of the refresh check into one helper.
Issue 1332's repro is an ALTER TABLE issued by a separate process while the statement's connection has WAL enabled, which the version counter could never observe. The re-prepare detection handles it; add a test covering that exact scenario. Also collapse a duplicated paragraph in the integers doc section and shorten a test comment to three lines.
sqlite3_step() transparently re-prepares an expired statement, which can change the result shape. The columnTypes getter captured the column count before the step, so after a schema change the returned array was truncated (more columns) or padded with spurious "NULL" entries read from out-of-range column indexes (fewer columns).
b2b7b5f to
4b3c09f
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/jsc/bindings/sqlite/JSSQLStatement.cpp (2)
2180-2181: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winReset
stmtbefore returning from metadata initialization failures.
initializeColumnNamescan leavecolumnNamesandvalidColumnspartially rebuilt. These three paths return with an active SQLite statement. Initerate, the next call can skip reset and use partial metadata. Resetstmtbefore eachRETURN_IF_EXCEPTIONat lines 2180-2181, 2230-2231, and 2321-2322.🤖 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 `@src/jsc/bindings/sqlite/JSSQLStatement.cpp` around lines 2180 - 2181, In src/jsc/bindings/sqlite/JSSQLStatement.cpp at lines 2180-2181, 2230-2231, and 2321-2322, update each initializeColumnNames metadata-failure path to reset stmt before RETURN_IF_EXCEPTION executes. Ensure all three sites leave the SQLite statement reset when metadata rebuilding throws, preventing iterate from reusing partial metadata.Source: Coding guidelines
855-861: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy liftMake metadata refresh transactional.
initializeColumnNamescommitshasExecutedandversionbefore allocation-capable work completes. If construction raises, it can leave_structure,_prototype,columnNames, orvalidColumnsincomplete.updateColumnNamesIfNeededalso clearsSQLITE_STMTSTATUS_REPREPAREbefore initialization succeeds. The next call can skip refresh and use invalid metadata.Build metadata in temporary state and commit it only after success, or restore the previous cache state on failure.
🤖 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 `@src/jsc/bindings/sqlite/JSSQLStatement.cpp` around lines 855 - 861, Make metadata refresh in initializeColumnNames and updateColumnNamesIfNeeded transactional: stage all allocation-capable metadata changes and hasExecuted/version updates in temporary state, then commit only after successful completion; on failure, preserve the prior _structure, _prototype, columnNames, validColumns, and execution state. Ensure SQLITE_STMTSTATUS_REPREPARE is not consumed permanently until initialization succeeds, so a failed refresh is retried on the next call.Sources: Coding guidelines, MCP tools
🤖 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 `@src/jsc/bindings/sqlite/JSSQLStatement.cpp`:
- Around line 918-919: Update both string-binding branches in the relevant
JSSQLStatement binding logic to use sqlite3_bind_text64 with the UTF-8 encoding
flag and SQLITE_TRANSIENT, passing the full utf8 length without narrowing.
Ensure the existing CHECK_BIND handling is preserved and no branch continues
using the 32-bit sqlite3_bind_text API.
---
Outside diff comments:
In `@src/jsc/bindings/sqlite/JSSQLStatement.cpp`:
- Around line 2180-2181: In src/jsc/bindings/sqlite/JSSQLStatement.cpp at lines
2180-2181, 2230-2231, and 2321-2322, update each initializeColumnNames
metadata-failure path to reset stmt before RETURN_IF_EXCEPTION executes. Ensure
all three sites leave the SQLite statement reset when metadata rebuilding
throws, preventing iterate from reusing partial metadata.
- Around line 855-861: Make metadata refresh in initializeColumnNames and
updateColumnNamesIfNeeded transactional: stage all allocation-capable metadata
changes and hasExecuted/version updates in temporary state, then commit only
after successful completion; on failure, preserve the prior _structure,
_prototype, columnNames, validColumns, and execution state. Ensure
SQLITE_STMTSTATUS_REPREPARE is not consumed permanently until initialization
succeeds, so a failed refresh is retried on the next call.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: fc2d3b8d-4310-4d67-9819-663dddaa6918
📒 Files selected for processing (1)
src/jsc/bindings/sqlite/JSSQLStatement.cpp
|
Post-rebase review sweep on 31e6a6a:
|
Three binding-layer bugs in
bun:sqlitewhere it diverges fromnode:sqliteandbetter-sqlite3running the same SQLite. The first two silently corrupt data.1. Lone surrogates are stored as ill-formed UTF-8 and can consume the following character
rebindValuebound 16-bit strings withsqlite3_bind_text16, so SQLite's own UTF-16 decoder performed the conversion. That decoder pairs a lone high surrogate with whatever code unit follows (here"b", producing U+10062 and consuming theb), and writes a trailing lone surrogate as the ill-formed 3-byte sequenceED A0 80. The database file then contains text that is not valid UTF-8, so other tools reading the file see corruption, and the stored text differs from the JS string in content as well as encoding.Fix: always encode to UTF-8 with
WTF::StringView::utf8(), which replaces lone surrogates with U+FFFD exactly likeTextEncoderand every other string-to-bytes path in Bun, and bind withsqlite3_bind_text.sqlite3_bind_text16is no longer used, so its entry is removed fromlazy_sqlite3.h.This also fixes a second artifact of
bind_text16: a string beginning with U+FEFF or U+FFFE used to have its first two bytes stripped by SQLite's UTF-16 BOM sniffer, so a bound"\uFFFE"came back as"". The test intest/js/sql/sqlite-sql.test.tsthat documented both old behaviors is updated.2. Out-of-range BigInt parameters are silently wrapped modulo 2^64
rebindValueonly performed the int64 range check whensafeIntegerswas enabled; the default mode calledJSBigInt::toBigInt64, which truncates to 64 bits.node:sqliteandbetter-sqlite3both throw aRangeErrorregardless of mode. better-sqlite3'ssafeIntegers, which Bun's option is modeled on, only controls how integers are returned, never whether BigInt input is validated. Silently storing5for2n ** 64n + 5nis the classic truncation bug for snowflake and other u64 identifiers.Fix: always range-check the BigInt and throw the same
RangeErrorthesafeIntegerspath already threw. The now-unusedsafeIntegers/isSafeIntegerparameter is removed from therebindValue/rebindObject/rebindStatementchain.This is a behavior change. The previous behavior was covered by an
expect(...).not.toThrow(RangeError)assertion and a sentence indocs/runtime/sqlite.mdx; both are updated here. If the silent wrapping was intentional, say so and I will revert this part.3. A prepared statement's cached column names never refresh after SQLite re-prepares it
Fixes #1332
After
DROP TABLE t; CREATE TABLE t (zzz TEXT),q.get()returns the new column's value under the old column's name, so any app that runs DDL at runtime can silently get mis-keyed rows.initializeColumnNamesis gated on a per-connection version counter that only increments when a non-read-only prepared statement steps. The multi-statement exec path used bydb.run()/db.exec()never touches it, and schema changes made through another connection to the same file cannot touch it at all. Meanwhile SQLite transparently re-prepares the expired statement insidesqlite3_step(), so the live result shape and the cached column names andStructurediverge.Fix: detect the re-prepare directly with
sqlite3_stmt_status(stmt, SQLITE_STMTSTATUS_REPREPARE, 1)right after eachsqlite3_step(). That works for any source of the schema change, including #1332's case of anALTER TABLEissued by a separate process against a WAL database, which a per-connection counter can never observe. The six copies of the!hasExecuted || need_update()check are folded into oneupdateColumnNamesIfNeededhelper.sqlite3_stmt_statusis added tolazy_sqlite3.hfor the macOS dynamic-load path.The
columnTypesgetter is a seventhsqlite3_step()site with the same class of bug: it capturedsqlite3_column_countbefore the step, so after a schema change the returned array was truncated (more columns) or padded with spurious"NULL"entries read from out-of-range column indexes (fewer columns). The count is now read after the step.Not included
new Database(path, {})(and{ readonly: false }) failing withSQLITE_MISUSEbecause an options object zeroes the open flags was reported alongside these, but it already has an open PR, #32422, so it is not duplicated here.Performance
Release build (
--profile=release,bun-profile), mitata, Xeon Platinum 8375C. Both binaries built from the same tree (ffea69ae7cbase); the only difference is this PR's twosrc/jsc/bindings/sqlite/files. 3 interleaved rounds; mean of the per-runavgtime.SELECT * FROM t .all()(200,000 rows × 5 cols)SELECT * FROM t .values()(200,000 rows × 5 cols)SELECT * FROM s .all()(100 rows × 3 cols)bind_text16→utf8()pathLoading a large table via
.all()/.values()is unchanged within noise. mitata's per-run min–max spread on the 200K-row.all()was 90–106 ms (±8%), so the +1.2% delta is well inside it. Structurally the newsqlite3_stmt_status(…, SQLITE_STMTSTATUS_REPREPARE, 1)call runs once per.all()/.values()invocation, not per row, so there is no added per-row work in the step loop.The 16-bit string bind shows +1.6% against a +0.6% on the unchanged ASCII control; the residual ~1% is one extra temporary:
WTF::StringView::utf8()allocates aCString, andSQLITE_TRANSIENTthen copies it again, whereassqlite3_bind_text16transcoded UTF-16→UTF-8 in place inside SQLite. BigInt binding is inside the noise band of the unchanged control.Benchmark script
Rebase note
Rebased onto
mainafter thenode:sqliteimplementation (#32498), #34925 (which rewrotejsSqlStatementGetColumnNamesto read column names live from SQLite instead of the cached array, dropping the seventhinitializeColumnNamescall site), and the docs editorial pass in #33112. The only conflict waslazy_sqlite3.h: thenode:sqlitePR restructured it (static -> inline variables so both TUs share onedlopen) and already providessqlite3_stmt_statuswith a fallback stub, so this PR's header diff is now just removing the four now-unusedsqlite3_bind_text16entries.JSSQLStatement.cpp, the tests, and the docs auto-merged cleanly.Verification
All three reproduce on
bun v1.4.0and on currentmain. Intest/js/bun/sqlite/sqlite.test.js, 24 of the new or updated test cases fail onv1.4.0and all 113 pass with this change.test/js/sql/sqlite-sql.test.ts,test/js/bun/sqlite/column-types.test.js,test/js/bun/sqlite/sql-timezone.test.js,test/js/sql/sqlite-url-parsing.test.ts, andtest/regression/issue/14709.test.tsalso pass. Two pre-existing debug-build timeouts insqlite-sql.test.tsreproduce identically on a debug build ofmainwithout this change.no test proof · iteration 7 · Platform-specific test(s) that do not run on this machine. Deferring to CI, which covers all platforms: test/js/bun/sqlite/sqlite.test.js