Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/node/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ wd_ts_bundle(
"*.js",
"assert/*.ts",
"dns/*.ts",
"fs/*.ts",
"stream/*.js",
"path/*.ts",
"util/*.ts",
Expand Down
2 changes: 1 addition & 1 deletion src/node/diagnostics_channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ export function tracingChannel(
this[kAsyncEnd] = channel(`tracing:${nameOrChannels}:asyncEnd`);
this[kError] = channel(`tracing:${nameOrChannels}:error`);
} else {
validateObject(nameOrChannels, 'channels', {});
validateObject(nameOrChannels, 'channels');
const channels = nameOrChannels as TracingChannels;
this[kStart] = validateChannel(channels.start, 'channels.start');
this[kEnd] = validateChannel(channels.end, 'channels.end');
Expand Down
25 changes: 25 additions & 0 deletions src/node/fs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) 2017-2022 Cloudflare, Inc.
// Licensed under the Apache 2.0 license found in the LICENSE file or at:
// https://opensource.org/licenses/Apache-2.0

import * as promises from 'node-internal:internal_fs_promises';
import * as constants from 'node-internal:internal_fs_constants';
import * as syncMethods from 'node-internal:internal_fs_sync';
import * as callbackMethods from 'node-internal:internal_fs_callback';
import { WriteStream, ReadStream } from 'node-internal:internal_fs_streams';
import { Dirent, Dir } from 'node-internal:internal_fs';

export * from 'node-internal:internal_fs_callback';
export * from 'node-internal:internal_fs_sync';
export { constants, promises, Dirent, Dir, WriteStream, ReadStream };

export default {
constants,
promises,
Dirent,
Dir,
WriteStream,
ReadStream,
...syncMethods,
...callbackMethods,
};
14 changes: 14 additions & 0 deletions src/node/fs/promises.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) 2017-2022 Cloudflare, Inc.
// Licensed under the Apache 2.0 license found in the LICENSE file or at:
// https://opensource.org/licenses/Apache-2.0

import * as fs from 'node-internal:internal_fs_promises';
import * as constants from 'node-internal:internal_fs_constants';

export * from 'node-internal:internal_fs_promises';
export { constants };

export default {
constants,
...fs,
};
4 changes: 2 additions & 2 deletions src/node/internal/crypto_keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ function validateExportOptions(
type: KeyObjectType,
name = 'options'
): asserts options is ExportOptions {
validateObject(options, name, {});
validateObject(options, name);
// Yes, converting to any is a bit of a cheat, but it allows us to check
// each option individually without having to do a bunch of type guards.
const opts = options;
Expand Down Expand Up @@ -182,7 +182,7 @@ export abstract class KeyObject {
}

public export(options: ExportOptions = {}): KeyExportResult {
validateObject(options, 'options', {});
validateObject(options, 'options');

validateExportOptions(options, this.type);

Expand Down
6 changes: 3 additions & 3 deletions src/node/internal/crypto_random.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ function processGeneratePrimeOptions(options: GeneratePrimeOptions): {
safe: boolean;
bigint: boolean;
} {
validateObject(options, 'options', {});
validateObject(options, 'options');
const { safe = false, bigint = false } = options;
let { add, rem } = options;
validateBoolean(safe, 'options.safe');
Expand Down Expand Up @@ -427,7 +427,7 @@ export function checkPrimeSync(
options: CheckPrimeOptions = {}
): boolean {
candidate = validateCandidate(candidate);
validateObject(options, 'options', {});
validateObject(options, 'options');
const checks = validateChecks(options);
return cryptoImpl.checkPrimeSync(candidate as ArrayBufferView, checks);
}
Expand All @@ -451,7 +451,7 @@ export function checkPrime(
callback = options;
options = {};
}
validateObject(options, 'options', {});
validateObject(options, 'options');
validateFunction(callback, 'callback');
const checks = validateChecks(options);
new Promise<boolean>((res, rej) => {
Expand Down
94 changes: 94 additions & 0 deletions src/node/internal/filesystem.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
export interface StatOptions {
followSymlinks?: boolean;
}

export interface Stat {
type: 'file' | 'directory' | 'symlink';
size: number;
lastModified: bigint;
created: bigint;
writable: boolean;
device: boolean;
}

export function stat(pathOrFd: number | URL, options: StatOptions): Stat | null;
export function setLastModified(
pathOrFd: number | URL,
mtime: Date,
options: StatOptions
): void;

export function truncate(pathOrFd: number | URL, length: number): void;

export function readLink(
path: URL,
options: { failIfNotSymlink: boolean }
): string;

export function link(from: URL, to: URL, options: { symbolic: boolean }): void;

export function unlink(path: URL): void;

export function open(
path: URL,
options: {
read: boolean;
write: boolean;
append: boolean;
exclusive: boolean;
followSymlinks: boolean;
}
): number;

export function close(fd: number): void;

export function write(
fd: number,
buffers: ArrayBufferView[],
options: {
position: number | bigint | null;
}
): number;

export function read(
fd: number,
buffers: ArrayBufferView[],
options: {
position: number | bigint | null;
}
): number;

export function readAll(pathOrFd: number | URL): Uint8Array;

export function writeAll(
pathOrFd: number | URL,
data: ArrayBufferView,
options: { append: boolean; exclusive: boolean }
): number;

export function renameOrCopy(
from: URL,
to: URL,
options: { copy: boolean }
): void;

export function mkdir(
path: URL,
options: { recursive: boolean; tmp: boolean }
): string | undefined;

export function rm(
path: URL,
options: { recursive: boolean; force: boolean; dironly: boolean }
): void;

export interface DirEntryHandle {
name: string;
parentPath: string;
type: number;
}

export function readdir(
path: URL,
options: { recursive: boolean }
): DirEntryHandle[];
42 changes: 42 additions & 0 deletions src/node/internal/internal_errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -817,3 +817,45 @@ export class ERR_INVALID_CHAR extends NodeTypeError {
super('ERR_INVALID_CHAR', msg);
}
}

export class NodeFsError extends NodeError {
syscall: string;
path?: string;
constructor(code: string, message: string, syscall: string) {
super(code, message);
this.syscall = syscall;
}
}

export class NodeSyscallError extends NodeError {
syscall: string;
errno?: number;
constructor(code: string, message: string, syscall: string) {
super(code, message);
this.syscall = syscall;
}
}

export class ERR_ENOENT extends NodeFsError {
constructor(path: string, options: { syscall: string }) {
super('ENOENT', `No such file or directory: ${path}`, options.syscall);
this.code = 'ENOENT';
this.path = path;
}
}

export class ERR_EBADF extends NodeSyscallError {
constructor(options: { syscall: string }) {
super('EBADF', `Bad file descriptor`, options.syscall);
this.code = 'EBADF';
this.errno = -9; // EBADF
}
}

export class ERR_EINVAL extends NodeSyscallError {
constructor(options: { syscall: string }) {
super('EINVAL', `Invalid argument`, options.syscall);
this.code = 'EINVAL';
this.errno = -22; // EINVAL
}
}
115 changes: 115 additions & 0 deletions src/node/internal/internal_fs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import {
UV_DIRENT_DIR,
UV_DIRENT_FILE,
UV_DIRENT_BLOCK,
UV_DIRENT_CHAR,
UV_DIRENT_LINK,
UV_DIRENT_FIFO,
UV_DIRENT_SOCKET,
} from 'node-internal:internal_fs_constants';
import { getOptions } from 'node-internal:internal_fs_utils';
import { validateFunction, validateUint32 } from 'node-internal:validators';
import { ERR_MISSING_ARGS } from 'node-internal:internal_errors';

const kType = Symbol('type');

export class Dirent {
public name: string;
public parentPath: string;
private [kType]: number;

public constructor(name: string, type: number, path: string) {
this.name = name;
this.parentPath = path;
this[kType] = type;
}

public isDirectory(): boolean {
return this[kType] === UV_DIRENT_DIR;
}

public isFile(): boolean {
return this[kType] === UV_DIRENT_FILE;
}

public isBlockDevice(): boolean {
return this[kType] === UV_DIRENT_BLOCK;
}

public isCharacterDevice(): boolean {
return this[kType] === UV_DIRENT_CHAR;
}

public isSymbolicLink(): boolean {
return this[kType] === UV_DIRENT_LINK;
}

public isFIFO(): boolean {
return this[kType] === UV_DIRENT_FIFO;
}

public isSocket(): boolean {
return this[kType] === UV_DIRENT_SOCKET;
}
}

export class Dir {
// @ts-expect-error TS6133 Value is not read.
#handle: unknown; // eslint-disable-line no-unused-private-class-members
#path: string;
#options: Record<string, unknown>;

public constructor(
handle: unknown,
path: string,
options: Record<string, unknown>
) {
if (handle == null) {
throw new ERR_MISSING_ARGS('handle');
}
this.#handle = handle;
this.#path = path;
this.#options = {
bufferSize: 32,
...getOptions(options, {
encoding: 'utf8',
}),
};

validateUint32(this.#options.bufferSize, 'options.bufferSize', true);
}

public get path(): string {
return this.#path;
}

public read(callback: unknown): void {
validateFunction(callback, 'callback');
throw new Error('Not implemented');
}

public processReadResult(): void {
throw new Error('Not implemented');
}

public readSyncRecursive(): void {
throw new Error('Not implemented');
}

public readSync(): void {
throw new Error('Not implemented');
}

public close(): void {
throw new Error('Not implemented');
}

public closeSync(): void {
throw new Error('Not implemented');
}

// eslint-disable-next-line @typescript-eslint/require-await,require-yield
public async *entries(): AsyncGenerator<unknown, unknown, unknown> {
throw new Error('Not implemented');
}
}
Loading