chore(vendor): import pi 1.3.0

Imported as a linear vendor commit so forge rebases do not replay the upstream root tree.

git-subtree-dir: third_party/pi

git-subtree-split: 71023aec1546d6d677a65669c5665c0927ce0dd0
This commit is contained in:
alexion committed 2026-10-15 17:58:48 -04:00
1 parent 719370c8f7
commit 6081e3e325
1743 files changed
+205459 -131704

No files matched your search

@@ -0,0 +1,31 @@
const { createHash } = require("node:crypto");
const assert = require("node:assert/strict");
const { readFileSync } = require("node:fs");
(async () => {
let ticks = 0;
const timer = setInterval(() => ticks++, 10);
const started = performance.now();
try {
const helper = require(process.argv[2]);
const pending = helper[process.argv[3]]();
assert.ok(pending instanceof Promise, "Native reads must return promises");
const value = await pending;
const bytes = typeof value === "string" || Buffer.isBuffer(value) ? Buffer.from(value) : undefined;
console.log(JSON.stringify({
ok: true,
value: value === null || (typeof value === "string" && value.length <= 100) ? value : undefined,
unavailable: value === undefined || undefined,
length: bytes?.length,
hash: bytes && createHash("sha256").update(bytes).digest("hex"),
}));
} catch (error) {
console.log(JSON.stringify({ ok: false, error: String(error) }));
} finally {
clearInterval(timer);
if (performance.now() - started > 200) assert.ok(ticks > 5, "Clipboard I/O must not block the JS event loop");
// Check before Node exits: process exit must not hide a leaked child or zombie.
assert.equal(readFileSync(`/proc/self/task/${process.pid}/children`, "utf8").trim(), "");
}
})().catch((error) => { console.error(error); process.exitCode = 1; });
@@ -0,0 +1,64 @@
#include <assert.h>
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
static atomic_int allocations, reads;
static atomic_bool released;
static void* tracked_calloc(size_t count, size_t size) {
void* pointer = calloc(count, size);
if (pointer) atomic_fetch_add(&allocations, 1);
return pointer;
}
static void tracked_free(void* pointer) {
if (pointer) atomic_fetch_sub(&allocations, 1);
free(pointer);
}
#define calloc tracked_calloc
#define free tracked_free
#include "../../native/linux/src/clipboard-worker.h"
#undef calloc
#undef free
// Exercise the production executor with a controlled blocking callback, without X11.
static void read_clipboard(clipboard_job* job) {
job->data = tracked_calloc(5, 1);
assert(job->data);
memcpy(job->data, "text", 4);
job->length = 4;
job->format = job->operation == CLIPBOARD_IMAGE ? CLIPBOARD_BUFFER : CLIPBOARD_UTF8;
atomic_fetch_add(&reads, 1);
while (!atomic_load(&released)) {
struct timespec delay = {.tv_nsec = 1000000};
nanosleep(&delay, 0);
}
}
static napi_value release_reader(napi_env env, napi_callback_info info) {
(void)info;
atomic_store(&released, true);
return undefined_value(env);
}
static napi_value get_state(napi_env env, napi_callback_info info) {
(void)info;
char state[80];
pthread_mutex_lock(&worker_mutex);
snprintf(state, sizeof(state), "%d,%d,%d", atomic_load(&reads), atomic_load(&allocations), worker_busy);
pthread_mutex_unlock(&worker_mutex);
napi_create_string_utf8_fn create_string = (napi_create_string_utf8_fn)node_symbol("napi_create_string_utf8");
napi_value result = 0;
create_string(env, state, NAPI_AUTO_LENGTH, &result);
return result;
}
PI_NAPI_EXPORT napi_value napi_register_module_v1(napi_env env, napi_value exports) {
set_function_export(env, exports, "getText", get_clipboard_text);
set_function_export(env, exports, "getImage", get_clipboard_image);
set_function_export(env, exports, "release", release_reader);
set_function_export(env, exports, "state", get_state);
return exports;
}
@@ -0,0 +1,66 @@
const assert = require("node:assert/strict");
const { once } = require("node:events");
const { readFile } = require("node:fs/promises");
const { setTimeout: delay } = require("node:timers/promises");
const { isMainThread, parentPort, Worker, workerData } = require("node:worker_threads");
async function waitFor(predicate) {
const deadline = performance.now() + 5000;
while (!predicate()) {
assert.ok(performance.now() < deadline, "Timed out waiting for the private reader");
await delay(10);
}
}
(async () => {
if (!isMainThread) {
const helper = require(workerData);
void helper.getText();
await waitFor(() => helper.state().startsWith("1,"));
parentPort.postMessage("reading");
return;
}
const [addon, mode] = process.argv.slice(2);
if (mode === "worker-exit") {
// The originating environment unloads while its private callback still waits.
const worker = new Worker(__filename, { workerData: addon });
await once(worker, "message");
await worker.terminate();
const helper = require(addon);
assert.equal(helper.state(), "1,1,1", "The detached operation survives environment teardown");
helper.release();
await waitFor(() => helper.state() === "1,0,0");
assert.equal(await helper.getText(), "text");
console.log("passed");
return;
}
const helper = require(addon);
const started = performance.now();
const pending = helper.getText();
await waitFor(() => helper.state().startsWith("1,"));
if (mode === "process-exit") {
assert.equal(await pending, undefined);
console.log("passed");
return; // The private callback never finishes; Node must still exit naturally.
}
const concurrentStarted = performance.now();
const concurrent = Array.from({ length: 20 }, (_, index) => helper[index % 2 ? "getText" : "getImage"]());
// With UV_THREADPOOL_SIZE=2, a second blocked native task would delay this read.
await readFile(__filename);
assert.deepEqual(await Promise.all(concurrent), Array(20).fill(undefined));
assert.ok(performance.now() - concurrentStarted < 1500, "Concurrent reads and filesystem I/O must remain available");
assert.equal(await pending, undefined);
assert.ok(performance.now() - started < 4500, "The shared worker must leave its bounded wait");
assert.equal(helper.state(), "1,1,1", "Only one private reader may remain blocked");
assert.equal(await helper.getImage(), undefined);
assert.equal(helper.state(), "1,1,1", "Another request must not start another private reader");
helper.release();
await waitFor(() => helper.state() === "1,0,0");
assert.equal(await helper.getText(), "text");
assert.deepEqual(await helper.getImage(), Buffer.from("text"));
assert.equal(helper.state(), "3,0,0", "Late and successful results must all be freed");
console.log("passed");
})().catch((error) => {
console.error(error);
process.exitCode = 1;
});
@@ -0,0 +1,177 @@
#include <xcb/xcb.h>
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Track only allocations made by the clipboard implementation, not libxcb.
// This makes the partial-transfer leak regression deterministic, unlike RSS.
static void* allocations[64];
static size_t sizes[64];
static size_t allocated_bytes;
static size_t peak_bytes;
static void* tracked_realloc(void* pointer, size_t size) {
size_t index = 0;
while (index < 64 && allocations[index] != pointer) index++;
assert(index < 64);
void* result = realloc(pointer, size);
if (result) {
allocated_bytes = allocated_bytes - sizes[index] + size;
sizes[index] = size;
allocations[index] = result;
if (allocated_bytes > peak_bytes) peak_bytes = allocated_bytes;
}
return result;
}
static void tracked_free(void* pointer) {
for (size_t index = 0; pointer && index < 64; index++) {
if (allocations[index] == pointer) {
allocated_bytes -= sizes[index];
sizes[index] = 0;
allocations[index] = 0;
break;
}
}
free(pointer);
}
#define realloc tracked_realloc
#define free tracked_free
#include "../../native/linux/src/linux-platform-x11.c"
#undef realloc
#undef free
int main(int argc, char** argv) {
if (argc != 2) return 1;
if (strcmp(argv[1], "metadata") == 0) {
xcb_atom_t atom = XCB_ATOM_STRING;
property_data chunk = {
.data = (unsigned char*)&atom, .length = sizeof(atom),
.items = 1, .format = 32, .type = XCB_ATOM_ATOM,
};
property_data result = {0};
assert(append_property(&result, &chunk));
assert(append_property(&result, &chunk));
assert(result.length == 2 * sizeof(atom) && result.items == 2);
chunk.format = 8;
chunk.items = sizeof(atom);
assert(!append_property(&result, &chunk));
chunk.format = 32;
chunk.items = 1;
chunk.type = XCB_ATOM_STRING;
assert(!append_property(&result, &chunk));
chunk.type = XCB_ATOM_ATOM;
chunk.length--;
assert(!append_property(&result, &chunk));
assert(result.length == 2 * sizeof(atom) && result.items == 2);
// The terminating chunk must agree with the preceding metadata too.
chunk.length = chunk.items = 0;
chunk.format = 8;
assert(!append_property(&result, &chunk));
chunk.format = 32;
assert(append_property(&result, &chunk));
tracked_free(result.data);
assert(allocated_bytes == 0);
puts("validated");
return 0;
}
if (strcmp(argv[1], "text") == 0 || strcmp(argv[1], "image") == 0) {
x11_clipboard clipboard;
assert(open_clipboard(&clipboard));
property_data result = {0};
bool received = read_selection(&clipboard, strcmp(argv[1], "image") == 0, &result);
close_clipboard(&clipboard);
assert(!received);
assert(!result.data && !result.length);
assert(peak_bytes >= 8192); // Both the received chunk and accumulated data were allocated.
assert(allocated_bytes == 0);
puts("clean");
return 0;
}
x11_clipboard clipboard;
assert(open_clipboard(&clipboard));
xcb_connection_t* connection = clipboard.connection;
xcb_atom_t text = intern_atom(&clipboard, "UTF8_STRING");
xcb_atom_t image = intern_atom(&clipboard, "image/png");
xcb_set_selection_owner(connection, clipboard.window, clipboard.clipboard, XCB_CURRENT_TIME);
// Wait for the server to process selection ownership before reporting ready.
assert(intern_atom(&clipboard, "READY") != XCB_NONE);
puts("ready");
fflush(stdout);
xcb_window_t requestor = XCB_NONE;
xcb_atom_t property = XCB_NONE;
xcb_atom_t target = XCB_NONE;
bool sent_chunk = false;
xcb_generic_event_t* event;
while ((event = xcb_wait_for_event(connection))) {
uint8_t type = event->response_type & 0x7f;
if (type == XCB_SELECTION_REQUEST) {
xcb_selection_request_event_t* request = (xcb_selection_request_event_t*)event;
puts("requested");
fflush(stdout);
if (strcmp(argv[1], "idle") == 0) {
free(event);
continue;
}
xcb_atom_t response_property = request->property;
if (strcmp(argv[1], "direct-text") == 0) {
if (request->target == text) {
const char value[] = "café 日本語";
xcb_change_property(connection, XCB_PROP_MODE_REPLACE, request->requestor,
request->property, text, 8, sizeof(value) - 1, value);
} else {
response_property = XCB_NONE;
}
} else if (request->target == clipboard.targets) {
xcb_atom_t targets[] = {text, image};
xcb_change_property(connection, XCB_PROP_MODE_REPLACE, request->requestor,
request->property, XCB_ATOM_ATOM, 32, 2, targets);
} else {
requestor = request->requestor;
property = request->property;
target = request->target;
uint32_t mask = XCB_EVENT_MASK_PROPERTY_CHANGE;
xcb_change_window_attributes(connection, requestor, XCB_CW_EVENT_MASK, &mask);
uint32_t length = 8192;
xcb_change_property(connection, XCB_PROP_MODE_REPLACE, requestor,
property, clipboard.incr, 32, 1, &length);
}
union {
xcb_selection_notify_event_t selection;
char bytes[32];
} notification = { .selection = {
.response_type = XCB_SELECTION_NOTIFY,
.time = request->time,
.requestor = request->requestor,
.selection = request->selection,
.target = request->target,
.property = response_property,
} };
xcb_send_event(connection, false, request->requestor, XCB_EVENT_MASK_NO_EVENT, notification.bytes);
xcb_flush(connection);
} else if (type == XCB_PROPERTY_NOTIFY) {
xcb_property_notify_event_t* notification = (xcb_property_notify_event_t*)event;
if (notification->window == requestor && notification->atom == property &&
notification->state == XCB_PROPERTY_DELETE) {
if (!sent_chunk) {
unsigned char chunk[4096] = {0};
xcb_change_property(connection, XCB_PROP_MODE_REPLACE, requestor, property, target, 8, sizeof(chunk), chunk);
sent_chunk = true;
} else if (strcmp(argv[1], "invalid") == 0) {
// Reject the terminating chunk after allocating the preceding data.
xcb_change_property(connection, XCB_PROP_MODE_REPLACE, requestor, property, XCB_ATOM_ATOM, 32, 0, 0);
} // Otherwise never finish the transfer; the reader must time out.
xcb_flush(connection);
}
}
free(event);
}
close_clipboard(&clipboard);
}