aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/bundler/bun-build-api.test.ts23
-rw-r--r--test/js/bun/http/serve.test.ts32
-rw-r--r--test/js/bun/plugin/module-plugins.ts38
-rw-r--r--test/js/bun/plugin/plugins.test.ts78
-rw-r--r--test/js/bun/resolve/import-meta.test.js2
-rw-r--r--test/js/bun/resolve/png/test-png-import.test.js4
-rw-r--r--test/js/bun/resolve/resolve.test.ts143
-rw-r--r--test/js/node/net/node-net.test.ts7
-rw-r--r--test/js/node/process/process.test.js6
-rw-r--r--test/js/web/fetch/fetch.test.ts102
10 files changed, 425 insertions, 10 deletions
diff --git a/test/bundler/bun-build-api.test.ts b/test/bundler/bun-build-api.test.ts
index 3c2308d94..d1f1a10b8 100644
--- a/test/bundler/bun-build-api.test.ts
+++ b/test/bundler/bun-build-api.test.ts
@@ -290,4 +290,27 @@ describe("Bun.build", () => {
// depends on the ws package in the test/node_modules.
expect(content).toContain("var websocket = __toESM(require_websocket(), 1);");
});
+
+ test("module() throws error", async () => {
+ expect(() =>
+ Bun.build({
+ entrypoints: [join(import.meta.dir, "./fixtures/trivial/bundle-ws.ts")],
+ plugins: [
+ {
+ name: "test",
+ setup: b => {
+ b.module("ad", () => {
+ return {
+ exports: {
+ hello: "world",
+ },
+ loader: "object",
+ };
+ });
+ },
+ },
+ ],
+ }),
+ ).toThrow();
+ });
});
diff --git a/test/js/bun/http/serve.test.ts b/test/js/bun/http/serve.test.ts
index be271cf33..67b7614b2 100644
--- a/test/js/bun/http/serve.test.ts
+++ b/test/js/bun/http/serve.test.ts
@@ -1237,14 +1237,42 @@ it("server.requestIP (v6)", async () => {
fetch(req, server) {
return Response.json(server.requestIP(req));
},
- hostname: "0000:0000:0000:0000:0000:0000:0000:0001",
+ hostname: "::1",
});
const response = await fetch(`http://localhost:${server.port}`).then(x => x.json());
expect(response).toEqual({
- address: "0000:0000:0000:0000:0000:0000:0000:0001",
+ address: "::1",
family: "IPv6",
port: expect.any(Number),
});
server.stop(true);
});
+
+it("server.requestIP (unix)", async () => {
+ const unix = "/tmp/bun-serve.sock";
+ const server = Bun.serve({
+ unix,
+ fetch(req, server) {
+ return Response.json(server.requestIP(req));
+ },
+ });
+ const requestText = `GET / HTTP/1.1\r\nHost: localhost\r\n\r\n`;
+ const received: Buffer[] = [];
+ const { resolve, promise } = Promise.withResolvers<void>();
+ const connection = await Bun.connect({
+ unix,
+ socket: {
+ data(socket, data) {
+ received.push(data);
+ resolve();
+ },
+ },
+ });
+ connection.write(requestText);
+ connection.flush();
+ await promise;
+ expect(Buffer.concat(received).toString()).toEndWith("\r\n\r\nnull");
+ connection.end();
+ server.stop(true);
+});
diff --git a/test/js/bun/plugin/module-plugins.ts b/test/js/bun/plugin/module-plugins.ts
new file mode 100644
index 000000000..d6034c5df
--- /dev/null
+++ b/test/js/bun/plugin/module-plugins.ts
@@ -0,0 +1,38 @@
+import { plugin } from "bun";
+plugin({
+ name: "i am virtual!",
+ setup(builder) {
+ builder.module("my-virtual-module-async", async () => {
+ // check
+ await Bun.sleep(1);
+ return {
+ exports: {
+ hello: "world",
+ },
+ loader: "object",
+ };
+ });
+
+ builder.module("my-virtual-module-sync", () => {
+ return {
+ exports: {
+ hello: "world",
+ },
+ loader: "object",
+ };
+ });
+
+ builder.onLoad({ filter: /.*/, namespace: "rejected-promise" }, async ({ path }) => {
+ throw new Error("Rejected Promise");
+ });
+
+ builder.onResolve({ filter: /.*/, namespace: "rejected-promise2" }, ({ path }) => ({
+ namespace: "rejected-promise2",
+ path,
+ }));
+
+ builder.onLoad({ filter: /.*/, namespace: "rejected-promise2" }, ({ path }) => {
+ return Promise.reject(new Error("Rejected Promise"));
+ });
+ },
+});
diff --git a/test/js/bun/plugin/plugins.test.ts b/test/js/bun/plugin/plugins.test.ts
index c2827f600..2d3cfa1fa 100644
--- a/test/js/bun/plugin/plugins.test.ts
+++ b/test/js/bun/plugin/plugins.test.ts
@@ -185,6 +185,7 @@ plugin({
// This is to test that it works when imported from a separate file
import "../../third_party/svelte";
+import "./module-plugins";
describe("require", () => {
it("SSRs `<h1>Hello world!</h1>` with Svelte", () => {
@@ -210,6 +211,83 @@ describe("require", () => {
});
});
+describe("module", () => {
+ it("throws with require()", () => {
+ expect(() => require("my-virtual-module-async")).toThrow();
+ });
+
+ it("async module works with async import", async () => {
+ // @ts-expect-error
+ const { hello } = await import("my-virtual-module-async");
+
+ expect(hello).toBe("world");
+ delete require.cache["my-virtual-module-async"];
+ });
+
+ it("sync module module works with require()", async () => {
+ const { hello } = require("my-virtual-module-sync");
+
+ expect(hello).toBe("world");
+ delete require.cache["my-virtual-module-sync"];
+ });
+
+ it("sync module module works with require.resolve()", async () => {
+ expect(require.resolve("my-virtual-module-sync")).toBe("my-virtual-module-sync");
+ delete require.cache["my-virtual-module-sync"];
+ });
+
+ it("sync module module works with import", async () => {
+ // @ts-expect-error
+ const { hello } = await import("my-virtual-module-sync");
+
+ expect(hello).toBe("world");
+ delete require.cache["my-virtual-module-sync"];
+ });
+
+ it("modules are overridable", async () => {
+ // @ts-expect-error
+ let { hello, there } = await import("my-virtual-module-sync");
+ expect(there).toBeUndefined();
+ expect(hello).toBe("world");
+
+ Bun.plugin({
+ setup(builder) {
+ builder.module("my-virtual-module-sync", () => ({
+ exports: {
+ there: true,
+ },
+ loader: "object",
+ }));
+ },
+ });
+
+ {
+ const { there, hello } = require("my-virtual-module-sync");
+ expect(there).toBe(true);
+ expect(hello).toBeUndefined();
+ }
+
+ Bun.plugin({
+ setup(builder) {
+ builder.module("my-virtual-module-sync", () => ({
+ exports: {
+ yo: true,
+ },
+ loader: "object",
+ }));
+ },
+ });
+
+ {
+ // @ts-expect-error
+ const { there, hello, yo } = await import("my-virtual-module-sync");
+ expect(yo).toBe(true);
+ expect(hello).toBeUndefined();
+ expect(there).toBeUndefined();
+ }
+ });
+});
+
describe("dynamic import", () => {
it("SSRs `<h1>Hello world!</h1>` with Svelte", async () => {
const { default: App }: any = await import("./hello.svelte");
diff --git a/test/js/bun/resolve/import-meta.test.js b/test/js/bun/resolve/import-meta.test.js
index a940d0c87..e0e3bb11e 100644
--- a/test/js/bun/resolve/import-meta.test.js
+++ b/test/js/bun/resolve/import-meta.test.js
@@ -102,7 +102,7 @@ it("Module.createRequire(file://url).resolve(file://url)", () => {
const createdRequire = Module.createRequire(import.meta.url);
const result1 = createdRequire.resolve("./require-json.json");
- const result2 = createdRequire.resolve("file://./require-json.json");
+ const result2 = createdRequire.resolve(`file://${expected}`);
expect(result1).toBe(expected);
expect(result2).toBe(expected);
});
diff --git a/test/js/bun/resolve/png/test-png-import.test.js b/test/js/bun/resolve/png/test-png-import.test.js
index f4a809e7a..ca2d0b9ce 100644
--- a/test/js/bun/resolve/png/test-png-import.test.js
+++ b/test/js/bun/resolve/png/test-png-import.test.js
@@ -1,7 +1,7 @@
import { expect, test } from "bun:test";
import { resolve } from "path";
-// import MyPNG from "./test-png.png";
+import MyPNG from "./test-png.png";
-test.todo("png import", () => {
+test("png import", () => {
expect(MyPNG).toBe(resolve(__dirname, "./test-png.png"));
});
diff --git a/test/js/bun/resolve/resolve.test.ts b/test/js/bun/resolve/resolve.test.ts
index a9272fb3f..217d3dc81 100644
--- a/test/js/bun/resolve/resolve.test.ts
+++ b/test/js/bun/resolve/resolve.test.ts
@@ -92,7 +92,6 @@ it("file url in import resolves", async () => {
});
writeFileSync(`${dir}/test.js`, `import {foo} from 'file://${dir}/index.js';\nconsole.log(foo);`);
- console.log("dir", dir);
const { exitCode, stdout } = Bun.spawnSync({
cmd: [bunExe(), `${dir}/test.js`],
env: bunEnv,
@@ -102,13 +101,97 @@ it("file url in import resolves", async () => {
expect(stdout.toString("utf8")).toBe("1\n");
});
+it("invalid file url in import throws error", async () => {
+ const dir = tempDirWithFiles("fileurl", {});
+ writeFileSync(`${dir}/test.js`, `import {foo} from 'file://\0invalid url';\nconsole.log(foo);`);
+
+ const { exitCode, stdout, stderr } = Bun.spawnSync({
+ cmd: [bunExe(), `${dir}/test.js`],
+ env: bunEnv,
+ cwd: import.meta.dir,
+ });
+ expect(exitCode).not.toBe(0);
+ expect(stderr.toString("utf8")).toContain("file://\0invalid url");
+});
+
it("file url in await import resolves", async () => {
const dir = tempDirWithFiles("fileurl", {
"index.js": "export const foo = 1;",
});
writeFileSync(`${dir}/test.js`, `const {foo} = await import('file://${dir}/index.js');\nconsole.log(foo);`);
- console.log("dir", dir);
+ const { exitCode, stdout } = Bun.spawnSync({
+ cmd: [bunExe(), `${dir}/test.js`],
+ env: bunEnv,
+ cwd: import.meta.dir,
+ });
+ expect(exitCode).toBe(0);
+ expect(stdout.toString("utf8")).toBe("1\n");
+});
+
+it("file url with special characters in await import resolves", async () => {
+ const filename = "🅱️ndex.js";
+ const dir = tempDirWithFiles("file url", {
+ [filename]: "export const foo = 1;",
+ });
+ writeFileSync(
+ `${dir}/test.js`,
+ `const {foo} = await import('file://${dir.replace(/ /g, "%20")}/${encodeURIComponent(
+ filename,
+ )}');\nconsole.log(foo);`,
+ );
+
+ const { exitCode, stdout } = Bun.spawnSync({
+ cmd: [bunExe(), `${dir}/test.js`],
+ env: bunEnv,
+ cwd: import.meta.dir,
+ });
+ expect(exitCode).toBe(0);
+ expect(stdout.toString("utf8")).toBe("1\n");
+});
+
+it("file url with special characters not encoded in await import resolves", async () => {
+ const filename = "🅱️ndex.js";
+ const dir = tempDirWithFiles("file url", {
+ [filename]: "export const foo = 1;",
+ });
+ writeFileSync(`${dir}/test.js`, `const {foo} = await import('file://${dir}/${filename}');\nconsole.log(foo);`);
+
+ const { exitCode, stdout } = Bun.spawnSync({
+ cmd: [bunExe(), `${dir}/test.js`],
+ env: bunEnv,
+ cwd: import.meta.dir,
+ });
+ expect(exitCode).toBe(0);
+ expect(stdout.toString("utf8")).toBe("1\n");
+});
+
+it("file url with special characters in import statement resolves", async () => {
+ const filename = "🅱️ndex.js";
+ const dir = tempDirWithFiles("file url", {
+ [filename]: "export const foo = 1;",
+ });
+ writeFileSync(
+ `${dir}/test.js`,
+ `import {foo} from 'file://${dir.replace(/ /g, "%20")}/${encodeURIComponent(filename)}';\nconsole.log(foo);`,
+ );
+
+ const { exitCode, stdout } = Bun.spawnSync({
+ cmd: [bunExe(), `${dir}/test.js`],
+ env: bunEnv,
+ cwd: import.meta.dir,
+ });
+ expect(exitCode).toBe(0);
+ expect(stdout.toString("utf8")).toBe("1\n");
+});
+
+it("file url with special characters not encoded in import statement resolves", async () => {
+ const filename = "🅱️ndex.js";
+ const dir = tempDirWithFiles("file url", {
+ [filename]: "export const foo = 1;",
+ });
+ writeFileSync(`${dir}/test.js`, `import {foo} from 'file://${dir}/${filename}';\nconsole.log(foo);`);
+
const { exitCode, stdout } = Bun.spawnSync({
cmd: [bunExe(), `${dir}/test.js`],
env: bunEnv,
@@ -124,7 +207,6 @@ it("file url in require resolves", async () => {
});
writeFileSync(`${dir}/test.js`, `const {foo} = require('file://${dir}/index.js');\nconsole.log(foo);`);
- console.log("dir", dir);
const { exitCode, stdout } = Bun.spawnSync({
cmd: [bunExe(), `${dir}/test.js`],
env: bunEnv,
@@ -134,6 +216,61 @@ it("file url in require resolves", async () => {
expect(stdout.toString("utf8")).toBe("1\n");
});
+it("file url with special characters in require resolves", async () => {
+ const filename = "🅱️ndex.js";
+ const dir = tempDirWithFiles("file url", {
+ [filename]: "export const foo = 1;",
+ });
+ writeFileSync(
+ `${dir}/test.js`,
+ `const {foo} = require('file://${dir.replace(/ /g, "%20")}/${encodeURIComponent(filename)}');\nconsole.log(foo);`,
+ );
+
+ const { exitCode, stdout } = Bun.spawnSync({
+ cmd: [bunExe(), `${dir}/test.js`],
+ env: bunEnv,
+ cwd: import.meta.dir,
+ });
+ expect(exitCode).toBe(0);
+ expect(stdout.toString("utf8")).toBe("1\n");
+});
+
+it("file url in require.resolve resolves", async () => {
+ const dir = tempDirWithFiles("fileurl", {
+ "index.js": "export const foo = 1;",
+ });
+ writeFileSync(`${dir}/test.js`, `const to = require.resolve('file://${dir}/index.js');\nconsole.log(to);`);
+
+ const { exitCode, stdout } = Bun.spawnSync({
+ cmd: [bunExe(), `${dir}/test.js`],
+ env: bunEnv,
+ cwd: import.meta.dir,
+ });
+ expect(exitCode).toBe(0);
+ expect(stdout.toString("utf8")).toBe(`${dir}/index.js\n`);
+});
+
+it("file url with special characters in require resolves", async () => {
+ const filename = "🅱️ndex.js";
+ const dir = tempDirWithFiles("file url", {
+ [filename]: "export const foo = 1;",
+ });
+ writeFileSync(
+ `${dir}/test.js`,
+ `const to = require.resolve('file://${dir.replace(/ /g, "%20")}/${encodeURIComponent(
+ filename,
+ )}');\nconsole.log(to);`,
+ );
+
+ const { exitCode, stdout } = Bun.spawnSync({
+ cmd: [bunExe(), `${dir}/test.js`],
+ env: bunEnv,
+ cwd: import.meta.dir,
+ });
+ expect(exitCode).toBe(0);
+ expect(stdout.toString("utf8")).toBe(`${dir}/${filename}\n`);
+});
+
it("import long string should not segfault", async () => {
try {
await import("a".repeat(10000));
diff --git a/test/js/node/net/node-net.test.ts b/test/js/node/net/node-net.test.ts
index 109391af5..a16ac6db1 100644
--- a/test/js/node/net/node-net.test.ts
+++ b/test/js/node/net/node-net.test.ts
@@ -411,3 +411,10 @@ it("should handle connection error (unix)", done => {
done();
});
});
+
+it("Socket has a prototype", () => {
+ function Connection() {}
+ function Connection2() {}
+ require("util").inherits(Connection, Socket);
+ require("util").inherits(Connection2, require("tls").TLSSocket);
+});
diff --git a/test/js/node/process/process.test.js b/test/js/node/process/process.test.js
index a4a8862a2..4fb678dce 100644
--- a/test/js/node/process/process.test.js
+++ b/test/js/node/process/process.test.js
@@ -407,7 +407,8 @@ describe("signal", () => {
stdout: "pipe",
});
const prom = child.exited;
- process.kill(child.pid, "SIGTERM");
+ const ret = process.kill(child.pid, "SIGTERM");
+ expect(ret).toBe(true);
await prom;
expect(child.signalCode).toBe("SIGTERM");
});
@@ -418,7 +419,8 @@ describe("signal", () => {
stdout: "pipe",
});
const prom = child.exited;
- process.kill(child.pid, 9);
+ const ret = process.kill(child.pid, 9);
+ expect(ret).toBe(true);
await prom;
expect(child.signalCode).toBe("SIGKILL");
});
diff --git a/test/js/web/fetch/fetch.test.ts b/test/js/web/fetch/fetch.test.ts
index 85e2296cd..8c5e27f88 100644
--- a/test/js/web/fetch/fetch.test.ts
+++ b/test/js/web/fetch/fetch.test.ts
@@ -1241,6 +1241,16 @@ describe("Request", () => {
expect(req.signal.aborted).toBe(true);
});
+ it("copies method (#6144)", () => {
+ const request = new Request("http://localhost:1337/test", {
+ method: "POST",
+ });
+ const new_req = new Request(request, {
+ body: JSON.stringify({ message: "Hello world" }),
+ });
+ expect(new_req.method).toBe("POST");
+ });
+
it("cloned signal", async () => {
gc();
const controller = new AbortController();
@@ -1692,3 +1702,95 @@ it("should throw RedirectURLTooLong when location is too long", async () => {
expect(err.code).toStrictEqual("RedirectURLTooLong");
server.stop(true);
});
+
+it("304 not modified with missing content-length does not cause a request timeout", async () => {
+ const server = await Bun.listen({
+ socket: {
+ open(socket) {
+ socket.write("HTTP/1.1 304 Not Modified\r\n\r\n");
+ socket.flush();
+ setTimeout(() => {
+ socket.end();
+ }, 9999).unref();
+ },
+ data() {},
+ close() {},
+ },
+ port: 0,
+ hostname: "localhost",
+ });
+
+ const response = await fetch(`http://${server.hostname}:${server.port}/`);
+ expect(response.status).toBe(304);
+ expect(await response.arrayBuffer()).toHaveLength(0);
+ server.stop(true);
+});
+
+it("304 not modified with missing content-length and connection close does not cause a request timeout", async () => {
+ const server = await Bun.listen({
+ socket: {
+ open(socket) {
+ socket.write("HTTP/1.1 304 Not Modified\r\nConnection: close\r\n\r\n");
+ socket.flush();
+ setTimeout(() => {
+ socket.end();
+ }, 9999).unref();
+ },
+ data() {},
+ close() {},
+ },
+ port: 0,
+ hostname: "localhost",
+ });
+
+ const response = await fetch(`http://${server.hostname}:${server.port}/`);
+ expect(response.status).toBe(304);
+ expect(await response.arrayBuffer()).toHaveLength(0);
+ server.stop(true);
+});
+
+it("304 not modified with content-length 0 and connection close does not cause a request timeout", async () => {
+ const server = await Bun.listen({
+ socket: {
+ open(socket) {
+ socket.write("HTTP/1.1 304 Not Modified\r\nConnection: close\r\nContent-Length: 0\r\n\r\n");
+ socket.flush();
+ setTimeout(() => {
+ socket.end();
+ }, 9999).unref();
+ },
+ data() {},
+ close() {},
+ },
+ port: 0,
+ hostname: "localhost",
+ });
+
+ const response = await fetch(`http://${server.hostname}:${server.port}/`);
+ expect(response.status).toBe(304);
+ expect(await response.arrayBuffer()).toHaveLength(0);
+ server.stop(true);
+});
+
+it("304 not modified with 0 content-length does not cause a request timeout", async () => {
+ const server = await Bun.listen({
+ socket: {
+ open(socket) {
+ socket.write("HTTP/1.1 304 Not Modified\r\nContent-Length: 0\r\n\r\n");
+ socket.flush();
+ setTimeout(() => {
+ socket.end();
+ }, 9999).unref();
+ },
+ data() {},
+ close() {},
+ },
+ port: 0,
+ hostname: "localhost",
+ });
+
+ const response = await fetch(`http://${server.hostname}:${server.port}/`);
+ expect(response.status).toBe(304);
+ expect(await response.arrayBuffer()).toHaveLength(0);
+ server.stop(true);
+});