← Back to list

implementing-jsc-classes-zig
by oven-sh
Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one
⭐ 86,545🍴 3,959📅 Jan 23, 20265 files · 25.2 KB
Use Cases
⚡
Efficient Code Generation
Auto-generate boilerplate code to reduce development time.
🔍
Code Review Assistance
Analyze PR changes and suggest improvements.
🔧
Refactoring Suggestions
Suggest refactoring options to improve code quality.
FAQ
Files5
25.2 KB
implementing-jsc-classes-cpp/
SKILL.md6.5 KB
implementing-jsc-classes-zig/
SKILL.md5.2 KB
writing-bundler-tests/
SKILL.md4.4 KB
writing-dev-server-tests/
SKILL.md2.9 KB
zig-system-calls/
SKILL.md6.2 KB
SKILL.md
name: implementing-jsc-classes-zig description: Creates JavaScript classes using Bun's Zig bindings generator (.classes.ts). Use when implementing new JS APIs in Zig with JSC integration.
Bun's JavaScriptCore Class Bindings Generator
Bridge JavaScript and Zig through .classes.ts definitions and Zig implementations.
Architecture
- Zig Implementation (.zig files)
- JavaScript Interface Definition (.classes.ts files)
- Generated Code (C++/Zig files connecting them)
Class Definition (.classes.ts)
define({
name: "TextDecoder",
constructor: true,
JSType: "object",
finalize: true,
proto: {
decode: { args: 1 },
encoding: { getter: true, cache: true },
fatal: { getter: true },
},
});
Options:
name: Class nameconstructor: Has public constructorJSType: "object", "function", etc.finalize: Needs cleanupproto: Properties/methodscache: Cache property values via WriteBarrier
Zig Implementation
pub const TextDecoder = struct {
pub const js = JSC.Codegen.JSTextDecoder;
pub const toJS = js.toJS;
pub const fromJS = js.fromJS;
pub const fromJSDirect = js.fromJSDirect;
encoding: []const u8,
fatal: bool,
pub fn constructor(
globalObject: *JSGlobalObject,
callFrame: *JSC.CallFrame,
) bun.JSError!*TextDecoder {
return bun.new(TextDecoder, .{ .encoding = "utf-8", .fatal = false });
}
pub fn decode(
this: *TextDecoder,
globalObject: *JSGlobalObject,
callFrame: *JSC.CallFrame,
) bun.JSError!JSC.JSValue {
const args = callFrame.arguments();
if (args.len < 1 or args.ptr[0].isUndefinedOrNull()) {
return globalObject.throw("Input cannot be null", .{});
}
return JSC.JSValue.jsString(globalObject, "result");
}
pub fn getEncoding(this: *TextDecoder, globalObject: *JSGlobalObject) JSC.JSValue {
return JSC.JSValue.createStringFromUTF8(globalObject, this.encoding);
}
fn deinit(this: *TextDecoder) void {
// Release resources
}
pub fn finalize(this: *TextDecoder) void {
this.deinit();
bun.destroy(this);
}
};
Key patterns:
- Use
bun.JSError!JSValuereturn type for error handling - Use
globalObjectnotctx deinit()for cleanup,finalize()called by GC- Update
src/bun.js/bindings/generated_classes_list.zig
CallFrame Access
const args = callFrame.arguments();
const first_arg = args.ptr[0]; // Access as slice
const argCount = args.len;
const thisValue = callFrame.thisValue();
Property Caching
For cache: true properties, generated accessors:
// Get cached value
pub fn encodingGetCached(thisValue: JSC.JSValue) ?JSC.JSValue {
const result = TextDecoderPrototype__encodingGetCachedValue(thisValue);
if (result == .zero) return null;
return result;
}
// Set cached value
pub fn encodingSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void {
TextDecoderPrototype__encodingSetCachedValue(thisValue, globalObject, value);
}
Error Handling
pub fn method(this: *MyClass, globalObject: *JSGlobalObject, callFrame: *JSC.CallFrame) bun.JSError!JSC.JSValue {
const args = callFrame.arguments();
if (args.len < 1) {
return globalObject.throw("Missing required argument", .{});
}
return JSC.JSValue.jsString(globalObject, "Success!");
}
Memory Management
pub fn deinit(this: *TextDecoder) void {
this._encoding.deref();
if (this.buffer) |buffer| {
bun.default_allocator.free(buffer);
}
}
pub fn finalize(this: *TextDecoder) void {
JSC.markBinding(@src());
this.deinit();
bun.default_allocator.destroy(this);
}
Creating a New Binding
- Define interface in
.classes.ts:
define({
name: "MyClass",
constructor: true,
finalize: true,
proto: {
myMethod: { args: 1 },
myProperty: { getter: true, cache: true },
},
});
- Implement in
.zig:
pub const MyClass = struct {
pub const js = JSC.Codegen.JSMyClass;
pub const toJS = js.toJS;
pub const fromJS = js.fromJS;
value: []const u8,
pub const new = bun.TrivialNew(@This());
pub fn constructor(globalObject: *JSGlobalObject, callFrame: *JSC.CallFrame) bun.JSError!*MyClass {
return MyClass.new(.{ .value = "" });
}
pub fn myMethod(this: *MyClass, globalObject: *JSGlobalObject, callFrame: *JSC.CallFrame) bun.JSError!JSC.JSValue {
return JSC.JSValue.jsUndefined();
}
pub fn getMyProperty(this: *MyClass, globalObject: *JSGlobalObject) JSC.JSValue {
return JSC.JSValue.jsString(globalObject, this.value);
}
pub fn deinit(this: *MyClass) void {}
pub fn finalize(this: *MyClass) void {
this.deinit();
bun.destroy(this);
}
};
- Add to
src/bun.js/bindings/generated_classes_list.zig
Generated Components
- C++ Classes:
JSMyClass,JSMyClassPrototype,JSMyClassConstructor - Method Bindings:
MyClassPrototype__myMethodCallback - Property Accessors:
MyClassPrototype__myPropertyGetterWrap - Zig Bindings: External function declarations, cached value accessors
Score
Total Score
80/100
Based on repository quality metrics
✓SKILL.md
SKILL.mdファイルが含まれている
+20
✓LICENSE
ライセンスが設定されている
+10
○説明文
100文字以上の説明がある
0/10
✓人気
GitHub Stars 1000以上
+15
✓最近の活動
1ヶ月以内に更新
+10
✓フォーク
10回以上フォークされている
+5
○Issue管理
オープンIssueが50未満
0/5
✓言語
プログラミング言語が設定されている
+5
✓タグ
1つ以上のタグが設定されている
+5
Reviews
💬
Reviews coming soon

