mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
217 lines
6.4 KiB
TypeScript
217 lines
6.4 KiB
TypeScript
import {
|
|
callerSourceOrigin,
|
|
describeArray,
|
|
deserialize,
|
|
drainMicrotasks,
|
|
edenGC,
|
|
fullGC,
|
|
gcAndSweep,
|
|
getProtectedObjects,
|
|
getRandomSeed,
|
|
heapSize,
|
|
heapStats,
|
|
isRope,
|
|
describe as jscDescribe,
|
|
memoryUsage,
|
|
numberOfDFGCompiles,
|
|
optimizeNextInvocation,
|
|
profile,
|
|
releaseWeakRefs,
|
|
reoptimizationRetryCount,
|
|
serialize,
|
|
setRandomSeed,
|
|
setTimeZone,
|
|
totalCompileTime,
|
|
} from "bun:jsc";
|
|
import { describe, expect, it } from "bun:test";
|
|
import { isBuildKite, isWindows } from "harness";
|
|
|
|
describe("bun:jsc", () => {
|
|
function count() {
|
|
var j = 0;
|
|
for (var i = 0; i < 999999; i++) {
|
|
j += i + 2;
|
|
}
|
|
|
|
return j;
|
|
}
|
|
|
|
it("describe", () => {
|
|
expect(jscDescribe([])).toBeDefined();
|
|
});
|
|
it("describeArray", () => {
|
|
expect(describeArray([1, 2, 3])).toBeDefined();
|
|
});
|
|
it("gcAndSweep", () => {
|
|
expect(gcAndSweep()).toBeGreaterThan(0);
|
|
});
|
|
it("fullGC", () => {
|
|
expect(fullGC()).toBeGreaterThan(0);
|
|
});
|
|
it("edenGC", () => {
|
|
expect(edenGC()).toBeGreaterThan(0);
|
|
});
|
|
it("heapSize", () => {
|
|
expect(heapSize()).toBeGreaterThan(0);
|
|
});
|
|
it("heapStats", () => {
|
|
const stats = heapStats();
|
|
expect(stats.heapCapacity).toBeGreaterThan(0);
|
|
expect(stats.heapSize).toBeGreaterThan(0);
|
|
expect(stats.objectCount).toBeGreaterThan(0);
|
|
});
|
|
it("memoryUsage", () => {
|
|
const usage = memoryUsage();
|
|
expect(usage.current).toBeGreaterThan(0);
|
|
expect(usage.peak).toBeGreaterThan(0);
|
|
});
|
|
it("getRandomSeed", () => {
|
|
expect(getRandomSeed()).toBeDefined();
|
|
});
|
|
it("setRandomSeed", () => {
|
|
expect(setRandomSeed(2)).toBeUndefined();
|
|
});
|
|
it("isRope", () => {
|
|
// https://twitter.com/bunjavascript/status/1806921203644571685
|
|
let y;
|
|
y = 123;
|
|
expect(isRope("a" + y + "b")).toBe(true);
|
|
expect(isRope("abcdefgh")).toBe(false);
|
|
});
|
|
it("callerSourceOrigin", () => {
|
|
expect(callerSourceOrigin()).toBe(import.meta.url);
|
|
});
|
|
it("noFTL", () => {});
|
|
it("noOSRExitFuzzing", () => {});
|
|
it("optimizeNextInvocation", () => {
|
|
count();
|
|
expect(optimizeNextInvocation(count)).toBeUndefined();
|
|
count();
|
|
});
|
|
it("numberOfDFGCompiles", async () => {
|
|
await Bun.sleep(5); // this failed once and i suspect it is because the query was done too fast
|
|
expect(numberOfDFGCompiles(count)).toBeGreaterThanOrEqual(0);
|
|
});
|
|
it("releaseWeakRefs", () => {
|
|
expect(releaseWeakRefs()).toBeUndefined();
|
|
});
|
|
it("totalCompileTime", () => {
|
|
expect(totalCompileTime(count)).toBeGreaterThanOrEqual(0);
|
|
});
|
|
it("reoptimizationRetryCount", () => {
|
|
expect(reoptimizationRetryCount(count)).toBeGreaterThanOrEqual(0);
|
|
});
|
|
it("drainMicrotasks", () => {
|
|
expect(drainMicrotasks()).toBeUndefined();
|
|
});
|
|
it("startRemoteDebugger", () => {
|
|
// try {
|
|
// startRemoteDebugger("");
|
|
// } catch (e) {
|
|
// if (process.platform !== "darwin") {
|
|
// throw e;
|
|
// }
|
|
// }
|
|
});
|
|
it("getProtectedObjects", () => {
|
|
expect(getProtectedObjects().length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it("setTimeZone", () => {
|
|
var origTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
const realOrigTimezone = origTimezone;
|
|
if (origTimezone === "America/Anchorage") {
|
|
origTimezone = "America/New_York";
|
|
}
|
|
const origDate = new Date();
|
|
origDate.setSeconds(0);
|
|
origDate.setMilliseconds(0);
|
|
origDate.setMinutes(0);
|
|
const origDateString = origDate.toString();
|
|
expect(origTimezone).toBeDefined();
|
|
expect(origTimezone).not.toBe("America/Anchorage");
|
|
expect(setTimeZone("America/Anchorage")).toBe("America/Anchorage");
|
|
expect(Intl.DateTimeFormat().resolvedOptions().timeZone).toBe("America/Anchorage");
|
|
if (realOrigTimezone === origTimezone) {
|
|
const newDate = new Date();
|
|
newDate.setSeconds(0);
|
|
newDate.setMilliseconds(0);
|
|
newDate.setMinutes(0);
|
|
const newDateString = newDate.toString();
|
|
expect(newDateString).not.toBe(origDateString);
|
|
}
|
|
|
|
setTimeZone(realOrigTimezone);
|
|
|
|
expect(Intl.DateTimeFormat().resolvedOptions().timeZone).toBe(origTimezone);
|
|
});
|
|
|
|
it("serialize", () => {
|
|
const serialized = serialize({ a: 1 });
|
|
expect(serialized).toBeInstanceOf(SharedArrayBuffer);
|
|
expect(deserialize(serialized)).toStrictEqual({ a: 1 });
|
|
const nested = serialize(serialized);
|
|
expect(deserialize(deserialize(nested))).toStrictEqual({ a: 1 });
|
|
});
|
|
|
|
it("serialize (binaryType: 'nodebuffer')", () => {
|
|
const serialized = serialize({ a: 1 }, { binaryType: "nodebuffer" });
|
|
expect(serialized).toBeInstanceOf(Buffer);
|
|
expect(serialized.buffer).toBeInstanceOf(SharedArrayBuffer);
|
|
expect(deserialize(serialized)).toStrictEqual({ a: 1 });
|
|
const nested = serialize(serialized);
|
|
expect(deserialize(deserialize(nested))).toStrictEqual({ a: 1 });
|
|
});
|
|
|
|
it("serialize GC test", () => {
|
|
for (let i = 0; i < 1000; i++) {
|
|
serialize({ a: 1 });
|
|
}
|
|
Bun.gc(true);
|
|
});
|
|
|
|
it.todoIf(isBuildKite && isWindows)("profile async", async () => {
|
|
const { promise, resolve } = Promise.withResolvers();
|
|
const result = await profile(
|
|
async function hey(arg1: number) {
|
|
await Bun.sleep(10).then(() => resolve(arguments));
|
|
return arg1;
|
|
},
|
|
1,
|
|
2,
|
|
);
|
|
const input = await promise;
|
|
expect({ ...input }).toStrictEqual({ "0": 2 });
|
|
});
|
|
|
|
it.todoIf(isBuildKite && isWindows)("profile can be called multiple times", () => {
|
|
// Fibonacci generates deep stacks and is CPU-intensive
|
|
function fib(n: number): number {
|
|
if (n <= 1) return n;
|
|
return fib(n - 1) + fib(n - 2);
|
|
}
|
|
|
|
// First profile call
|
|
const result1 = profile(() => fib(30));
|
|
expect(result1).toBeDefined();
|
|
expect(result1.functions).toBeDefined();
|
|
expect(result1.stackTraces).toBeDefined();
|
|
expect(result1.stackTraces.traces.length).toBeGreaterThan(0);
|
|
|
|
// Second profile call - should work after first one completed
|
|
// This verifies that shutdown() -> pause() fix works
|
|
const result2 = profile(() => fib(30));
|
|
expect(result2).toBeDefined();
|
|
expect(result2.functions).toBeDefined();
|
|
expect(result2.stackTraces).toBeDefined();
|
|
expect(result2.stackTraces.traces.length).toBeGreaterThan(0);
|
|
|
|
// Third profile call - verify profiler can be reused multiple times
|
|
const result3 = profile(() => fib(30));
|
|
expect(result3).toBeDefined();
|
|
expect(result3.functions).toBeDefined();
|
|
expect(result3.stackTraces).toBeDefined();
|
|
expect(result3.stackTraces.traces.length).toBeGreaterThan(0);
|
|
});
|
|
});
|