aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Colin McDonnell <colinmcd94@gmail.com> 2023-03-02 17:36:47 -0800
committerGravatar GitHub <noreply@github.com> 2023-03-02 17:36:47 -0800
commitb469e5035161286abeb1a7726518d1afcc163a51 (patch)
tree2eb8c1e1e4d1adf726888b39d1c6f43795c65a1a
parent27c35791185bd85337e312e12c87d5c22d7f3a52 (diff)
downloadbun-b469e5035161286abeb1a7726518d1afcc163a51.tar.gz
bun-b469e5035161286abeb1a7726518d1afcc163a51.tar.zst
bun-b469e5035161286abeb1a7726518d1afcc163a51.zip
Add fs/promises tests and migrate fs.test.js to TypeScript (#2279)
-rw-r--r--packages/bun-types/bun.d.ts36
-rw-r--r--packages/bun-types/fs.d.ts7
-rw-r--r--packages/bun-types/fs/promises.d.ts37
-rw-r--r--packages/bun-types/tests/fs.test-d.ts6
-rw-r--r--test/bun.js/event-emitter.test.ts2
-rw-r--r--test/bun.js/fs.test.ts (renamed from test/bun.js/fs.test.js)53
-rw-r--r--test/bun.js/gc.ts (renamed from test/bun.js/gc.js)4
7 files changed, 103 insertions, 42 deletions
diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts
index 8f020dcfc..fc3bcbdb1 100644
--- a/packages/bun-types/bun.d.ts
+++ b/packages/bun-types/bun.d.ts
@@ -395,7 +395,9 @@ declare module "bun" {
stream?: boolean;
}): void;
- write(chunk: string | ArrayBufferView | ArrayBuffer): number;
+ write(
+ chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
+ ): number;
/**
* Flush the internal buffer
*
@@ -534,7 +536,9 @@ declare module "bun" {
*
* If the file descriptor is not writable yet, the data is buffered.
*/
- write(chunk: string | ArrayBufferView | ArrayBuffer): number;
+ write(
+ chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
+ ): number;
/**
* Flush the internal buffer, committing the data to disk or the pipe.
*/
@@ -650,38 +654,38 @@ declare module "bun" {
* @param seed The seed to use.
*/
export const hash: ((
- data: string | ArrayBufferView | ArrayBuffer,
+ data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
seed?: number,
) => number | bigint) &
Hash;
interface Hash {
wyhash: (
- data: string | ArrayBufferView | ArrayBuffer,
+ data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
seed?: number,
) => number | bigint;
crc32: (
- data: string | ArrayBufferView | ArrayBuffer,
+ data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
seed?: number,
) => number | bigint;
adler32: (
- data: string | ArrayBufferView | ArrayBuffer,
+ data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
seed?: number,
) => number | bigint;
cityHash32: (
- data: string | ArrayBufferView | ArrayBuffer,
+ data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
seed?: number,
) => number | bigint;
cityHash64: (
- data: string | ArrayBufferView | ArrayBuffer,
+ data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
seed?: number,
) => number | bigint;
murmur32v3: (
- data: string | ArrayBufferView | ArrayBuffer,
+ data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
seed?: number,
) => number | bigint;
murmur64v2: (
- data: string | ArrayBufferView | ArrayBuffer,
+ data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
seed?: number,
) => number | bigint;
}
@@ -989,7 +993,7 @@ declare module "bun" {
*
*/
send(
- data: string | ArrayBufferView | ArrayBuffer,
+ data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
compress?: boolean,
): ServerWebSocketSendStatus;
@@ -1101,7 +1105,7 @@ declare module "bun" {
*/
publish(
topic: string,
- data: string | ArrayBufferView | ArrayBuffer,
+ data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
compress?: boolean,
): ServerWebSocketSendStatus;
@@ -1739,7 +1743,7 @@ declare module "bun" {
*/
publish(
topic: string,
- data: string | ArrayBufferView | ArrayBuffer,
+ data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
compress?: boolean,
): ServerWebSocketSendStatus;
@@ -1944,7 +1948,7 @@ declare module "bun" {
* @param level
* @returns The previous level
*/
- gcAggressionLevel(level: 0 | 1 | 2): 0 | 1 | 2;
+ gcAggressionLevel(level?: 0 | 1 | 2): 0 | 1 | 2;
}
export const unsafe: unsafe;
@@ -2474,7 +2478,7 @@ declare module "bun" {
/**
* The source code of the module
*/
- contents: string | ArrayBufferView | ArrayBuffer;
+ contents: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer;
/**
* The loader to use for this file
*
@@ -3349,7 +3353,7 @@ type TimeLike = string | number | Date;
type StringOrBuffer = string | TypedArray | ArrayBufferLike;
type PathLike = string | TypedArray | ArrayBufferLike | URL;
type PathOrFileDescriptor = PathLike | number;
-type NoParamCallback = VoidFunction;
+type NoParamCallback = (err: ErrnoException | null) => void;
type BufferEncoding =
| "buffer"
| "utf8"
diff --git a/packages/bun-types/fs.d.ts b/packages/bun-types/fs.d.ts
index 7e34d5873..14c5c1d1d 100644
--- a/packages/bun-types/fs.d.ts
+++ b/packages/bun-types/fs.d.ts
@@ -20,10 +20,11 @@
declare module "fs" {
import * as stream from "stream";
import type { SystemError, ArrayBufferView } from "bun";
-
interface ObjectEncodingOptions {
encoding?: BufferEncoding | null | undefined;
}
+
+ const promises: Awaited<typeof import("fs/promises")>;
type EncodingOption =
| ObjectEncodingOptions
| BufferEncoding
@@ -1517,6 +1518,7 @@ declare module "fs" {
* See the POSIX [`mkdir(2)`](http://man7.org/linux/man-pages/man2/mkdir.2.html) documentation for more details.
* @since v0.0.67
*/
+
function mkdirSync(
path: PathLike,
options: MakeDirectoryOptions & {
@@ -3930,6 +3932,5 @@ declare module "fs" {
}
declare module "node:fs" {
- import * as fs from "fs";
- export = fs;
+ export * from "fs";
}
diff --git a/packages/bun-types/fs/promises.d.ts b/packages/bun-types/fs/promises.d.ts
index 164ef8db9..997896b01 100644
--- a/packages/bun-types/fs/promises.d.ts
+++ b/packages/bun-types/fs/promises.d.ts
@@ -9,7 +9,7 @@
*/
declare module "fs/promises" {
import { ArrayBufferView } from "bun";
- import {
+ import type {
Stats,
BigIntStats,
StatOptions,
@@ -25,6 +25,7 @@ declare module "fs/promises" {
SimlinkType,
Abortable,
RmOptions,
+ RmDirOptions,
} from "node:fs";
interface FlagAndOpenMode {
@@ -677,9 +678,39 @@ declare module "fs/promises" {
* @since v14.14.0
*/
export function rm(path: PathLike, options?: RmOptions): Promise<void>;
+
+ /**
+ * Asynchronously test whether or not the given path exists by checking with the file system.
+ *
+ * ```ts
+ * import { exists } from 'fs/promises';
+ *
+ * const e = await exists('/etc/passwd');
+ * e; // boolean
+ * ```
+ */
+ function exists(path: PathLike): Promise<boolean>;
+
+ /**
+ * @deprecated Use `fs.promises.rm()` instead.
+ *
+ * Asynchronously remove a directory.
+ *
+ * ```ts
+ * import { rmdir } from 'fs/promises';
+ *
+ * // remove a directory
+ * await rmdir('/tmp/mydir'); // Promise<void>
+ * ```
+ *
+ * To remove a directory recursively, use `fs.promises.rm()` instead, with the `recursive` option set to `true`.
+ */
+ function rmdir(
+ path: PathLike,
+ options?: Omit<RmDirOptions, "recursive">,
+ ): Promise<void>;
}
declare module "node:fs/promises" {
- import * as fsPromises from "fs/promises";
- export = fsPromises;
+ export * from "fs/promises";
}
diff --git a/packages/bun-types/tests/fs.test-d.ts b/packages/bun-types/tests/fs.test-d.ts
new file mode 100644
index 000000000..1ef14a2f8
--- /dev/null
+++ b/packages/bun-types/tests/fs.test-d.ts
@@ -0,0 +1,6 @@
+import * as tsd from "tsd";
+import * as fs from "fs";
+import { exists } from "fs/promises";
+
+tsd.expectType<Promise<boolean>>(exists("/etc/passwd"));
+tsd.expectType<Promise<boolean>>(fs.promises.exists("/etc/passwd"));
diff --git a/test/bun.js/event-emitter.test.ts b/test/bun.js/event-emitter.test.ts
index cd1eaeaf2..2bb891778 100644
--- a/test/bun.js/event-emitter.test.ts
+++ b/test/bun.js/event-emitter.test.ts
@@ -150,7 +150,7 @@ test("EventEmitter GCs", () => {
(function () {
Bun.gc(true);
- function EventEmitterSubclass() {
+ function EventEmitterSubclass(this: any) {
EventEmitter.call(this);
}
diff --git a/test/bun.js/fs.test.js b/test/bun.js/fs.test.ts
index ce5209c53..4c847d25a 100644
--- a/test/bun.js/fs.test.js
+++ b/test/bun.js/fs.test.ts
@@ -26,6 +26,9 @@ import fs, {
Dirent,
Stats,
} from "node:fs";
+
+import _promises from "node:fs/promises";
+
import { tmpdir } from "node:os";
import { join } from "node:path";
@@ -49,7 +52,7 @@ describe("copyFileSync", () => {
it("should work for files < 128 KB", () => {
const tempdir = `/tmp/fs.test.js/${Date.now()}/1234/hi`;
expect(existsSync(tempdir)).toBe(false);
- expect(tempdir.includes(mkdirSync(tempdir, { recursive: true }))).toBe(true);
+ expect(tempdir.includes(mkdirSync(tempdir, { recursive: true })!)).toBe(true);
// that don't exist
copyFileSync(import.meta.path, tempdir + "/copyFileSync.js");
@@ -67,7 +70,7 @@ describe("copyFileSync", () => {
it("should work for files > 128 KB ", () => {
const tempdir = `/tmp/fs.test.js/${Date.now()}-1/1234/hi`;
expect(existsSync(tempdir)).toBe(false);
- expect(tempdir.includes(mkdirSync(tempdir, { recursive: true }))).toBe(true);
+ expect(tempdir.includes(mkdirSync(tempdir, { recursive: true })!)).toBe(true);
var buffer = new Int32Array(128 * 1024);
for (let i = 0; i < buffer.length; i++) {
buffer[i] = i % 256;
@@ -92,7 +95,7 @@ describe("mkdirSync", () => {
it("should create a directory", () => {
const tempdir = `/tmp/fs.test.js/${Date.now()}/1234/hi`;
expect(existsSync(tempdir)).toBe(false);
- expect(tempdir.includes(mkdirSync(tempdir, { recursive: true }))).toBe(true);
+ expect(tempdir.includes(mkdirSync(tempdir, { recursive: true })!)).toBe(true);
expect(existsSync(tempdir)).toBe(true);
});
});
@@ -135,6 +138,7 @@ it("mkdtempSync, readdirSync, rmdirSync and unlinkSync with non-ascii", () => {
});
it("mkdtempSync() empty name", () => {
+ // @ts-ignore-next-line
const tempdir = mkdtempSync();
expect(existsSync(tempdir)).toBe(true);
writeFileSync(tempdir + "/non-ascii-👍.txt", "hello");
@@ -188,7 +192,7 @@ it("readdirSync throws when given a file path", () => {
try {
readdirSync(import.meta.path);
throw new Error("should not get here");
- } catch (exception) {
+ } catch (exception: any) {
expect(exception.name).toBe("ENOTDIR");
}
});
@@ -197,7 +201,7 @@ it("readdirSync throws when given a path that doesn't exist", () => {
try {
readdirSync(import.meta.path + "/does-not-exist/really");
throw new Error("should not get here");
- } catch (exception) {
+ } catch (exception: any) {
expect(exception.name).toBe("ENOTDIR");
}
});
@@ -206,7 +210,7 @@ it("readdirSync throws when given a file path with trailing slash", () => {
try {
readdirSync(import.meta.path + "/");
throw new Error("should not get here");
- } catch (exception) {
+ } catch (exception: any) {
expect(exception.name).toBe("ENOTDIR");
}
});
@@ -455,7 +459,7 @@ describe("stat", () => {
try {
statSync("/tmp/doesntexist");
throw "statSync should throw";
- } catch (e) {
+ } catch (e: any) {
expect(e.code).toBe("ENOENT");
}
});
@@ -499,8 +503,8 @@ describe("rmdir", () => {
rmdir(path, err => {
try {
expect(err).toBeDefined();
- expect(err.code).toBe("EPERM");
- expect(err.message).toBe("Operation not permitted");
+ expect(err!.code).toBe("EPERM");
+ expect(err!.message).toBe("Operation not permitted");
expect(existsSync(path)).toBe(true);
} catch (e) {
return done(e);
@@ -621,6 +625,7 @@ describe("fs.WriteStream", () => {
});
it("should be constructable", () => {
+ // @ts-ignore-next-line
const stream = new fs.WriteStream("test.txt");
expect(stream instanceof fs.WriteStream).toBe(true);
});
@@ -630,6 +635,7 @@ describe("fs.WriteStream", () => {
mkdirForce(pathToDir);
const path = join(pathToDir, `fs-writestream-test.txt`);
+ // @ts-ignore-next-line
const stream = new fs.WriteStream(path, { flags: "w+" });
stream.write("Test file written successfully");
stream.end();
@@ -645,6 +651,7 @@ describe("fs.WriteStream", () => {
});
it("should work if re-exported by name", () => {
+ // @ts-ignore-next-line
const stream = new WriteStream_("test.txt");
expect(stream instanceof WriteStream_).toBe(true);
expect(stream instanceof WriteStreamStar_).toBe(true);
@@ -652,6 +659,7 @@ describe("fs.WriteStream", () => {
});
it("should work if re-exported by name, called without new", () => {
+ // @ts-ignore-next-line
const stream = WriteStream_("test.txt");
expect(stream instanceof WriteStream_).toBe(true);
expect(stream instanceof WriteStreamStar_).toBe(true);
@@ -659,6 +667,7 @@ describe("fs.WriteStream", () => {
});
it("should work if re-exported, as export * from ...", () => {
+ // @ts-ignore-next-line
const stream = new WriteStreamStar_("test.txt");
expect(stream instanceof WriteStream_).toBe(true);
expect(stream instanceof WriteStreamStar_).toBe(true);
@@ -666,6 +675,7 @@ describe("fs.WriteStream", () => {
});
it("should work if re-exported, as export * from..., called without new", () => {
+ // @ts-ignore-next-line
const stream = WriteStreamStar_("test.txt");
expect(stream instanceof WriteStream_).toBe(true);
expect(stream instanceof WriteStreamStar_).toBe(true);
@@ -676,7 +686,7 @@ describe("fs.WriteStream", () => {
const pathToDir = `${tmpdir()}/${Date.now()}`;
mkdirForce(pathToDir);
const path = join(pathToDir, `fs-writestream-re-exported-test.txt`);
-
+ // @ts-ignore-next-line
const stream = new WriteStream_(path, { flags: "w+" });
stream.write("Test file written successfully");
stream.end();
@@ -698,6 +708,7 @@ describe("fs.ReadStream", () => {
});
it("should be constructable", () => {
+ // @ts-ignore-next-line
const stream = new fs.ReadStream("test.txt");
expect(stream instanceof fs.ReadStream).toBe(true);
});
@@ -711,7 +722,7 @@ describe("fs.ReadStream", () => {
encoding: "utf8",
flag: "w+",
});
-
+ // @ts-ignore-next-line
const stream = new fs.ReadStream(path);
stream.setEncoding("utf8");
stream.on("error", e => {
@@ -731,6 +742,7 @@ describe("fs.ReadStream", () => {
});
it("should work if re-exported by name", () => {
+ // @ts-ignore-next-line
const stream = new ReadStream_("test.txt");
expect(stream instanceof ReadStream_).toBe(true);
expect(stream instanceof ReadStreamStar_).toBe(true);
@@ -738,6 +750,7 @@ describe("fs.ReadStream", () => {
});
it("should work if re-exported by name, called without new", () => {
+ // @ts-ignore-next-line
const stream = ReadStream_("test.txt");
expect(stream instanceof ReadStream_).toBe(true);
expect(stream instanceof ReadStreamStar_).toBe(true);
@@ -745,6 +758,7 @@ describe("fs.ReadStream", () => {
});
it("should work if re-exported as export * from ...", () => {
+ // @ts-ignore-next-line
const stream = new ReadStreamStar_("test.txt");
expect(stream instanceof ReadStreamStar_).toBe(true);
expect(stream instanceof ReadStream_).toBe(true);
@@ -752,6 +766,7 @@ describe("fs.ReadStream", () => {
});
it("should work if re-exported as export * from ..., called without new", () => {
+ // @ts-ignore-next-line
const stream = ReadStreamStar_("test.txt");
expect(stream instanceof ReadStreamStar_).toBe(true);
expect(stream instanceof ReadStream_).toBe(true);
@@ -768,6 +783,7 @@ describe("fs.ReadStream", () => {
flag: "w+",
});
+ // @ts-ignore-next-line
const stream = new ReadStream_(path);
stream.setEncoding("utf8");
stream.on("error", e => {
@@ -812,7 +828,7 @@ describe("createWriteStream", () => {
try {
stream.write(null);
expect(() => {}).toThrow(Error);
- } catch (exception) {
+ } catch (exception: any) {
expect(exception.code).toBe("ERR_STREAM_NULL_VALUES");
}
});
@@ -820,12 +836,13 @@ describe("createWriteStream", () => {
it("writing null throws ERR_STREAM_NULL_VALUES (objectMode: true)", async () => {
const path = `/tmp/fs.test.js/${Date.now()}.createWriteStreamNulls.txt`;
const stream = createWriteStream(path, {
+ // @ts-ignore-next-line
objectMode: true,
});
try {
stream.write(null);
expect(() => {}).toThrow(Error);
- } catch (exception) {
+ } catch (exception: any) {
expect(exception.code).toBe("ERR_STREAM_NULL_VALUES");
}
});
@@ -836,7 +853,7 @@ describe("createWriteStream", () => {
try {
stream.write(false);
expect(() => {}).toThrow(Error);
- } catch (exception) {
+ } catch (exception: any) {
expect(exception.code).toBe("ERR_INVALID_ARG_TYPE");
}
});
@@ -844,12 +861,13 @@ describe("createWriteStream", () => {
it("writing false throws ERR_INVALID_ARG_TYPE (objectMode: true)", async () => {
const path = `/tmp/fs.test.js/${Date.now()}.createWriteStreamFalse.txt`;
const stream = createWriteStream(path, {
+ // @ts-ignore-next-line
objectMode: true,
});
try {
stream.write(false);
expect(() => {}).toThrow(Error);
- } catch (exception) {
+ } catch (exception: any) {
expect(exception.code).toBe("ERR_INVALID_ARG_TYPE");
}
});
@@ -893,7 +911,7 @@ describe("fs/promises", () => {
for (const args of fizz) {
try {
// check it doens't segfault when called with invalid arguments
- await promises.readdir(...args);
+ await promises.readdir(...(args as [any, ...any[]]));
} catch (e) {
// check that producing the error doesn't cause any crashes
Bun.inspect(e);
@@ -909,7 +927,7 @@ describe("fs/promises", () => {
try {
await rmdir(path);
expect(() => {}).toThrow();
- } catch (err) {
+ } catch (err: any) {
expect(err.code).toBe("ENOTDIR");
// expect(err.message).toBe("Operation not permitted");
expect(await exists(path)).toBe(true);
@@ -992,6 +1010,7 @@ it("fs.Stats", () => {
it("repro 1516: can use undefined/null to specify default flag", () => {
const path = "/tmp/repro_1516.txt";
writeFileSync(path, "b", { flag: undefined });
+ // @ts-ignore-next-line
expect(readFileSync(path, { encoding: "utf8", flag: null })).toBe("b");
rmSync(path);
});
diff --git a/test/bun.js/gc.js b/test/bun.js/gc.ts
index 3f9678f92..b9d80116d 100644
--- a/test/bun.js/gc.js
+++ b/test/bun.js/gc.ts
@@ -1,5 +1,5 @@
-export function gc() {
- Bun.gc(true);
+export function gc(force: boolean = true) {
+ Bun.gc(force);
}
// we must ensure that finalizers are run