Skip to content

Add ExternalShared and RawRefCount#23013

Merged
Jarred-Sumner merged 4 commits into
mainfrom
taylor.fish/external-shared
Sep 26, 2025
Merged

Add ExternalShared and RawRefCount#23013
Jarred-Sumner merged 4 commits into
mainfrom
taylor.fish/external-shared

Conversation

@taylordotfish

@taylordotfish taylordotfish commented Sep 26, 2025

Copy link
Copy Markdown
Contributor

Add bun.ptr.ExternalShared, a shared pointer whose reference count is managed externally; e.g., by extern functions. This can be used to work with RefCounted C++ objects in Zig. For example:

// C++:
struct MyType : RefCounted<MyType> { ... };
extern "C" void MyType__ref(MyType* self) { self->ref(); }
extern "C" void MyType__ref(MyType* self) { self->deref(); }
// Zig:
const MyType = opaque {
    extern fn MyType__ref(self: *MyType) void;
    extern fn MyType__deref(self: *MyType) void;

    pub const Ref = bun.ptr.ExternalShared(MyType);

    // This enables `ExternalShared` to work.
    pub const external_shared_descriptor = struct {
        pub const ref = MyType__ref;
        pub const deref = MyType__deref;
    };
};

// Now `MyType.Ref` behaves just like `Ref<MyType>` in C++:
var some_ref: MyType.Ref = someFunctionReturningMyTypeRef();
const ptr: *MyType = some_ref.get(); // gets the inner pointer
var some_other_ref = some_ref.clone(); // increments the ref count
some_ref.deinit(); // decrements the ref count
// decrements the ref count again; if no other refs exist, the object
// is destroyed
some_other_ref.deinit();

This commit also adds RawRefCount, a simple wrapper around an integer reference count that can be used to implement the interface required by ExternalShared. Generally, for reference-counted Zig types, bun.ptr.Shared is preferred, but occasionally it is useful to have an “intrusive” reference-counted type where the ref count is stored in the type itself. For this purpose, ExternalShared + RawRefCount is more flexible and less error-prone than the deprecated bun.ptr.RefCounted type.

(For internal tracking: fixes STAB-1287, STAB-1288)

Add `bun.ptr.ExternalShared`, a shared pointer whose reference count is
managed externally; e.g., by extern functions. This can be used to work
with `RefCounted` C++ objects in Zig. For example:

```cpp
// C++:
struct MyType : RefCounted<MyType> { ... };
extern "C" void MyType__ref(MyType* self) { self->ref(); }
extern "C" void MyType__ref(MyType* self) { self->deref(); }
```

```zig
// Zig:
const MyType = opaque {
    extern fn MyType__ref(self: *MyType) void;
    extern fn MyType__deref(self: *MyType) void;

    pub const Ref = bun.ptr.ExternalShared(MyType);

    // This enables `ExternalShared` to work.
    pub const external_shared_descriptor = struct {
        pub const ref = MyType__ref;
        pub const deref = MyType__deref;
    };
};

// Now `MyType.Ref` behaves just like `Ref<MyType>` in C++:
var some_ref: MyType.Ref = someFunctionReturningMyTypeRef();
const ptr: *MyType = some_ref.get(); // gets the inner pointer
var some_other_ref = some_ref.clone(); // increments the ref count
some_ref.deinit(); // decrements the ref count
// decrements the ref count again; if no other refs exist, the object
// is destroyed
some_other_ref.deinit();
```

This commit also adds `RawRefCount`, a simple wrapper around an integer
reference count that can be used to implement the interface required by
`ExternalShared`. Generally, for reference-counted Zig types,
`bun.ptr.Shared` is preferred, but occasionally it is useful to have an
“intrusive” reference-counted type where the ref count is stored in the
type itself. For this purpose, `ExternalShared` + `RawRefCount` is more
flexible and less error-prone than the deprecated `bun.ptr.RefCounted`
type.
@robobun

robobun commented Sep 26, 2025

Copy link
Copy Markdown
Collaborator
Updated 2:30 PM PT - Sep 26th, 2025

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


🧪   To try this PR locally:

bunx bun-pr 23013

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

bun-23013 --bun

@coderabbitai

coderabbitai Bot commented Sep 26, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Added a new ExternalShared smart pointer type with a nullable Optional variant, a RawRefCount generic thread-aware reference-count helper, re-exported both from src/ptr.zig, and integrated ExternalShared semantics into WTFString via an external_shared_descriptor and WTFString alias.

Changes

Cohort / File(s) Summary
Pointer API surface
src/ptr.zig
Re-exported ExternalShared from ptr/external_shared.zig; added public raw_ref_count import and re-exported RawRefCount.
External shared pointer type
src/ptr/external_shared.zig
Added ExternalShared(comptime T: type) requiring T.external_shared_descriptor. Provides adopt, deinit, get, clone, cloneFromRaw, leak, intoOptional, and a nested Optional with initNull, adopt, deinit, get, take, clone, cloneFromRaw, leak.
Raw ref count module
src/ptr/raw_ref_count.zig
Introduced ThreadSafety and DecrementResult enums and RawRefCount(comptime Int: type, comptime thread_safety: ThreadSafety) factory producing a struct with conditional raw_value (atomic or plain), conditional thread lock, init, increment, decrement, and public deinit marker.
WTFString integration
src/string/WTFStringImpl.zig
Added public external_shared_descriptor on WTFStringImplStruct (provides ref/deref) and exported WTFString as bun.ptr.ExternalShared(WTFStringImplStruct).

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning The pull request includes modifications to src/string/WTFStringImpl.zig by adding an external_shared_descriptor and a new WTFString alias, which are not mentioned in the objectives from the linked issues. These changes extend beyond adding the core ExternalShared and RawRefCount types and appear unrelated to the issues’ scope. Including this unrelated update may distract from the primary enhancements and complicate the review. Please remove the changes to src/string/WTFStringImpl.zig or move them into a separate PR with a clear description and appropriate issue reference, and if these edits are intended to demonstrate usage, explicitly document and link the relevant issue in the PR description.
Description Check ⚠️ Warning The pull request description thoroughly explains the new functionality and provides illustrative examples, but it does not follow the repository template headings. Specifically, it is missing the required sections "### What does this PR do?" and "### How did you verify your code works?", which are mandated by the description template. As a result, the description does not comply with the repository’s guidelines. Please restructure the PR description to include the "### What does this PR do?" and "### How did you verify your code works?" sections from the provided template, and populate each with appropriate details about the changes and the verification steps performed.
✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title succinctly highlights the primary additions of ExternalShared and RawRefCount, matching the core changes in the diff without extra noise. It clearly conveys the main features being introduced and gives reviewers immediate context. This aligns well with the guideline for concise and specific titles.
Linked Issues Check ✅ Passed The code implements the ExternalShared smart pointer with descriptor-based ref and deref operations as specified in STAB-1287, and introduces the RawRefCount helper with configurable integer types and both single-threaded and thread-safe variants as required by STAB-1288. All primary objectives from both linked issues are met by the new modules and their public APIs. Therefore, the changes satisfy the functional requirements outlined in the linked issues.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch taylor.fish/external-shared

📜 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 bb03268 and d965c2e.

📒 Files selected for processing (1)
  • src/ptr/external_shared.zig (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
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/ptr/external_shared.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/ptr/external_shared.zig
🧠 Learnings (1)
📓 Common learnings
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 : Handle reference counting correctly with ref()/deref() in JS-facing Zig code
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 : Declare the extern C symbol in Zig and export a Zig-friendly alias for use
🔇 Additional comments (1)
src/ptr/external_shared.zig (1)

15-19: Fix invalid #impl identifier

Every use of #impl here (field declaration, initializers, dereferences) is illegal Zig syntax—the language doesn’t permit identifiers beginning with # unless they’re quoted (e.g. @"#impl"). As written, this file won’t even parse, so nothing else in the PR can build. Please rename the backing field (and the Optional variant) to something like raw and update all accesses accordingly.

-        #impl: *T,
+        raw: *T,
@@
-            return .{ .#impl = incremented_raw };
+            return .{ .raw = incremented_raw };
@@
-            T.external_shared_descriptor.deref(self.#impl);
+            T.external_shared_descriptor.deref(self.raw);
@@
-            return self.#impl;
+            return self.raw;
@@
-            T.external_shared_descriptor.ref(self.#impl);
+            T.external_shared_descriptor.ref(self.raw);
@@
-            return .{ .#impl = raw };
+            return .{ .raw = raw };
@@
-            return self.#impl;
+            return self.raw;
@@
-        pub const Optional = struct {
-            #impl: ?*T = null,
+        pub const Optional = struct {
+            raw: ?*T = null,
@@
-                return .{ .#impl = incremented_raw };
+                return .{ .raw = incremented_raw };
@@
-                if (self.#impl) |impl| {
+                if (self.raw) |impl| {
@@
-                return self.#impl;
+                return self.raw;
@@
-                const result: NonOptional = .{ .#impl = self.#impl orelse return null };
-                self.#impl = null;
+                const result: NonOptional = .{ .raw = self.raw orelse return null };
+                self.raw = null;
@@
-                if (self.#impl) |impl| {
+                if (self.raw) |impl| {
@@
-                if (raw) |some_raw| {
+                if (raw) |some_raw| {
@@
-                return .{ .#impl = raw };
+                return .{ .raw = raw };
@@
-                return self.#impl;
+                return self.raw;
@@
-            return .{ .#impl = self.#impl };
+            return .{ .raw = self.raw };

Also applies to: 54-96

⛔ Skipped due to learnings
Learnt from: taylordotfish
PR: oven-sh/bun#22227
File: src/allocators/allocation_scope.zig:284-314
Timestamp: 2025-09-02T18:25:27.976Z
Learning: In bun's custom Zig implementation, the `#` prefix for private fields is valid syntax and should not be flagged as invalid. The syntax `#fieldname` creates private fields that cannot be accessed from outside the defining struct, and usage like `self.#fieldname` is correct within the same struct. This applies to fields like `#parent`, `#state`, `#allocator`, `#trace`, etc. throughout the codebase.
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 : Declare the extern C symbol in Zig and export a Zig-friendly alias for use
Learnt from: taylordotfish
PR: oven-sh/bun#22227
File: src/safety/alloc.zig:93-95
Timestamp: 2025-09-02T17:14:46.924Z
Learning: In bun's Zig codebase, they use a custom extension of Zig that supports private field syntax with the `#` prefix (e.g., `#allocator`, `#trace`). This is not standard Zig syntax but is valid in their custom implementation. Fields prefixed with `#` are private fields that cannot be accessed from outside the defining struct.
Learnt from: cirospaciari
PR: oven-sh/bun#22842
File: src/bun.js/webcore/ResumableSink.zig:274-276
Timestamp: 2025-09-25T18:14:27.722Z
Learning: In Zig code, private fields are declared and accessed using the `#` prefix. When a field is declared as `#field_name`, it must be accessed as `this.#field_name`, not `this.field_name`. The `#` prefix is part of the private field access syntax and should not be removed.
Learnt from: taylordotfish
PR: oven-sh/bun#22227
File: src/collections/multi_array_list.zig:24-24
Timestamp: 2025-09-02T18:27:23.279Z
Learning: The `#allocator` syntax in bun's custom Zig implementation is valid and does not require quoting with @"#allocator". Private fields using the `#` prefix work correctly throughout the codebase without special quoting syntax.

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 a329da9 and 149e6a3.

📒 Files selected for processing (4)
  • src/ptr.zig (2 hunks)
  • src/ptr/external_shared.zig (1 hunks)
  • src/ptr/raw_ref_count.zig (1 hunks)
  • src/string/WTFStringImpl.zig (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
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/string/WTFStringImpl.zig
  • src/ptr.zig
  • src/ptr/raw_ref_count.zig
  • src/ptr/external_shared.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/string/WTFStringImpl.zig
  • src/ptr.zig
  • src/ptr/raw_ref_count.zig
  • src/ptr/external_shared.zig
🧠 Learnings (4)
📓 Common learnings
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 : Handle reference counting correctly with ref()/deref() in JS-facing Zig code
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 : Declare the extern C symbol in Zig and export a Zig-friendly alias for use
📚 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 : Declare the extern C symbol in Zig and export a Zig-friendly alias for use

Applied to files:

  • src/string/WTFStringImpl.zig
  • src/ptr.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 : Handle reference counting correctly with ref()/deref() in JS-facing Zig code

Applied to files:

  • src/ptr.zig
  • src/ptr/raw_ref_count.zig
📚 Learning: 2025-09-02T17:14:01.470Z
Learnt from: taylordotfish
PR: oven-sh/bun#22227
File: src/ptr/shared.zig:470-470
Timestamp: 2025-09-02T17:14:01.470Z
Learning: In Zig, regular arithmetic operations (like +=) have built-in overflow detection in debug/safe builds and will panic automatically. Atomic operations (like fetchAdd) do not have this automatic safety checking, so explicit overflow checks must be added manually. This is why NonAtomicCount doesn't need explicit overflow checks while AtomicCount does.

Applied to files:

  • src/ptr/raw_ref_count.zig
🔇 Additional comments (5)
src/ptr/external_shared.zig (1)

15-109: Rename #impl fields to valid Zig identifiers

Zig identifiers cannot start with #, so both the main struct and the optional wrapper fail to compile as written. Please rename these fields and update their usages accordingly.

-        #impl: *T,
+        ptr: *T,
@@
-            return .{ .#impl = incremented_raw };
+            return .{ .ptr = incremented_raw };
@@
-            T.external_shared_descriptor.deref(self.#impl);
+            T.external_shared_descriptor.deref(self.ptr);
@@
-            return self.#impl;
+            return self.ptr;
@@
-            T.external_shared_descriptor.ref(self.#impl);
+            T.external_shared_descriptor.ref(self.ptr);
@@
-            return .{ .#impl = raw };
+            return .{ .ptr = raw };
@@
-            defer self.* = undefined;
-            return self.#impl;
+            defer self.* = undefined;
+            return self.ptr;
@@
-        pub const Optional = struct {
-            #impl: ?*T = null,
+        pub const Optional = struct {
+            ptr: ?*T = null,
@@
-                return .{ .#impl = incremented_raw };
+                return .{ .ptr = incremented_raw };
@@
-                if (self.#impl) |impl| {
+                if (self.ptr) |impl| {
@@
-                return self.#impl;
+                return self.ptr;
@@
-                const result: NonOptional = .{ .#impl = self.#impl orelse return null };
-                self.#impl = null;
+                const result: NonOptional = .{ .ptr = self.ptr orelse return null };
+                self.ptr = null;
@@
-                if (self.#impl) |impl| {
+                if (self.ptr) |impl| {
@@
-                return .{ .#impl = raw };
+                return .{ .ptr = raw };
@@
-                defer self.* = undefined;
-                return self.#impl;
+                defer self.* = undefined;
+                return self.ptr;
@@
-            return .{ .#impl = self.#impl };
+            return .{ .ptr = self.ptr };
⛔ Skipped due to learnings
Learnt from: taylordotfish
PR: oven-sh/bun#22227
File: src/allocators/allocation_scope.zig:284-314
Timestamp: 2025-09-02T18:25:27.976Z
Learning: In bun's custom Zig implementation, the `#` prefix for private fields is valid syntax and should not be flagged as invalid. The syntax `#fieldname` creates private fields that cannot be accessed from outside the defining struct, and usage like `self.#fieldname` is correct within the same struct. This applies to fields like `#parent`, `#state`, `#allocator`, `#trace`, etc. throughout the codebase.
Learnt from: taylordotfish
PR: oven-sh/bun#22227
File: src/safety/alloc.zig:93-95
Timestamp: 2025-09-02T17:14:46.924Z
Learning: In bun's Zig codebase, they use a custom extension of Zig that supports private field syntax with the `#` prefix (e.g., `#allocator`, `#trace`). This is not standard Zig syntax but is valid in their custom implementation. Fields prefixed with `#` are private fields that cannot be accessed from outside the defining struct.
Learnt from: cirospaciari
PR: oven-sh/bun#22842
File: src/bun.js/webcore/ResumableSink.zig:274-276
Timestamp: 2025-09-25T18:14:27.722Z
Learning: In Zig code, private fields are declared and accessed using the `#` prefix. When a field is declared as `#field_name`, it must be accessed as `this.#field_name`, not `this.field_name`. The `#` prefix is part of the private field access syntax and should not be removed.
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 : Declare the extern C symbol in Zig and export a Zig-friendly alias for use
Learnt from: taylordotfish
PR: oven-sh/bun#22227
File: src/collections/multi_array_list.zig:24-24
Timestamp: 2025-09-02T18:27:23.279Z
Learning: The `#allocator` syntax in bun's custom Zig implementation is valid and does not require quoting with @"#allocator". Private fields using the `#` prefix work correctly throughout the codebase without special quoting syntax.
src/ptr/raw_ref_count.zig (1)

19-53: Use valid identifier names instead of #thread_lock

Identifiers starting with # are illegal in Zig, so this field (and all references to it) prevent the module from compiling. Rename the field to a standard identifier and update the call sites.

-        #thread_lock: if (thread_safety == .single_threaded) bun.safety.ThreadLock else void,
+        thread_lock: if (thread_safety == .single_threaded) bun.safety.ThreadLock else void,
@@
-                .#thread_lock = switch (comptime thread_safety) {
+                .thread_lock = switch (comptime thread_safety) {
@@
-                    self.#thread_lock.lockOrAssert();
+                    self.thread_lock.lockOrAssert();
@@
-                    self.#thread_lock.lockOrAssert();
+                    self.thread_lock.lockOrAssert();
⛔ Skipped due to learnings
Learnt from: taylordotfish
PR: oven-sh/bun#22227
File: src/allocators/allocation_scope.zig:284-314
Timestamp: 2025-09-02T18:25:27.976Z
Learning: In bun's custom Zig implementation, the `#` prefix for private fields is valid syntax and should not be flagged as invalid. The syntax `#fieldname` creates private fields that cannot be accessed from outside the defining struct, and usage like `self.#fieldname` is correct within the same struct. This applies to fields like `#parent`, `#state`, `#allocator`, `#trace`, etc. throughout the codebase.
Learnt from: cirospaciari
PR: oven-sh/bun#22842
File: src/bun.js/webcore/ResumableSink.zig:274-276
Timestamp: 2025-09-25T18:14:27.722Z
Learning: In Zig code, private fields are declared and accessed using the `#` prefix. When a field is declared as `#field_name`, it must be accessed as `this.#field_name`, not `this.field_name`. The `#` prefix is part of the private field access syntax and should not be removed.
Learnt from: taylordotfish
PR: oven-sh/bun#22227
File: src/safety/alloc.zig:93-95
Timestamp: 2025-09-02T17:14:46.924Z
Learning: In bun's Zig codebase, they use a custom extension of Zig that supports private field syntax with the `#` prefix (e.g., `#allocator`, `#trace`). This is not standard Zig syntax but is valid in their custom implementation. Fields prefixed with `#` are private fields that cannot be accessed from outside the defining struct.
Learnt from: taylordotfish
PR: oven-sh/bun#22227
File: src/collections/multi_array_list.zig:24-24
Timestamp: 2025-09-02T18:27:23.279Z
Learning: The `#allocator` syntax in bun's custom Zig implementation is valid and does not require quoting with @"#allocator". Private fields using the `#` prefix work correctly throughout the codebase without special quoting syntax.
src/string/WTFStringImpl.zig (2)

221-224: Descriptor exposes the right hooks

Re-exporting the existing ref/deref ensures ExternalShared will reuse the proven WTF ref-counting paths, so we stay in lockstep with WebKit semantics.


227-229: Alias lines WTFString up with the new smart pointer

This keeps the public surface matching the old WTF::Ref behavior while routing through the new intrusive wrapper—nice and tidy.

src/ptr.zig (1)

16-28: Clean re-export of the new pointer utilities

Pulling ExternalShared and RawRefCount into the central ptr module makes them discoverable alongside the rest of the smart-pointer toolbox.

Comment thread src/ptr/raw_ref_count.zig

@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: 2

📜 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 149e6a3 and 64e35f2.

📒 Files selected for processing (1)
  • src/ptr/raw_ref_count.zig (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
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/ptr/raw_ref_count.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/ptr/raw_ref_count.zig
🧠 Learnings (3)
📓 Common learnings
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 : Handle reference counting correctly with ref()/deref() in JS-facing Zig code
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 : Declare the extern C symbol in Zig and export a Zig-friendly alias for use
📚 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 : Handle reference counting correctly with ref()/deref() in JS-facing Zig code

Applied to files:

  • src/ptr/raw_ref_count.zig
📚 Learning: 2025-09-02T17:14:01.470Z
Learnt from: taylordotfish
PR: oven-sh/bun#22227
File: src/ptr/shared.zig:470-470
Timestamp: 2025-09-02T17:14:01.470Z
Learning: In Zig, regular arithmetic operations (like +=) have built-in overflow detection in debug/safe builds and will panic automatically. Atomic operations (like fetchAdd) do not have this automatic safety checking, so explicit overflow checks must be added manually. This is why NonAtomicCount doesn't need explicit overflow checks while AtomicCount does.

Applied to files:

  • src/ptr/raw_ref_count.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/ptr/raw_ref_count.zig
Comment thread src/ptr/raw_ref_count.zig
@Jarred-Sumner Jarred-Sumner merged commit 266fca2 into main Sep 26, 2025
57 of 60 checks passed
@Jarred-Sumner Jarred-Sumner deleted the taylor.fish/external-shared branch September 26, 2025 22:16
taylordotfish added a commit that referenced this pull request Sep 26, 2025
Reduce the size of `bun.webcore.Blob` from 120 bytes to 96. Also make it
ref-counted: in-progress work on improving the bindings generator
depends on this, as it means C++ can pass a pointer to the `Blob` to Zig
without risking it being destroyed if the GC collects the associated
`JSBlob`.

Note that this PR depends on #23013.
taylordotfish added a commit that referenced this pull request Sep 27, 2025
Reduce the size of `bun.webcore.Blob` from 120 bytes to 96. Also make it
ref-counted: in-progress work on improving the bindings generator
depends on this, as it means C++ can pass a pointer to the `Blob` to Zig
without risking it being destroyed if the GC collects the associated
`JSBlob`.

Note that this PR depends on #23013.

(For internal tracking: fixes STAB-1289, STAB-1290)
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