mirror of
https://github.com/denoland/deno.git
synced 2025-09-26 12:19:12 +00:00
refactor: Add "deno_fs" extension crate (#18040)
This commit factors out APIs related to file system from "runtime/" to a separate "deno_fs" extension crate.
This commit is contained in:
parent
64354f4112
commit
fe368b72c1
18 changed files with 179 additions and 19 deletions
|
@ -1,899 +0,0 @@
|
|||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
const core = globalThis.Deno.core;
|
||||
const ops = core.ops;
|
||||
const primordials = globalThis.__bootstrap.primordials;
|
||||
const {
|
||||
ArrayPrototypeFilter,
|
||||
Date,
|
||||
DatePrototype,
|
||||
Error,
|
||||
Function,
|
||||
MathTrunc,
|
||||
ObjectEntries,
|
||||
ObjectPrototypeIsPrototypeOf,
|
||||
ObjectValues,
|
||||
SymbolAsyncIterator,
|
||||
SymbolIterator,
|
||||
Uint32Array,
|
||||
} = primordials;
|
||||
import { read, readSync, write, writeSync } from "internal:deno_io/12_io.js";
|
||||
import * as abortSignal from "internal:deno_web/03_abort_signal.js";
|
||||
import {
|
||||
readableStreamForRid,
|
||||
ReadableStreamPrototype,
|
||||
writableStreamForRid,
|
||||
} from "internal:deno_web/06_streams.js";
|
||||
import { pathFromURL } from "internal:deno_web/00_infra.js";
|
||||
|
||||
function chmodSync(path, mode) {
|
||||
ops.op_chmod_sync(pathFromURL(path), mode);
|
||||
}
|
||||
|
||||
async function chmod(path, mode) {
|
||||
await core.opAsync("op_chmod_async", pathFromURL(path), mode);
|
||||
}
|
||||
|
||||
function chownSync(
|
||||
path,
|
||||
uid,
|
||||
gid,
|
||||
) {
|
||||
ops.op_chown_sync(pathFromURL(path), uid, gid);
|
||||
}
|
||||
|
||||
async function chown(
|
||||
path,
|
||||
uid,
|
||||
gid,
|
||||
) {
|
||||
await core.opAsync(
|
||||
"op_chown_async",
|
||||
pathFromURL(path),
|
||||
uid,
|
||||
gid,
|
||||
);
|
||||
}
|
||||
|
||||
function copyFileSync(
|
||||
fromPath,
|
||||
toPath,
|
||||
) {
|
||||
ops.op_copy_file_sync(
|
||||
pathFromURL(fromPath),
|
||||
pathFromURL(toPath),
|
||||
);
|
||||
}
|
||||
|
||||
async function copyFile(
|
||||
fromPath,
|
||||
toPath,
|
||||
) {
|
||||
await core.opAsync(
|
||||
"op_copy_file_async",
|
||||
pathFromURL(fromPath),
|
||||
pathFromURL(toPath),
|
||||
);
|
||||
}
|
||||
|
||||
function cwd() {
|
||||
return ops.op_cwd();
|
||||
}
|
||||
|
||||
function chdir(directory) {
|
||||
ops.op_chdir(pathFromURL(directory));
|
||||
}
|
||||
|
||||
function makeTempDirSync(options = {}) {
|
||||
return ops.op_make_temp_dir_sync(options);
|
||||
}
|
||||
|
||||
function makeTempDir(options = {}) {
|
||||
return core.opAsync("op_make_temp_dir_async", options);
|
||||
}
|
||||
|
||||
function makeTempFileSync(options = {}) {
|
||||
return ops.op_make_temp_file_sync(options);
|
||||
}
|
||||
|
||||
function makeTempFile(options = {}) {
|
||||
return core.opAsync("op_make_temp_file_async", options);
|
||||
}
|
||||
|
||||
function mkdirArgs(path, options) {
|
||||
const args = { path: pathFromURL(path), recursive: false };
|
||||
if (options != null) {
|
||||
if (typeof options.recursive == "boolean") {
|
||||
args.recursive = options.recursive;
|
||||
}
|
||||
if (options.mode) {
|
||||
args.mode = options.mode;
|
||||
}
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
function mkdirSync(path, options) {
|
||||
ops.op_mkdir_sync(mkdirArgs(path, options));
|
||||
}
|
||||
|
||||
async function mkdir(
|
||||
path,
|
||||
options,
|
||||
) {
|
||||
await core.opAsync("op_mkdir_async", mkdirArgs(path, options));
|
||||
}
|
||||
|
||||
function readDirSync(path) {
|
||||
return ops.op_read_dir_sync(pathFromURL(path))[
|
||||
SymbolIterator
|
||||
]();
|
||||
}
|
||||
|
||||
function readDir(path) {
|
||||
const array = core.opAsync(
|
||||
"op_read_dir_async",
|
||||
pathFromURL(path),
|
||||
);
|
||||
return {
|
||||
async *[SymbolAsyncIterator]() {
|
||||
yield* await array;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function readLinkSync(path) {
|
||||
return ops.op_read_link_sync(pathFromURL(path));
|
||||
}
|
||||
|
||||
function readLink(path) {
|
||||
return core.opAsync("op_read_link_async", pathFromURL(path));
|
||||
}
|
||||
|
||||
function realPathSync(path) {
|
||||
return ops.op_realpath_sync(pathFromURL(path));
|
||||
}
|
||||
|
||||
function realPath(path) {
|
||||
return core.opAsync("op_realpath_async", pathFromURL(path));
|
||||
}
|
||||
|
||||
function removeSync(
|
||||
path,
|
||||
options = {},
|
||||
) {
|
||||
ops.op_remove_sync(
|
||||
pathFromURL(path),
|
||||
!!options.recursive,
|
||||
);
|
||||
}
|
||||
|
||||
async function remove(
|
||||
path,
|
||||
options = {},
|
||||
) {
|
||||
await core.opAsync(
|
||||
"op_remove_async",
|
||||
pathFromURL(path),
|
||||
!!options.recursive,
|
||||
);
|
||||
}
|
||||
|
||||
function renameSync(oldpath, newpath) {
|
||||
ops.op_rename_sync(
|
||||
pathFromURL(oldpath),
|
||||
pathFromURL(newpath),
|
||||
);
|
||||
}
|
||||
|
||||
async function rename(oldpath, newpath) {
|
||||
await core.opAsync(
|
||||
"op_rename_async",
|
||||
pathFromURL(oldpath),
|
||||
pathFromURL(newpath),
|
||||
);
|
||||
}
|
||||
|
||||
// Extract the FsStat object from the encoded buffer.
|
||||
// See `runtime/ops/fs.rs` for the encoder.
|
||||
//
|
||||
// This is not a general purpose decoder. There are 4 types:
|
||||
//
|
||||
// 1. date
|
||||
// offset += 4
|
||||
// 1/0 | extra padding | high u32 | low u32
|
||||
// if date[0] == 1, new Date(u64) else null
|
||||
//
|
||||
// 2. bool
|
||||
// offset += 2
|
||||
// 1/0 | extra padding
|
||||
//
|
||||
// 3. u64
|
||||
// offset += 2
|
||||
// high u32 | low u32
|
||||
//
|
||||
// 4. ?u64 converts a zero u64 value to JS null on Windows.
|
||||
function createByteStruct(types) {
|
||||
// types can be "date", "bool" or "u64".
|
||||
// `?` prefix means optional on windows.
|
||||
let offset = 0;
|
||||
let str =
|
||||
'const unix = Deno.build.os === "darwin" || Deno.build.os === "linux"; return {';
|
||||
const typeEntries = ObjectEntries(types);
|
||||
for (let i = 0; i < typeEntries.length; ++i) {
|
||||
let { 0: name, 1: type } = typeEntries[i];
|
||||
|
||||
const optional = type.startsWith("?");
|
||||
if (optional) type = type.slice(1);
|
||||
|
||||
if (type == "u64") {
|
||||
if (!optional) {
|
||||
str += `${name}: view[${offset}] + view[${offset + 1}] * 2**32,`;
|
||||
} else {
|
||||
str += `${name}: (unix ? (view[${offset}] + view[${
|
||||
offset + 1
|
||||
}] * 2**32) : (view[${offset}] + view[${
|
||||
offset + 1
|
||||
}] * 2**32) || null),`;
|
||||
}
|
||||
} else if (type == "date") {
|
||||
str += `${name}: view[${offset}] === 0 ? null : new Date(view[${
|
||||
offset + 2
|
||||
}] + view[${offset + 3}] * 2**32),`;
|
||||
offset += 2;
|
||||
} else {
|
||||
str += `${name}: !!(view[${offset}] + view[${offset + 1}] * 2**32),`;
|
||||
}
|
||||
offset += 2;
|
||||
}
|
||||
str += "};";
|
||||
// ...so you don't like eval huh? don't worry, it only executes during snapshot :)
|
||||
return [new Function("view", str), new Uint32Array(offset)];
|
||||
}
|
||||
|
||||
const { 0: statStruct, 1: statBuf } = createByteStruct({
|
||||
isFile: "bool",
|
||||
isDirectory: "bool",
|
||||
isSymlink: "bool",
|
||||
size: "u64",
|
||||
mtime: "date",
|
||||
atime: "date",
|
||||
birthtime: "date",
|
||||
dev: "?u64",
|
||||
ino: "?u64",
|
||||
mode: "?u64",
|
||||
nlink: "?u64",
|
||||
uid: "?u64",
|
||||
gid: "?u64",
|
||||
rdev: "?u64",
|
||||
blksize: "?u64",
|
||||
blocks: "?u64",
|
||||
});
|
||||
|
||||
function parseFileInfo(response) {
|
||||
const unix = core.build.os === "darwin" || core.build.os === "linux";
|
||||
return {
|
||||
isFile: response.isFile,
|
||||
isDirectory: response.isDirectory,
|
||||
isSymlink: response.isSymlink,
|
||||
size: response.size,
|
||||
mtime: response.mtimeSet !== null ? new Date(response.mtime) : null,
|
||||
atime: response.atimeSet !== null ? new Date(response.atime) : null,
|
||||
birthtime: response.birthtimeSet !== null
|
||||
? new Date(response.birthtime)
|
||||
: null,
|
||||
// Only non-null if on Unix
|
||||
dev: unix ? response.dev : null,
|
||||
ino: unix ? response.ino : null,
|
||||
mode: unix ? response.mode : null,
|
||||
nlink: unix ? response.nlink : null,
|
||||
uid: unix ? response.uid : null,
|
||||
gid: unix ? response.gid : null,
|
||||
rdev: unix ? response.rdev : null,
|
||||
blksize: unix ? response.blksize : null,
|
||||
blocks: unix ? response.blocks : null,
|
||||
};
|
||||
}
|
||||
|
||||
function fstatSync(rid) {
|
||||
ops.op_fstat_sync(rid, statBuf);
|
||||
return statStruct(statBuf);
|
||||
}
|
||||
|
||||
async function fstat(rid) {
|
||||
return parseFileInfo(await core.opAsync("op_fstat_async", rid));
|
||||
}
|
||||
|
||||
async function lstat(path) {
|
||||
const res = await core.opAsync("op_stat_async", {
|
||||
path: pathFromURL(path),
|
||||
lstat: true,
|
||||
});
|
||||
return parseFileInfo(res);
|
||||
}
|
||||
|
||||
function lstatSync(path) {
|
||||
ops.op_stat_sync(
|
||||
pathFromURL(path),
|
||||
true,
|
||||
statBuf,
|
||||
);
|
||||
return statStruct(statBuf);
|
||||
}
|
||||
|
||||
async function stat(path) {
|
||||
const res = await core.opAsync("op_stat_async", {
|
||||
path: pathFromURL(path),
|
||||
lstat: false,
|
||||
});
|
||||
return parseFileInfo(res);
|
||||
}
|
||||
|
||||
function statSync(path) {
|
||||
ops.op_stat_sync(
|
||||
pathFromURL(path),
|
||||
false,
|
||||
statBuf,
|
||||
);
|
||||
return statStruct(statBuf);
|
||||
}
|
||||
|
||||
function coerceLen(len) {
|
||||
if (len == null || len < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
function ftruncateSync(rid, len) {
|
||||
ops.op_ftruncate_sync(rid, coerceLen(len));
|
||||
}
|
||||
|
||||
async function ftruncate(rid, len) {
|
||||
await core.opAsync("op_ftruncate_async", rid, coerceLen(len));
|
||||
}
|
||||
|
||||
function truncateSync(path, len) {
|
||||
ops.op_truncate_sync(path, coerceLen(len));
|
||||
}
|
||||
|
||||
async function truncate(path, len) {
|
||||
await core.opAsync("op_truncate_async", path, coerceLen(len));
|
||||
}
|
||||
|
||||
function umask(mask) {
|
||||
return ops.op_umask(mask);
|
||||
}
|
||||
|
||||
function linkSync(oldpath, newpath) {
|
||||
ops.op_link_sync(oldpath, newpath);
|
||||
}
|
||||
|
||||
async function link(oldpath, newpath) {
|
||||
await core.opAsync("op_link_async", oldpath, newpath);
|
||||
}
|
||||
|
||||
function toUnixTimeFromEpoch(value) {
|
||||
if (ObjectPrototypeIsPrototypeOf(DatePrototype, value)) {
|
||||
const time = value.valueOf();
|
||||
const seconds = MathTrunc(time / 1e3);
|
||||
const nanoseconds = MathTrunc(time - (seconds * 1e3)) * 1e6;
|
||||
|
||||
return [
|
||||
seconds,
|
||||
nanoseconds,
|
||||
];
|
||||
}
|
||||
|
||||
const seconds = value;
|
||||
const nanoseconds = 0;
|
||||
|
||||
return [
|
||||
seconds,
|
||||
nanoseconds,
|
||||
];
|
||||
}
|
||||
|
||||
function futimeSync(
|
||||
rid,
|
||||
atime,
|
||||
mtime,
|
||||
) {
|
||||
const { 0: atimeSec, 1: atimeNsec } = toUnixTimeFromEpoch(atime);
|
||||
const { 0: mtimeSec, 1: mtimeNsec } = toUnixTimeFromEpoch(mtime);
|
||||
ops.op_futime_sync(rid, atimeSec, atimeNsec, mtimeSec, mtimeNsec);
|
||||
}
|
||||
|
||||
async function futime(
|
||||
rid,
|
||||
atime,
|
||||
mtime,
|
||||
) {
|
||||
const { 0: atimeSec, 1: atimeNsec } = toUnixTimeFromEpoch(atime);
|
||||
const { 0: mtimeSec, 1: mtimeNsec } = toUnixTimeFromEpoch(mtime);
|
||||
await core.opAsync(
|
||||
"op_futime_async",
|
||||
rid,
|
||||
atimeSec,
|
||||
atimeNsec,
|
||||
mtimeSec,
|
||||
mtimeNsec,
|
||||
);
|
||||
}
|
||||
|
||||
function utimeSync(
|
||||
path,
|
||||
atime,
|
||||
mtime,
|
||||
) {
|
||||
const { 0: atimeSec, 1: atimeNsec } = toUnixTimeFromEpoch(atime);
|
||||
const { 0: mtimeSec, 1: mtimeNsec } = toUnixTimeFromEpoch(mtime);
|
||||
ops.op_utime_sync(
|
||||
pathFromURL(path),
|
||||
atimeSec,
|
||||
atimeNsec,
|
||||
mtimeSec,
|
||||
mtimeNsec,
|
||||
);
|
||||
}
|
||||
|
||||
async function utime(
|
||||
path,
|
||||
atime,
|
||||
mtime,
|
||||
) {
|
||||
const { 0: atimeSec, 1: atimeNsec } = toUnixTimeFromEpoch(atime);
|
||||
const { 0: mtimeSec, 1: mtimeNsec } = toUnixTimeFromEpoch(mtime);
|
||||
await core.opAsync(
|
||||
"op_utime_async",
|
||||
pathFromURL(path),
|
||||
atimeSec,
|
||||
atimeNsec,
|
||||
mtimeSec,
|
||||
mtimeNsec,
|
||||
);
|
||||
}
|
||||
|
||||
function symlinkSync(
|
||||
oldpath,
|
||||
newpath,
|
||||
options,
|
||||
) {
|
||||
ops.op_symlink_sync(
|
||||
pathFromURL(oldpath),
|
||||
pathFromURL(newpath),
|
||||
options?.type,
|
||||
);
|
||||
}
|
||||
|
||||
async function symlink(
|
||||
oldpath,
|
||||
newpath,
|
||||
options,
|
||||
) {
|
||||
await core.opAsync(
|
||||
"op_symlink_async",
|
||||
pathFromURL(oldpath),
|
||||
pathFromURL(newpath),
|
||||
options?.type,
|
||||
);
|
||||
}
|
||||
|
||||
function fdatasyncSync(rid) {
|
||||
ops.op_fdatasync_sync(rid);
|
||||
}
|
||||
|
||||
async function fdatasync(rid) {
|
||||
await core.opAsync("op_fdatasync_async", rid);
|
||||
}
|
||||
|
||||
function fsyncSync(rid) {
|
||||
ops.op_fsync_sync(rid);
|
||||
}
|
||||
|
||||
async function fsync(rid) {
|
||||
await core.opAsync("op_fsync_async", rid);
|
||||
}
|
||||
|
||||
function flockSync(rid, exclusive) {
|
||||
ops.op_flock_sync(rid, exclusive === true);
|
||||
}
|
||||
|
||||
async function flock(rid, exclusive) {
|
||||
await core.opAsync("op_flock_async", rid, exclusive === true);
|
||||
}
|
||||
|
||||
function funlockSync(rid) {
|
||||
ops.op_funlock_sync(rid);
|
||||
}
|
||||
|
||||
async function funlock(rid) {
|
||||
await core.opAsync("op_funlock_async", rid);
|
||||
}
|
||||
|
||||
function seekSync(
|
||||
rid,
|
||||
offset,
|
||||
whence,
|
||||
) {
|
||||
return ops.op_seek_sync({ rid, offset, whence });
|
||||
}
|
||||
|
||||
function seek(
|
||||
rid,
|
||||
offset,
|
||||
whence,
|
||||
) {
|
||||
return core.opAsync("op_seek_async", { rid, offset, whence });
|
||||
}
|
||||
|
||||
function openSync(
|
||||
path,
|
||||
options,
|
||||
) {
|
||||
if (options) checkOpenOptions(options);
|
||||
const mode = options?.mode;
|
||||
const rid = ops.op_open_sync(
|
||||
pathFromURL(path),
|
||||
options,
|
||||
mode,
|
||||
);
|
||||
|
||||
return new FsFile(rid);
|
||||
}
|
||||
|
||||
async function open(
|
||||
path,
|
||||
options,
|
||||
) {
|
||||
if (options) checkOpenOptions(options);
|
||||
const mode = options?.mode;
|
||||
const rid = await core.opAsync(
|
||||
"op_open_async",
|
||||
pathFromURL(path),
|
||||
options,
|
||||
mode,
|
||||
);
|
||||
|
||||
return new FsFile(rid);
|
||||
}
|
||||
|
||||
function createSync(path) {
|
||||
return openSync(path, {
|
||||
read: true,
|
||||
write: true,
|
||||
truncate: true,
|
||||
create: true,
|
||||
});
|
||||
}
|
||||
|
||||
function create(path) {
|
||||
return open(path, {
|
||||
read: true,
|
||||
write: true,
|
||||
truncate: true,
|
||||
create: true,
|
||||
});
|
||||
}
|
||||
|
||||
class FsFile {
|
||||
#rid = 0;
|
||||
|
||||
#readable;
|
||||
#writable;
|
||||
|
||||
constructor(rid) {
|
||||
this.#rid = rid;
|
||||
}
|
||||
|
||||
get rid() {
|
||||
return this.#rid;
|
||||
}
|
||||
|
||||
write(p) {
|
||||
return write(this.rid, p);
|
||||
}
|
||||
|
||||
writeSync(p) {
|
||||
return writeSync(this.rid, p);
|
||||
}
|
||||
|
||||
truncate(len) {
|
||||
return ftruncate(this.rid, len);
|
||||
}
|
||||
|
||||
truncateSync(len) {
|
||||
return ftruncateSync(this.rid, len);
|
||||
}
|
||||
|
||||
read(p) {
|
||||
return read(this.rid, p);
|
||||
}
|
||||
|
||||
readSync(p) {
|
||||
return readSync(this.rid, p);
|
||||
}
|
||||
|
||||
seek(offset, whence) {
|
||||
return seek(this.rid, offset, whence);
|
||||
}
|
||||
|
||||
seekSync(offset, whence) {
|
||||
return seekSync(this.rid, offset, whence);
|
||||
}
|
||||
|
||||
stat() {
|
||||
return fstat(this.rid);
|
||||
}
|
||||
|
||||
statSync() {
|
||||
return fstatSync(this.rid);
|
||||
}
|
||||
|
||||
close() {
|
||||
core.close(this.rid);
|
||||
}
|
||||
|
||||
get readable() {
|
||||
if (this.#readable === undefined) {
|
||||
this.#readable = readableStreamForRid(this.rid);
|
||||
}
|
||||
return this.#readable;
|
||||
}
|
||||
|
||||
get writable() {
|
||||
if (this.#writable === undefined) {
|
||||
this.#writable = writableStreamForRid(this.rid);
|
||||
}
|
||||
return this.#writable;
|
||||
}
|
||||
}
|
||||
|
||||
function checkOpenOptions(options) {
|
||||
if (
|
||||
ArrayPrototypeFilter(
|
||||
ObjectValues(options),
|
||||
(val) => val === true,
|
||||
).length === 0
|
||||
) {
|
||||
throw new Error("OpenOptions requires at least one option to be true");
|
||||
}
|
||||
|
||||
if (options.truncate && !options.write) {
|
||||
throw new Error("'truncate' option requires 'write' option");
|
||||
}
|
||||
|
||||
const createOrCreateNewWithoutWriteOrAppend =
|
||||
(options.create || options.createNew) &&
|
||||
!(options.write || options.append);
|
||||
|
||||
if (createOrCreateNewWithoutWriteOrAppend) {
|
||||
throw new Error(
|
||||
"'create' or 'createNew' options require 'write' or 'append' option",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const File = FsFile;
|
||||
|
||||
function readFileSync(path) {
|
||||
return ops.op_readfile_sync(pathFromURL(path));
|
||||
}
|
||||
|
||||
async function readFile(path, options) {
|
||||
let cancelRid;
|
||||
let abortHandler;
|
||||
if (options?.signal) {
|
||||
options.signal.throwIfAborted();
|
||||
cancelRid = ops.op_cancel_handle();
|
||||
abortHandler = () => core.tryClose(cancelRid);
|
||||
options.signal[abortSignal.add](abortHandler);
|
||||
}
|
||||
|
||||
try {
|
||||
const read = await core.opAsync(
|
||||
"op_readfile_async",
|
||||
pathFromURL(path),
|
||||
cancelRid,
|
||||
);
|
||||
return read;
|
||||
} finally {
|
||||
if (options?.signal) {
|
||||
options.signal[abortSignal.remove](abortHandler);
|
||||
|
||||
// always throw the abort error when aborted
|
||||
options.signal.throwIfAborted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function readTextFileSync(path) {
|
||||
return ops.op_readfile_text_sync(pathFromURL(path));
|
||||
}
|
||||
|
||||
async function readTextFile(path, options) {
|
||||
let cancelRid;
|
||||
let abortHandler;
|
||||
if (options?.signal) {
|
||||
options.signal.throwIfAborted();
|
||||
cancelRid = ops.op_cancel_handle();
|
||||
abortHandler = () => core.tryClose(cancelRid);
|
||||
options.signal[abortSignal.add](abortHandler);
|
||||
}
|
||||
|
||||
try {
|
||||
const read = await core.opAsync(
|
||||
"op_readfile_text_async",
|
||||
pathFromURL(path),
|
||||
cancelRid,
|
||||
);
|
||||
return read;
|
||||
} finally {
|
||||
if (options?.signal) {
|
||||
options.signal[abortSignal.remove](abortHandler);
|
||||
|
||||
// always throw the abort error when aborted
|
||||
options.signal.throwIfAborted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function writeFileSync(
|
||||
path,
|
||||
data,
|
||||
options = {},
|
||||
) {
|
||||
options.signal?.throwIfAborted();
|
||||
ops.op_write_file_sync(
|
||||
pathFromURL(path),
|
||||
options.mode,
|
||||
options.append ?? false,
|
||||
options.create ?? true,
|
||||
options.createNew ?? false,
|
||||
data,
|
||||
);
|
||||
}
|
||||
|
||||
async function writeFile(
|
||||
path,
|
||||
data,
|
||||
options = {},
|
||||
) {
|
||||
let cancelRid;
|
||||
let abortHandler;
|
||||
if (options.signal) {
|
||||
options.signal.throwIfAborted();
|
||||
cancelRid = ops.op_cancel_handle();
|
||||
abortHandler = () => core.tryClose(cancelRid);
|
||||
options.signal[abortSignal.add](abortHandler);
|
||||
}
|
||||
try {
|
||||
if (ObjectPrototypeIsPrototypeOf(ReadableStreamPrototype, data)) {
|
||||
const file = await open(path, {
|
||||
mode: options.mode,
|
||||
append: options.append ?? false,
|
||||
create: options.create ?? true,
|
||||
createNew: options.createNew ?? false,
|
||||
write: true,
|
||||
});
|
||||
await data.pipeTo(file.writable, {
|
||||
signal: options.signal,
|
||||
});
|
||||
} else {
|
||||
await core.opAsync(
|
||||
"op_write_file_async",
|
||||
pathFromURL(path),
|
||||
options.mode,
|
||||
options.append ?? false,
|
||||
options.create ?? true,
|
||||
options.createNew ?? false,
|
||||
data,
|
||||
cancelRid,
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
if (options.signal) {
|
||||
options.signal[abortSignal.remove](abortHandler);
|
||||
|
||||
// always throw the abort error when aborted
|
||||
options.signal.throwIfAborted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function writeTextFileSync(
|
||||
path,
|
||||
data,
|
||||
options = {},
|
||||
) {
|
||||
const encoder = new TextEncoder();
|
||||
return writeFileSync(path, encoder.encode(data), options);
|
||||
}
|
||||
|
||||
function writeTextFile(
|
||||
path,
|
||||
data,
|
||||
options = {},
|
||||
) {
|
||||
if (ObjectPrototypeIsPrototypeOf(ReadableStreamPrototype, data)) {
|
||||
return writeFile(
|
||||
path,
|
||||
data.pipeThrough(new TextEncoderStream()),
|
||||
options,
|
||||
);
|
||||
} else {
|
||||
const encoder = new TextEncoder();
|
||||
return writeFile(path, encoder.encode(data), options);
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
chdir,
|
||||
chmod,
|
||||
chmodSync,
|
||||
chown,
|
||||
chownSync,
|
||||
copyFile,
|
||||
copyFileSync,
|
||||
create,
|
||||
createSync,
|
||||
cwd,
|
||||
fdatasync,
|
||||
fdatasyncSync,
|
||||
File,
|
||||
flock,
|
||||
flockSync,
|
||||
FsFile,
|
||||
fstat,
|
||||
fstatSync,
|
||||
fsync,
|
||||
fsyncSync,
|
||||
ftruncate,
|
||||
ftruncateSync,
|
||||
funlock,
|
||||
funlockSync,
|
||||
futime,
|
||||
futimeSync,
|
||||
link,
|
||||
linkSync,
|
||||
lstat,
|
||||
lstatSync,
|
||||
makeTempDir,
|
||||
makeTempDirSync,
|
||||
makeTempFile,
|
||||
makeTempFileSync,
|
||||
mkdir,
|
||||
mkdirSync,
|
||||
open,
|
||||
openSync,
|
||||
readDir,
|
||||
readDirSync,
|
||||
readFile,
|
||||
readFileSync,
|
||||
readLink,
|
||||
readLinkSync,
|
||||
readTextFile,
|
||||
readTextFileSync,
|
||||
realPath,
|
||||
realPathSync,
|
||||
remove,
|
||||
removeSync,
|
||||
rename,
|
||||
renameSync,
|
||||
seek,
|
||||
seekSync,
|
||||
stat,
|
||||
statSync,
|
||||
symlink,
|
||||
symlinkSync,
|
||||
truncate,
|
||||
truncateSync,
|
||||
umask,
|
||||
utime,
|
||||
utimeSync,
|
||||
writeFile,
|
||||
writeFileSync,
|
||||
writeTextFile,
|
||||
writeTextFileSync,
|
||||
};
|
|
@ -16,7 +16,7 @@ const {
|
|||
SymbolFor,
|
||||
Symbol,
|
||||
} = primordials;
|
||||
import { FsFile } from "internal:runtime/30_fs.js";
|
||||
import { FsFile } from "internal:deno_fs/30_fs.js";
|
||||
import { readAll } from "internal:deno_io/12_io.js";
|
||||
import { assert, pathFromURL } from "internal:deno_web/00_infra.js";
|
||||
import * as abortSignal from "internal:deno_web/03_abort_signal.js";
|
||||
|
|
|
@ -15,7 +15,7 @@ import * as version from "internal:runtime/01_version.ts";
|
|||
import * as permissions from "internal:runtime/10_permissions.js";
|
||||
import * as io from "internal:deno_io/12_io.js";
|
||||
import * as buffer from "internal:runtime/13_buffer.js";
|
||||
import * as fs from "internal:runtime/30_fs.js";
|
||||
import * as fs from "internal:deno_fs/30_fs.js";
|
||||
import * as os from "internal:runtime/30_os.js";
|
||||
import * as fsEvents from "internal:runtime/40_fs_events.js";
|
||||
import * as process from "internal:runtime/40_process.js";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue