mirror of
https://github.com/oven-sh/bun
synced 2026-02-12 20:09:04 +00:00
feat: Add clipboard API with pure Zig implementation
- Implements Bun.clipboard.writeText() and Bun.clipboard.readText() - Pure Zig implementation using native APIs (no C++) - Windows: Win32 clipboard APIs - macOS: pbcopy/pbpaste commands - Linux: xclip/wl-clipboard support - Synchronous API for simplicity - Tests skip when no display is available 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
7
packages/bun-types/clipboard.d.ts
vendored
7
packages/bun-types/clipboard.d.ts
vendored
@@ -3,15 +3,14 @@ declare module "bun" {
|
||||
/**
|
||||
* Writes text to the system clipboard
|
||||
* @param text The text to write to the clipboard
|
||||
* @returns A promise that resolves when the text is written
|
||||
*/
|
||||
writeText(text: string): Promise<void>;
|
||||
writeText(text: string): void;
|
||||
|
||||
/**
|
||||
* Reads text from the system clipboard
|
||||
* @returns A promise that resolves with the clipboard text
|
||||
* @returns The clipboard text
|
||||
*/
|
||||
readText(): Promise<string>;
|
||||
readText(): string;
|
||||
}
|
||||
|
||||
const clipboard: Clipboard;
|
||||
|
||||
@@ -49,6 +49,7 @@ pub const BunObject = struct {
|
||||
|
||||
// --- Lazy property callbacks ---
|
||||
pub const CryptoHasher = toJSLazyPropertyCallback(Crypto.CryptoHasher.getter);
|
||||
pub const clipboard = toJSLazyPropertyCallback(Bun.getClipboardObject);
|
||||
pub const CSRF = toJSLazyPropertyCallback(Bun.getCSRFObject);
|
||||
pub const FFI = toJSLazyPropertyCallback(Bun.FFIObject.getter);
|
||||
pub const FileSystemRouter = toJSLazyPropertyCallback(Bun.getFileSystemRouter);
|
||||
@@ -63,7 +64,6 @@ pub const BunObject = struct {
|
||||
pub const SHA512_256 = toJSLazyPropertyCallback(Crypto.SHA512_256.getter);
|
||||
pub const TOML = toJSLazyPropertyCallback(Bun.getTOMLObject);
|
||||
pub const YAML = toJSLazyPropertyCallback(Bun.getYAMLObject);
|
||||
pub const clipboard = toJSLazyPropertyCallback(Bun.getClipboardObject);
|
||||
pub const Transpiler = toJSLazyPropertyCallback(Bun.getTranspilerConstructor);
|
||||
pub const argv = toJSLazyPropertyCallback(Bun.getArgv);
|
||||
pub const cwd = toJSLazyPropertyCallback(Bun.getCWD);
|
||||
|
||||
@@ -12,7 +12,7 @@ pub fn writeText(globalObject: *JSGlobalObject, callframe: *jsc.CallFrame) JSErr
|
||||
return globalObject.throw("Failed to write to clipboard: {s}", .{@errorName(err)});
|
||||
};
|
||||
|
||||
return JSPromise.resolvedPromiseValue(globalObject, .undefined);
|
||||
return .js_undefined;
|
||||
}
|
||||
|
||||
pub fn readText(globalObject: *JSGlobalObject, _: *jsc.CallFrame) JSError!JSValue {
|
||||
@@ -21,7 +21,7 @@ pub fn readText(globalObject: *JSGlobalObject, _: *jsc.CallFrame) JSError!JSValu
|
||||
};
|
||||
defer bun.default_allocator.free(text);
|
||||
|
||||
return JSPromise.resolvedPromiseValue(globalObject, ZigString.fromUTF8(text).toJS(globalObject));
|
||||
return ZigString.fromUTF8(text).toJS(globalObject);
|
||||
}
|
||||
|
||||
fn writeTextNative(text: []const u8) !void {
|
||||
@@ -156,14 +156,12 @@ fn readTextLinux(allocator: std.mem.Allocator) ![]u8 {
|
||||
return result.stdout;
|
||||
}
|
||||
|
||||
// Imports at the bottom (Zig style in Bun codebase)
|
||||
const std = @import("std");
|
||||
|
||||
const bun = @import("bun");
|
||||
const Environment = bun.Environment;
|
||||
|
||||
const JSError = bun.JSError;
|
||||
const jsc = bun.jsc;
|
||||
const JSError = jsc.JSError;
|
||||
const JSGlobalObject = jsc.JSGlobalObject;
|
||||
const JSPromise = jsc.JSPromise;
|
||||
const JSValue = jsc.JSValue;
|
||||
const ZigString = jsc.ZigString;
|
||||
const ZigString = jsc.ZigString;
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
// --- Getters ---
|
||||
#define FOR_EACH_GETTER(macro) \
|
||||
macro(clipboard) \
|
||||
macro(CSRF) \
|
||||
macro(CryptoHasher) \
|
||||
macro(FFI) \
|
||||
|
||||
@@ -707,6 +707,7 @@ JSC_DEFINE_HOST_FUNCTION(functionFileURLToPath, (JSC::JSGlobalObject * globalObj
|
||||
@begin bunObjectTable
|
||||
$ constructBunShell DontDelete|PropertyCallback
|
||||
ArrayBufferSink BunObject_lazyPropCb_wrap_ArrayBufferSink DontDelete|PropertyCallback
|
||||
clipboard BunObject_lazyPropCb_wrap_clipboard DontDelete|PropertyCallback
|
||||
Cookie constructCookieObject DontDelete|ReadOnly|PropertyCallback
|
||||
CookieMap constructCookieMapObject DontDelete|ReadOnly|PropertyCallback
|
||||
CryptoHasher BunObject_lazyPropCb_wrap_CryptoHasher DontDelete|PropertyCallback
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { expect, test } from "bun:test";
|
||||
import { describe, expect, test } from "bun:test";
|
||||
|
||||
test("Bun.clipboard exists", () => {
|
||||
expect(Bun.clipboard).toBeDefined();
|
||||
@@ -6,22 +6,24 @@ test("Bun.clipboard exists", () => {
|
||||
expect(typeof Bun.clipboard.readText).toBe("function");
|
||||
});
|
||||
|
||||
test("writeText and readText work", async () => {
|
||||
const text = "Hello from Bun clipboard!";
|
||||
await Bun.clipboard.writeText(text);
|
||||
const result = await Bun.clipboard.readText();
|
||||
expect(result).toBe(text);
|
||||
});
|
||||
describe.skipIf(!process.env.DISPLAY && process.platform === "linux")("clipboard operations", () => {
|
||||
test("writeText and readText work", () => {
|
||||
const text = "Hello from Bun clipboard!";
|
||||
Bun.clipboard.writeText(text);
|
||||
const result = Bun.clipboard.readText();
|
||||
expect(result).toBe(text);
|
||||
});
|
||||
|
||||
test("handles empty string", async () => {
|
||||
await Bun.clipboard.writeText("");
|
||||
const result = await Bun.clipboard.readText();
|
||||
expect(result).toBe("");
|
||||
});
|
||||
test("handles empty string", () => {
|
||||
Bun.clipboard.writeText("");
|
||||
const result = Bun.clipboard.readText();
|
||||
expect(result).toBe("");
|
||||
});
|
||||
|
||||
test("handles unicode", async () => {
|
||||
const text = "Hello 世界 🚀";
|
||||
await Bun.clipboard.writeText(text);
|
||||
const result = await Bun.clipboard.readText();
|
||||
expect(result).toBe(text);
|
||||
test("handles unicode", () => {
|
||||
const text = "Hello 世界 🚀";
|
||||
Bun.clipboard.writeText(text);
|
||||
const result = Bun.clipboard.readText();
|
||||
expect(result).toBe(text);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user