mirror of
https://github.com/denoland/deno.git
synced 2024-11-29 16:30:56 -05:00
b40086fd7d
This commit changes "include_js_files!" macro from "deno_core" in a way that "dir" option doesn't cause specifiers to be rewritten to include it. Example: ``` include_js_files! { dir "js", "hello.js", } ``` The above definition required embedders to use: `import ... from "internal:<ext_name>/js/hello.js"`. But with this change, the "js" directory in which the files are stored is an implementation detail, which for embedders results in: `import ... from "internal:<ext_name>/hello.js"`. The directory the files are stored in, is an implementation detail and in some cases might result in a significant size difference for the snapshot. As an example, in "deno_node" extension, we store the source code in "polyfills" directory; which resulted in each specifier to look like "internal:deno_node/polyfills/<module_name>", but with this change it's "internal:deno_node/<module_name>". Given that "deno_node" has over 100 files, many of them having several import specifiers to the same extension, this change removes 10 characters from each import specifier.
233 lines
6.8 KiB
TypeScript
233 lines
6.8 KiB
TypeScript
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
|
import {
|
|
O_APPEND,
|
|
O_CREAT,
|
|
O_EXCL,
|
|
O_RDONLY,
|
|
O_RDWR,
|
|
O_TRUNC,
|
|
O_WRONLY,
|
|
} from "internal:deno_node/_fs/_fs_constants.ts";
|
|
import { validateFunction } from "internal:deno_node/internal/validators.mjs";
|
|
import type { ErrnoException } from "internal:deno_node/_global.d.ts";
|
|
import {
|
|
BinaryEncodings,
|
|
Encodings,
|
|
notImplemented,
|
|
TextEncodings,
|
|
} from "internal:deno_node/_utils.ts";
|
|
|
|
export type CallbackWithError = (err: ErrnoException | null) => void;
|
|
|
|
export interface FileOptions {
|
|
encoding?: Encodings;
|
|
flag?: string;
|
|
signal?: AbortSignal;
|
|
}
|
|
|
|
export type TextOptionsArgument =
|
|
| TextEncodings
|
|
| ({ encoding: TextEncodings } & FileOptions);
|
|
export type BinaryOptionsArgument =
|
|
| BinaryEncodings
|
|
| ({ encoding: BinaryEncodings } & FileOptions);
|
|
export type FileOptionsArgument = Encodings | FileOptions;
|
|
|
|
export interface WriteFileOptions extends FileOptions {
|
|
mode?: number;
|
|
}
|
|
|
|
export function isFileOptions(
|
|
fileOptions: string | WriteFileOptions | undefined,
|
|
): fileOptions is FileOptions {
|
|
if (!fileOptions) return false;
|
|
|
|
return (
|
|
(fileOptions as FileOptions).encoding != undefined ||
|
|
(fileOptions as FileOptions).flag != undefined ||
|
|
(fileOptions as FileOptions).signal != undefined ||
|
|
(fileOptions as WriteFileOptions).mode != undefined
|
|
);
|
|
}
|
|
|
|
export function getEncoding(
|
|
optOrCallback?:
|
|
| FileOptions
|
|
| WriteFileOptions
|
|
// deno-lint-ignore no-explicit-any
|
|
| ((...args: any[]) => any)
|
|
| Encodings
|
|
| null,
|
|
): Encodings | null {
|
|
if (!optOrCallback || typeof optOrCallback === "function") {
|
|
return null;
|
|
}
|
|
|
|
const encoding = typeof optOrCallback === "string"
|
|
? optOrCallback
|
|
: optOrCallback.encoding;
|
|
if (!encoding) return null;
|
|
return encoding;
|
|
}
|
|
|
|
export function checkEncoding(encoding: Encodings | null): Encodings | null {
|
|
if (!encoding) return null;
|
|
|
|
encoding = encoding.toLowerCase() as Encodings;
|
|
if (["utf8", "hex", "base64"].includes(encoding)) return encoding;
|
|
|
|
if (encoding === "utf-8") {
|
|
return "utf8";
|
|
}
|
|
if (encoding === "binary") {
|
|
return "binary";
|
|
// before this was buffer, however buffer is not used in Node
|
|
// node -e "require('fs').readFile('../world.txt', 'buffer', console.log)"
|
|
}
|
|
|
|
const notImplementedEncodings = ["utf16le", "latin1", "ascii", "ucs2"];
|
|
|
|
if (notImplementedEncodings.includes(encoding as string)) {
|
|
notImplemented(`"${encoding}" encoding`);
|
|
}
|
|
|
|
throw new Error(`The value "${encoding}" is invalid for option "encoding"`);
|
|
}
|
|
|
|
export function getOpenOptions(
|
|
flag: string | number | undefined,
|
|
): Deno.OpenOptions {
|
|
if (!flag) {
|
|
return { create: true, append: true };
|
|
}
|
|
|
|
let openOptions: Deno.OpenOptions = {};
|
|
|
|
if (typeof flag === "string") {
|
|
switch (flag) {
|
|
case "a": {
|
|
// 'a': Open file for appending. The file is created if it does not exist.
|
|
openOptions = { create: true, append: true };
|
|
break;
|
|
}
|
|
case "ax":
|
|
case "xa": {
|
|
// 'ax', 'xa': Like 'a' but fails if the path exists.
|
|
openOptions = { createNew: true, write: true, append: true };
|
|
break;
|
|
}
|
|
case "a+": {
|
|
// 'a+': Open file for reading and appending. The file is created if it does not exist.
|
|
openOptions = { read: true, create: true, append: true };
|
|
break;
|
|
}
|
|
case "ax+":
|
|
case "xa+": {
|
|
// 'ax+', 'xa+': Like 'a+' but fails if the path exists.
|
|
openOptions = { read: true, createNew: true, append: true };
|
|
break;
|
|
}
|
|
case "r": {
|
|
// 'r': Open file for reading. An exception occurs if the file does not exist.
|
|
openOptions = { read: true };
|
|
break;
|
|
}
|
|
case "r+": {
|
|
// 'r+': Open file for reading and writing. An exception occurs if the file does not exist.
|
|
openOptions = { read: true, write: true };
|
|
break;
|
|
}
|
|
case "w": {
|
|
// 'w': Open file for writing. The file is created (if it does not exist) or truncated (if it exists).
|
|
openOptions = { create: true, write: true, truncate: true };
|
|
break;
|
|
}
|
|
case "wx":
|
|
case "xw": {
|
|
// 'wx', 'xw': Like 'w' but fails if the path exists.
|
|
openOptions = { createNew: true, write: true };
|
|
break;
|
|
}
|
|
case "w+": {
|
|
// 'w+': Open file for reading and writing. The file is created (if it does not exist) or truncated (if it exists).
|
|
openOptions = { create: true, write: true, truncate: true, read: true };
|
|
break;
|
|
}
|
|
case "wx+":
|
|
case "xw+": {
|
|
// 'wx+', 'xw+': Like 'w+' but fails if the path exists.
|
|
openOptions = { createNew: true, write: true, read: true };
|
|
break;
|
|
}
|
|
case "as":
|
|
case "sa": {
|
|
// 'as', 'sa': Open file for appending in synchronous mode. The file is created if it does not exist.
|
|
openOptions = { create: true, append: true };
|
|
break;
|
|
}
|
|
case "as+":
|
|
case "sa+": {
|
|
// 'as+', 'sa+': Open file for reading and appending in synchronous mode. The file is created if it does not exist.
|
|
openOptions = { create: true, read: true, append: true };
|
|
break;
|
|
}
|
|
case "rs+":
|
|
case "sr+": {
|
|
// 'rs+', 'sr+': Open file for reading and writing in synchronous mode. Instructs the operating system to bypass the local file system cache.
|
|
openOptions = { create: true, read: true, write: true };
|
|
break;
|
|
}
|
|
default: {
|
|
throw new Error(`Unrecognized file system flag: ${flag}`);
|
|
}
|
|
}
|
|
} else if (typeof flag === "number") {
|
|
if ((flag & O_APPEND) === O_APPEND) {
|
|
openOptions.append = true;
|
|
}
|
|
if ((flag & O_CREAT) === O_CREAT) {
|
|
openOptions.create = true;
|
|
openOptions.write = true;
|
|
}
|
|
if ((flag & O_EXCL) === O_EXCL) {
|
|
openOptions.createNew = true;
|
|
openOptions.read = true;
|
|
openOptions.write = true;
|
|
}
|
|
if ((flag & O_TRUNC) === O_TRUNC) {
|
|
openOptions.truncate = true;
|
|
}
|
|
if ((flag & O_RDONLY) === O_RDONLY) {
|
|
openOptions.read = true;
|
|
}
|
|
if ((flag & O_WRONLY) === O_WRONLY) {
|
|
openOptions.write = true;
|
|
}
|
|
if ((flag & O_RDWR) === O_RDWR) {
|
|
openOptions.read = true;
|
|
openOptions.write = true;
|
|
}
|
|
}
|
|
|
|
return openOptions;
|
|
}
|
|
|
|
export { isUint32 as isFd } from "internal:deno_node/internal/validators.mjs";
|
|
|
|
export function maybeCallback(cb: unknown) {
|
|
validateFunction(cb, "cb");
|
|
|
|
return cb as CallbackWithError;
|
|
}
|
|
|
|
// Ensure that callbacks run in the global context. Only use this function
|
|
// for callbacks that are passed to the binding layer, callbacks that are
|
|
// invoked from JS already run in the proper scope.
|
|
export function makeCallback(
|
|
this: unknown,
|
|
cb?: (err: Error | null, result?: unknown) => void,
|
|
) {
|
|
validateFunction(cb, "cb");
|
|
|
|
return (...args: unknown[]) => Reflect.apply(cb!, this, args);
|
|
}
|