diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2023-03-07 05:13:44 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-07 18:13:44 +0900 |
commit | fe368b72c1dd2f2d17b7b7e5965b9e3d9ca61c35 (patch) | |
tree | ebc76fb86e3bee1baf1e336feb36a507affa7316 /runtime/js/30_fs.js | |
parent | 64354f41125642d420d80cbf617dfb8ddca398e5 (diff) |
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.
Diffstat (limited to 'runtime/js/30_fs.js')
-rw-r--r-- | runtime/js/30_fs.js | 899 |
1 files changed, 0 insertions, 899 deletions
diff --git a/runtime/js/30_fs.js b/runtime/js/30_fs.js deleted file mode 100644 index 19e7f372b..000000000 --- a/runtime/js/30_fs.js +++ /dev/null @@ -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, -}; |