Skip to content

Add jsc.DecodedJSValue; make jsc.Strong more efficient#23218

Merged
Jarred-Sumner merged 6 commits into
mainfrom
taylor.fish/decoded-js-value
Oct 4, 2025
Merged

Add jsc.DecodedJSValue; make jsc.Strong more efficient#23218
Jarred-Sumner merged 6 commits into
mainfrom
taylor.fish/decoded-js-value

Conversation

@taylordotfish

@taylordotfish taylordotfish commented Oct 3, 2025

Copy link
Copy Markdown
Contributor

Add jsc.DecodedJSValue, an extern struct which is ABI-compatible with JSC::JSValue. (By contrast, jsc.JSValue is ABI-compatible with JSC::EncodedJSValue.) This enables jsc.Strong.get to be more efficient: it no longer has to call into C⁠+⁠+.

(For internal tracking: fixes ENG-20748)

Add `jsc.DecodedJSValue`, an extern struct which is ABI-compatible with
`JSC::JSValue`. (By contrast, `jsc.JSValue` is ABI-compatible with
`JSC::EncodedJSValue`.) This enables `jsc.Strong.get` to be more
efficient: it no longer has to call into C++.
@linear

linear Bot commented Oct 3, 2025

Copy link
Copy Markdown

@robobun

robobun commented Oct 3, 2025

Copy link
Copy Markdown
Collaborator
Updated 7:29 PM PT - Oct 3rd, 2025

@taylordotfish, your commit cdfbade has 2 failures in Build #27921 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 23218

That installs a local version of the PR into your bun-23218 executable, so you can run:

bun-23218 --bun

@coderabbitai

coderabbitai Bot commented Oct 3, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Introduces a Zig-side DecodedJSValue ABI to replace EncodedJSValue usage, updates exports, adds JSValue.decode(), refactors StrongRef.get to inline decode/encode logic, and removes the C/C++ Bun__StrongRef__get function. ModuleLoader now derives JSValue via DecodedJSValue.encode(). No public runtime entry points added.

Changes

Cohort / File(s) Summary of changes
JSValue ABI transition
src/bun.js/bindings/DecodedJSValue.zig, src/bun.js/bindings/EncodedJSValue.zig, src/bun.js/bindings/JSValue.zig, src/bun.js/jsc.zig, src/bun.js/ModuleLoader.zig
Added DecodedJSValue extern and encode() method; removed EncodedJSValue type; added JSValue.decode(); updated jsc exports to add DecodedJSValue and remove EncodedJSValue; switched ModuleLoader to use DecodedJSValue.encode() instead of constructing from EncodedJSValue.
StrongRef get path change
src/bun.js/Strong.zig, src/bun.js/bindings/StrongRef.h, src/bun.js/bindings/StrongRef.cpp
Inlined Strong.get decoding/encoding in Zig; removed extern Bun__StrongRef__get declaration and C++ definition.

Possibly related PRs

Suggested reviewers

  • Jarred-Sumner
  • pfgithub
  • zackradisic

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The pull request description does not follow the repository template because it lacks the required "What does this PR do?" and "How did you verify your code works?" sections, and it omits any details on testing or validation. Please update the description to include the "What does this PR do?" section and add a "How did you verify your code works?" section with details of the validation steps or tests performed.
✅ Passed checks (4 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title concisely and accurately summarizes the primary changes by noting the addition of jsc.DecodedJSValue and the improvement of jsc.Strong performance, which reflects the main intent and scope of the diff.
Linked Issues Check ✅ Passed The changes introduce a Zig extern struct matching the ABI of JSC::JSValue, update jsc.Strong.get to use this struct to eliminate C++ interop calls, and remove the outdated EncodedJSValue paths, thereby fully satisfying the objectives of ENG-20748.
Out of Scope Changes Check ✅ Passed All modifications are focused on introducing DecodedJSValue and optimizing jsc.Strong.get according to the linked issue, and there are no unrelated or out-of-scope changes in this diff.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ 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 taylor.fish/decoded-js-value

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f7485d5 and cdfbade.

📒 Files selected for processing (5)
  • src/bun.js/Strong.zig (1 hunks)
  • src/bun.js/bindings/JSValue.zig (1 hunks)
  • src/bun.js/bindings/StrongRef.cpp (0 hunks)
  • src/bun.js/bindings/StrongRef.h (0 hunks)
  • src/bun.js/jsc.zig (1 hunks)
💤 Files with no reviewable changes (2)
  • src/bun.js/bindings/StrongRef.h
  • src/bun.js/bindings/StrongRef.cpp
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/bun.js/jsc.zig
  • src/bun.js/bindings/JSValue.zig
  • src/bun.js/Strong.zig
⏰ 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). (1)
  • GitHub Check: Format

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c8cb771 and c52eba2.

📒 Files selected for processing (7)
  • src/bun.js/ModuleLoader.zig (1 hunks)
  • src/bun.js/Strong.zig (1 hunks)
  • src/bun.js/bindings/DecodedJSValue.zig (1 hunks)
  • src/bun.js/bindings/EncodedJSValue.zig (0 hunks)
  • src/bun.js/bindings/JSValue.zig (1 hunks)
  • src/bun.js/bindings/Strong.cpp (0 hunks)
  • src/bun.js/jsc.zig (1 hunks)
💤 Files with no reviewable changes (2)
  • src/bun.js/bindings/Strong.cpp
  • src/bun.js/bindings/EncodedJSValue.zig
🧰 Additional context used
📓 Path-based instructions (3)
src/**/*.zig

📄 CodeRabbit inference engine (.cursor/rules/building-bun.mdc)

Implement debug logs in Zig using const log = bun.Output.scoped(.${SCOPE}, false); and invoking log("...", .{})

Files:

  • src/bun.js/bindings/DecodedJSValue.zig
  • src/bun.js/Strong.zig
  • src/bun.js/bindings/JSValue.zig
  • src/bun.js/jsc.zig
  • src/bun.js/ModuleLoader.zig
**/*.zig

📄 CodeRabbit inference engine (.cursor/rules/javascriptcore-class.mdc)

**/*.zig: Declare the extern C symbol in Zig and export a Zig-friendly alias for use
Wrap the Bun____toJS extern in a Zig method that takes a JSGlobalObject and returns JSC.JSValue

**/*.zig: Format Zig files with zig-format (bun run zig-format)
In Zig, manage memory carefully with allocators and use defer for cleanup

Files:

  • src/bun.js/bindings/DecodedJSValue.zig
  • src/bun.js/Strong.zig
  • src/bun.js/bindings/JSValue.zig
  • src/bun.js/jsc.zig
  • src/bun.js/ModuleLoader.zig
src/bun.js/**/*.zig

📄 CodeRabbit inference engine (.cursor/rules/zig-javascriptcore-classes.mdc)

src/bun.js/**/*.zig: In Zig binding structs, expose generated bindings via pub const js = JSC.Codegen.JS and re-export toJS/fromJS/fromJSDirect
Constructors and prototype methods should return bun.JSError!JSC.JSValue to integrate Zig error handling with JS exceptions
Use parameter name globalObject (not ctx) and accept (*JSC.JSGlobalObject, *JSC.CallFrame) in binding methods/constructors
Implement getters as get(this, globalObject) returning JSC.JSValue and matching the .classes.ts interface
Provide deinit() for resource cleanup and finalize() that calls deinit(); use bun.destroy(this) or appropriate destroy pattern
Access JS call data via CallFrame (argument(i), argumentCount(), thisValue()) and throw errors with globalObject.throw(...)
For properties marked cache: true, use the generated Zig accessors (NameSetCached/GetCached) to work with GC-owned values
In finalize() for objects holding JS references, release them using .deref() before destroy

Files:

  • src/bun.js/bindings/DecodedJSValue.zig
  • src/bun.js/Strong.zig
  • src/bun.js/bindings/JSValue.zig
  • src/bun.js/jsc.zig
  • src/bun.js/ModuleLoader.zig
🧠 Learnings (8)
📓 Common learnings
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/zig-javascriptcore-classes.mdc:0-0
Timestamp: 2025-08-30T00:13:36.815Z
Learning: Applies to src/bun.js/**/*.zig : In Zig binding structs, expose generated bindings via pub const js = JSC.Codegen.JS<ClassName> and re-export toJS/fromJS/fromJSDirect
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/registering-bun-modules.mdc:0-0
Timestamp: 2025-08-30T00:11:57.076Z
Learning: Applies to src/{**/js_*.zig,bun.js/api/**/*.zig} : Use bun.JSError!JSValue for proper error propagation in JS-exposed Zig functions
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/javascriptcore-class.mdc:0-0
Timestamp: 2025-08-30T00:11:00.890Z
Learning: Applies to **/*.zig : Wrap the Bun__<Type>__toJS extern in a Zig method that takes a JSGlobalObject and returns JSC.JSValue
📚 Learning: 2025-08-30T00:13:36.815Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/zig-javascriptcore-classes.mdc:0-0
Timestamp: 2025-08-30T00:13:36.815Z
Learning: Applies to src/bun.js/**/*.zig : In Zig binding structs, expose generated bindings via pub const js = JSC.Codegen.JS<ClassName> and re-export toJS/fromJS/fromJSDirect

Applied to files:

  • src/bun.js/bindings/DecodedJSValue.zig
  • src/bun.js/Strong.zig
  • src/bun.js/bindings/JSValue.zig
  • src/bun.js/jsc.zig
  • src/bun.js/ModuleLoader.zig
📚 Learning: 2025-08-30T00:11:57.076Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/registering-bun-modules.mdc:0-0
Timestamp: 2025-08-30T00:11:57.076Z
Learning: Applies to src/{**/js_*.zig,bun.js/api/**/*.zig} : Use bun.JSError!JSValue for proper error propagation in JS-exposed Zig functions

Applied to files:

  • src/bun.js/bindings/DecodedJSValue.zig
  • src/bun.js/bindings/JSValue.zig
  • src/bun.js/jsc.zig
📚 Learning: 2025-08-30T00:13:36.815Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/zig-javascriptcore-classes.mdc:0-0
Timestamp: 2025-08-30T00:13:36.815Z
Learning: Applies to src/bun.js/**/*.zig : Implement getters as get<PropertyName>(this, globalObject) returning JSC.JSValue and matching the .classes.ts interface

Applied to files:

  • src/bun.js/Strong.zig
📚 Learning: 2025-09-08T04:44:59.101Z
Learnt from: CR
PR: oven-sh/bun#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-08T04:44:59.101Z
Learning: Applies to src/bun.js/bindings/**/*.cpp : Cache structures in ZigGlobalObject for JSC-bound classes

Applied to files:

  • src/bun.js/Strong.zig
📚 Learning: 2025-08-30T00:11:00.890Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/javascriptcore-class.mdc:0-0
Timestamp: 2025-08-30T00:11:00.890Z
Learning: Applies to **/*.zig : Wrap the Bun__<Type>__toJS extern in a Zig method that takes a JSGlobalObject and returns JSC.JSValue

Applied to files:

  • src/bun.js/bindings/JSValue.zig
  • src/bun.js/jsc.zig
📚 Learning: 2025-08-30T00:13:36.815Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/zig-javascriptcore-classes.mdc:0-0
Timestamp: 2025-08-30T00:13:36.815Z
Learning: Applies to src/bun.js/bindings/generated_classes_list.zig : Update src/bun.js/bindings/generated_classes_list.zig to include new classes

Applied to files:

  • src/bun.js/jsc.zig
📚 Learning: 2025-08-30T00:11:57.076Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/registering-bun-modules.mdc:0-0
Timestamp: 2025-08-30T00:11:57.076Z
Learning: Applies to src/**/js_*.zig : Implement JavaScript bindings in a Zig file named with a js_ prefix (e.g., js_smtp.zig, js_your_feature.zig)

Applied to files:

  • src/bun.js/jsc.zig
⏰ 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). (1)
  • GitHub Check: Format

Comment thread src/bun.js/bindings/JSValue.zig
@Jarred-Sumner Jarred-Sumner merged commit d8350c2 into main Oct 4, 2025
58 of 60 checks passed
@Jarred-Sumner Jarred-Sumner deleted the taylor.fish/decoded-js-value branch October 4, 2025 05:05
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.

3 participants