aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/cli/run/run-process-env.test.ts5
-rw-r--r--test/js/bun/websocket/websocket-server.test.ts3
-rw-r--r--test/js/first_party/ws/ws.test.ts12
-rw-r--r--test/js/web/workers/example.txt1
-rw-r--r--test/js/web/workers/structured-clone.test.ts248
5 files changed, 259 insertions, 10 deletions
diff --git a/test/cli/run/run-process-env.test.ts b/test/cli/run/run-process-env.test.ts
index 1d7cb2c56..8303fe19c 100644
--- a/test/cli/run/run-process-env.test.ts
+++ b/test/cli/run/run-process-env.test.ts
@@ -15,16 +15,15 @@ describe("process.env", () => {
});
// https://github.com/oven-sh/bun/issues/3589
- test('npm_lifecycle_event should have the value of the last call', () => {
+ test("npm_lifecycle_event should have the value of the last call", () => {
const dir = tempDirWithFiles("processenv_ls_call", {
"package.json": `{"scripts": { "first": "${bunExe()} run --cwd lsc second" } }`,
"lsc": {
"package.json": `{"scripts": { "second": "${bunExe()} run index.ts" } }`,
"index.ts": "console.log(process.env.npm_lifecycle_event);",
- }
+ },
});
-
const { stdout } = bunRunAsScript(dir, "first");
expect(stdout).toBe("second");
});
diff --git a/test/js/bun/websocket/websocket-server.test.ts b/test/js/bun/websocket/websocket-server.test.ts
index eb9b773a3..7a31fa396 100644
--- a/test/js/bun/websocket/websocket-server.test.ts
+++ b/test/js/bun/websocket/websocket-server.test.ts
@@ -107,7 +107,8 @@ describe("Server", () => {
const data = new Uint8Array(1 * 1024 * 1024);
// send data until backpressure is triggered
for (let i = 0; i < 10; i++) {
- if (ws.send(data) < 1) { // backpressure or dropped
+ if (ws.send(data) < 1) {
+ // backpressure or dropped
break;
}
}
diff --git a/test/js/first_party/ws/ws.test.ts b/test/js/first_party/ws/ws.test.ts
index c0b56a200..fc8e63f5f 100644
--- a/test/js/first_party/ws/ws.test.ts
+++ b/test/js/first_party/ws/ws.test.ts
@@ -110,11 +110,11 @@ describe("WebSocket", () => {
expect(isBinary).toBeTrue();
ws.ping();
});
- ws.on("ping", (data) => {
+ ws.on("ping", data => {
expect(data).toBeInstanceOf(type);
ws.pong();
});
- ws.on("pong", (data) => {
+ ws.on("pong", data => {
expect(data).toBeInstanceOf(type);
done();
});
@@ -145,7 +145,7 @@ describe("WebSocket", () => {
ws.on("open", () => {
ws.ping();
});
- ws.on("ping", (data) => {
+ ws.on("ping", data => {
expect(data).toBeInstanceOf(Buffer);
done();
});
@@ -155,7 +155,7 @@ describe("WebSocket", () => {
ws.on("open", () => {
ws.ping(message);
});
- ws.on("ping", (data) => {
+ ws.on("ping", data => {
expect(data).toEqual(Buffer.from(bytes));
done();
});
@@ -167,7 +167,7 @@ describe("WebSocket", () => {
ws.on("open", () => {
ws.pong();
});
- ws.on("pong", (data) => {
+ ws.on("pong", data => {
expect(data).toBeInstanceOf(Buffer);
done();
});
@@ -177,7 +177,7 @@ describe("WebSocket", () => {
ws.on("open", () => {
ws.pong(message);
});
- ws.on("pong", (data) => {
+ ws.on("pong", data => {
expect(data).toEqual(Buffer.from(bytes));
done();
});
diff --git a/test/js/web/workers/example.txt b/test/js/web/workers/example.txt
new file mode 100644
index 000000000..96236f815
--- /dev/null
+++ b/test/js/web/workers/example.txt
@@ -0,0 +1 @@
+example \ No newline at end of file
diff --git a/test/js/web/workers/structured-clone.test.ts b/test/js/web/workers/structured-clone.test.ts
new file mode 100644
index 000000000..61a0c1320
--- /dev/null
+++ b/test/js/web/workers/structured-clone.test.ts
@@ -0,0 +1,248 @@
+import { join } from "path";
+import { openSync } from "fs";
+
+describe("structured clone", () => {
+ let primitives_tests = [
+ { description: "primitive undefined", value: undefined },
+ { description: "primitive null", value: null },
+ { description: "primitive true", value: true },
+ { description: "primitive false", value: false },
+ { description: "primitive string, empty string", value: "" },
+ { description: "primitive string, lone high surrogate", value: "\uD800" },
+ { description: "primitive string, lone low surrogate", value: "\uDC00" },
+ { description: "primitive string, NUL", value: "\u0000" },
+ { description: "primitive string, astral character", value: "\uDBFF\uDFFD" },
+ { description: "primitive number, 0.2", value: 0.2 },
+ { description: "primitive number, 0", value: 0 },
+ { description: "primitive number, -0", value: -0 },
+ { description: "primitive number, NaN", value: NaN },
+ { description: "primitive number, Infinity", value: Infinity },
+ { description: "primitive number, -Infinity", value: -Infinity },
+ { description: "primitive number, 9007199254740992", value: 9007199254740992 },
+ { description: "primitive number, -9007199254740992", value: -9007199254740992 },
+ { description: "primitive number, 9007199254740994", value: 9007199254740994 },
+ { description: "primitive number, -9007199254740994", value: -9007199254740994 },
+ { description: "primitive BigInt, 0n", value: 0n },
+ { description: "primitive BigInt, -0n", value: -0n },
+ { description: "primitive BigInt, -9007199254740994000n", value: -9007199254740994000n },
+ {
+ description: "primitive BigInt, -9007199254740994000900719925474099400090071992547409940009007199254740994000n",
+ value: -9007199254740994000900719925474099400090071992547409940009007199254740994000n,
+ },
+ ];
+ for (let { description, value } of primitives_tests) {
+ test(description, () => {
+ var cloned = structuredClone(value);
+ expect(cloned).toBe(value);
+ });
+ }
+
+ test("Array with primitives", () => {
+ var input = [
+ undefined,
+ null,
+ true,
+ false,
+ "",
+ "\uD800",
+ "\uDC00",
+ "\u0000",
+ "\uDBFF\uDFFD",
+ 0.2,
+ 0,
+ -0,
+ NaN,
+ Infinity,
+ -Infinity,
+ 9007199254740992,
+ -9007199254740992,
+ 9007199254740994,
+ -9007199254740994,
+ -12n,
+ -0n,
+ 0n,
+ ];
+ var cloned = structuredClone(input);
+ expect(cloned).toBeInstanceOf(Array);
+ expect(cloned).not.toBe(input);
+ expect(cloned.length).toEqual(input.length);
+ for (const x in input) {
+ expect(cloned[x]).toBe(input[x]);
+ }
+ });
+ test("Object with primitives", () => {
+ var input: any = {
+ undefined: undefined,
+ null: null,
+ true: true,
+ false: false,
+ empty: "",
+ "high surrogate": "\uD800",
+ "low surrogate": "\uDC00",
+ nul: "\u0000",
+ astral: "\uDBFF\uDFFD",
+ "0.2": 0.2,
+ "0": 0,
+ "-0": -0,
+ NaN: NaN,
+ Infinity: Infinity,
+ "-Infinity": -Infinity,
+ "9007199254740992": 9007199254740992,
+ "-9007199254740992": -9007199254740992,
+ "9007199254740994": 9007199254740994,
+ "-9007199254740994": -9007199254740994,
+ "-12n": -12n,
+ "-0n": -0n,
+ "0n": 0n,
+ };
+ var cloned = structuredClone(input);
+ expect(cloned).toBeInstanceOf(Object);
+ expect(cloned).not.toBeInstanceOf(Array);
+ expect(cloned).not.toBe(input);
+ for (const x in input) {
+ expect(cloned[x]).toBe(input[x]);
+ }
+ });
+
+ test("map", () => {
+ var input = new Map();
+ input.set("a", 1);
+ input.set("b", 2);
+ input.set("c", 3);
+ var cloned = structuredClone(input);
+ expect(cloned).toBeInstanceOf(Map);
+ expect(cloned).not.toBe(input);
+ expect(cloned.size).toEqual(input.size);
+ for (const [key, value] of input) {
+ expect(cloned.get(key)).toBe(value);
+ }
+ });
+
+ test("set", () => {
+ var input = new Set();
+ input.add("a");
+ input.add("b");
+ input.add("c");
+ var cloned = structuredClone(input);
+ expect(cloned).toBeInstanceOf(Set);
+ expect(cloned).not.toBe(input);
+ expect(cloned.size).toEqual(input.size);
+ for (const value of input) {
+ expect(cloned.has(value)).toBe(true);
+ }
+ });
+
+ describe("bun blobs work", () => {
+ test("simple", async () => {
+ const blob = new Blob(["hello"], { type: "application/octet-stream" });
+ const cloned = structuredClone(blob);
+ await compareBlobs(blob, cloned);
+ });
+ test("empty", async () => {
+ const emptyBlob = new Blob([], { type: "" });
+ const clonedEmpty = structuredClone(emptyBlob);
+ await compareBlobs(emptyBlob, clonedEmpty);
+ });
+ test("empty with type", async () => {
+ const emptyBlob = new Blob([], { type: "application/octet-stream" });
+ const clonedEmpty = structuredClone(emptyBlob);
+ await compareBlobs(emptyBlob, clonedEmpty);
+ });
+ test("unknown type", async () => {
+ const blob = new Blob(["hello type"], { type: "this is type" });
+ const cloned = structuredClone(blob);
+ await compareBlobs(blob, cloned);
+ });
+ test("file from path", async () => {
+ const blob = Bun.file(join(import.meta.dir, "example.txt"));
+ const cloned = structuredClone(blob);
+ expect(cloned.lastModified).toBe(blob.lastModified);
+ expect(cloned.name).toBe(blob.name);
+ });
+ test("file from fd", async () => {
+ const fd = openSync(join(import.meta.dir, "example.txt"), "r");
+ const blob = Bun.file(fd);
+ const cloned = structuredClone(blob);
+ expect(cloned.lastModified).toBe(blob.lastModified);
+ expect(cloned.name).toBe(blob.name);
+ });
+ test("unpaired high surrogate (invalid utf-8)", async () => {
+ const blob = createBlob(encode_cesu8([0xd800]));
+ const cloned = structuredClone(blob);
+ await compareBlobs(blob, cloned);
+ });
+ test("unpaired low surrogate (invalid utf-8)", async () => {
+ const blob = createBlob(encode_cesu8([0xdc00]));
+ const cloned = structuredClone(blob);
+ await compareBlobs(blob, cloned);
+ });
+ test("paired surrogates (invalid utf-8)", async () => {
+ const blob = createBlob(encode_cesu8([0xd800, 0xdc00]));
+ const cloned = structuredClone(blob);
+ await compareBlobs(blob, cloned);
+ });
+ });
+
+ describe("transferrables", () => {
+ test("ArrayBuffer", () => {
+ const buffer = Uint8Array.from([1]).buffer;
+ const cloned = structuredClone(buffer, { transfer: [buffer] });
+ expect(buffer.byteLength).toBe(0);
+ expect(cloned.byteLength).toBe(1);
+ });
+ test("A detached ArrayBuffer cannot be transferred", () => {
+ const buffer = new ArrayBuffer(2);
+ const cloned = structuredClone(buffer, { transfer: [buffer] });
+ expect(() => {
+ structuredClone(buffer, { transfer: [buffer] });
+ }).toThrow(DOMException);
+ });
+ test("Transferring a non-transferable platform object fails", () => {
+ const blob = new Blob();
+ expect(() => {
+ structuredClone(blob, { transfer: [blob] });
+ }).toThrow(DOMException);
+ });
+ });
+});
+
+async function compareBlobs(original: Blob, cloned: Blob) {
+ expect(cloned).toBeInstanceOf(Blob);
+ expect(cloned).not.toBe(original);
+ expect(cloned.size).toBe(original.size);
+ expect(cloned.type).toBe(original.type);
+ const ab1 = await new Response(cloned).arrayBuffer();
+ const ab2 = await new Response(original).arrayBuffer();
+ expect(ab1.byteLength).toBe(ab2.byteLength);
+ const ta1 = new Uint8Array(ab1);
+ const ta2 = new Uint8Array(ab2);
+ for (let i = 0; i < ta1.length; i++) {
+ expect(ta1[i]).toBe(ta2[i]);
+ }
+}
+
+function encode_cesu8(codeunits: number[]): number[] {
+ // http://www.unicode.org/reports/tr26/ section 2.2
+ // only the 3-byte form is supported
+ const rv: number[] = [];
+ codeunits.forEach(function (codeunit) {
+ rv.push(b("11100000") + ((codeunit & b("1111000000000000")) >> 12));
+ rv.push(b("10000000") + ((codeunit & b("0000111111000000")) >> 6));
+ rv.push(b("10000000") + (codeunit & b("0000000000111111")));
+ });
+ return rv;
+}
+
+function b(s: string): number {
+ return parseInt(s, 2);
+}
+
+function createBlob(arr: number[]): Blob {
+ const buffer = new ArrayBuffer(arr.length);
+ const view = new DataView(buffer);
+ for (let i = 0; i < arr.length; i++) {
+ view.setUint8(i, arr[i]);
+ }
+
+ return new Blob([view]);
+}