mirror of
https://github.com/denoland/deno.git
synced 2024-12-11 18:17:48 -05:00
ce75e31625
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.
317 lines
7.9 KiB
JavaScript
317 lines
7.9 KiB
JavaScript
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
|
// Copyright Joyent and Node contributors. All rights reserved. MIT license.
|
|
|
|
import { codes } from "internal:deno_node/internal/error_codes.ts";
|
|
import { hideStackFrames } from "internal:deno_node/internal/hide_stack_frames.ts";
|
|
import { isArrayBufferView } from "internal:deno_node/internal/util/types.ts";
|
|
import { normalizeEncoding } from "internal:deno_node/internal/normalize_encoding.mjs";
|
|
|
|
/**
|
|
* @param {number} value
|
|
* @returns {boolean}
|
|
*/
|
|
function isInt32(value) {
|
|
return value === (value | 0);
|
|
}
|
|
|
|
/**
|
|
* @param {unknown} value
|
|
* @returns {boolean}
|
|
*/
|
|
function isUint32(value) {
|
|
return value === (value >>> 0);
|
|
}
|
|
|
|
const octalReg = /^[0-7]+$/;
|
|
const modeDesc = "must be a 32-bit unsigned integer or an octal string";
|
|
|
|
/**
|
|
* Parse and validate values that will be converted into mode_t (the S_*
|
|
* constants). Only valid numbers and octal strings are allowed. They could be
|
|
* converted to 32-bit unsigned integers or non-negative signed integers in the
|
|
* C++ land, but any value higher than 0o777 will result in platform-specific
|
|
* behaviors.
|
|
*
|
|
* @param {*} value Values to be validated
|
|
* @param {string} name Name of the argument
|
|
* @param {number} [def] If specified, will be returned for invalid values
|
|
* @returns {number}
|
|
*/
|
|
function parseFileMode(value, name, def) {
|
|
value ??= def;
|
|
if (typeof value === "string") {
|
|
if (!octalReg.test(value)) {
|
|
throw new codes.ERR_INVALID_ARG_VALUE(name, value, modeDesc);
|
|
}
|
|
value = Number.parseInt(value, 8);
|
|
}
|
|
|
|
validateInt32(value, name, 0, 2 ** 32 - 1);
|
|
return value;
|
|
}
|
|
|
|
const validateBuffer = hideStackFrames((buffer, name = "buffer") => {
|
|
if (!isArrayBufferView(buffer)) {
|
|
throw new codes.ERR_INVALID_ARG_TYPE(
|
|
name,
|
|
["Buffer", "TypedArray", "DataView"],
|
|
buffer,
|
|
);
|
|
}
|
|
});
|
|
|
|
const validateInteger = hideStackFrames(
|
|
(
|
|
value,
|
|
name,
|
|
min = Number.MIN_SAFE_INTEGER,
|
|
max = Number.MAX_SAFE_INTEGER,
|
|
) => {
|
|
if (typeof value !== "number") {
|
|
throw new codes.ERR_INVALID_ARG_TYPE(name, "number", value);
|
|
}
|
|
if (!Number.isInteger(value)) {
|
|
throw new codes.ERR_OUT_OF_RANGE(name, "an integer", value);
|
|
}
|
|
if (value < min || value > max) {
|
|
throw new codes.ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value);
|
|
}
|
|
},
|
|
);
|
|
|
|
/**
|
|
* @param {unknown} value
|
|
* @param {string} name
|
|
* @param {{
|
|
* allowArray?: boolean,
|
|
* allowFunction?: boolean,
|
|
* nullable?: boolean
|
|
* }} [options]
|
|
*/
|
|
const validateObject = hideStackFrames((value, name, options) => {
|
|
const useDefaultOptions = options == null;
|
|
const allowArray = useDefaultOptions ? false : options.allowArray;
|
|
const allowFunction = useDefaultOptions ? false : options.allowFunction;
|
|
const nullable = useDefaultOptions ? false : options.nullable;
|
|
if (
|
|
(!nullable && value === null) ||
|
|
(!allowArray && Array.isArray(value)) ||
|
|
(typeof value !== "object" && (
|
|
!allowFunction || typeof value !== "function"
|
|
))
|
|
) {
|
|
throw new codes.ERR_INVALID_ARG_TYPE(name, "Object", value);
|
|
}
|
|
});
|
|
|
|
const validateInt32 = hideStackFrames(
|
|
(value, name, min = -2147483648, max = 2147483647) => {
|
|
// The defaults for min and max correspond to the limits of 32-bit integers.
|
|
if (!isInt32(value)) {
|
|
if (typeof value !== "number") {
|
|
throw new codes.ERR_INVALID_ARG_TYPE(name, "number", value);
|
|
}
|
|
|
|
if (!Number.isInteger(value)) {
|
|
throw new codes.ERR_OUT_OF_RANGE(name, "an integer", value);
|
|
}
|
|
|
|
throw new codes.ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value);
|
|
}
|
|
|
|
if (value < min || value > max) {
|
|
throw new codes.ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value);
|
|
}
|
|
},
|
|
);
|
|
|
|
const validateUint32 = hideStackFrames(
|
|
(value, name, positive) => {
|
|
if (!isUint32(value)) {
|
|
if (typeof value !== "number") {
|
|
throw new codes.ERR_INVALID_ARG_TYPE(name, "number", value);
|
|
}
|
|
if (!Number.isInteger(value)) {
|
|
throw new codes.ERR_OUT_OF_RANGE(name, "an integer", value);
|
|
}
|
|
const min = positive ? 1 : 0;
|
|
// 2 ** 32 === 4294967296
|
|
throw new codes.ERR_OUT_OF_RANGE(
|
|
name,
|
|
`>= ${min} && < 4294967296`,
|
|
value,
|
|
);
|
|
}
|
|
if (positive && value === 0) {
|
|
throw new codes.ERR_OUT_OF_RANGE(name, ">= 1 && < 4294967296", value);
|
|
}
|
|
},
|
|
);
|
|
|
|
/**
|
|
* @param {unknown} value
|
|
* @param {string} name
|
|
*/
|
|
function validateString(value, name) {
|
|
if (typeof value !== "string") {
|
|
throw new codes.ERR_INVALID_ARG_TYPE(name, "string", value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {unknown} value
|
|
* @param {string} name
|
|
*/
|
|
function validateNumber(value, name) {
|
|
if (typeof value !== "number") {
|
|
throw new codes.ERR_INVALID_ARG_TYPE(name, "number", value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {unknown} value
|
|
* @param {string} name
|
|
*/
|
|
function validateBoolean(value, name) {
|
|
if (typeof value !== "boolean") {
|
|
throw new codes.ERR_INVALID_ARG_TYPE(name, "boolean", value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {unknown} value
|
|
* @param {string} name
|
|
* @param {unknown[]} oneOf
|
|
*/
|
|
const validateOneOf = hideStackFrames(
|
|
(value, name, oneOf) => {
|
|
if (!Array.prototype.includes.call(oneOf, value)) {
|
|
const allowed = Array.prototype.join.call(
|
|
Array.prototype.map.call(
|
|
oneOf,
|
|
(v) => (typeof v === "string" ? `'${v}'` : String(v)),
|
|
),
|
|
", ",
|
|
);
|
|
const reason = "must be one of: " + allowed;
|
|
|
|
throw new codes.ERR_INVALID_ARG_VALUE(name, value, reason);
|
|
}
|
|
},
|
|
);
|
|
|
|
export function validateEncoding(data, encoding) {
|
|
const normalizedEncoding = normalizeEncoding(encoding);
|
|
const length = data.length;
|
|
|
|
if (normalizedEncoding === "hex" && length % 2 !== 0) {
|
|
throw new codes.ERR_INVALID_ARG_VALUE(
|
|
"encoding",
|
|
encoding,
|
|
`is invalid for data of length ${length}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
// Check that the port number is not NaN when coerced to a number,
|
|
// is an integer and that it falls within the legal range of port numbers.
|
|
/**
|
|
* @param {string} name
|
|
* @returns {number}
|
|
*/
|
|
function validatePort(port, name = "Port", allowZero = true) {
|
|
if (
|
|
(typeof port !== "number" && typeof port !== "string") ||
|
|
(typeof port === "string" &&
|
|
String.prototype.trim.call(port).length === 0) ||
|
|
+port !== (+port >>> 0) ||
|
|
port > 0xFFFF ||
|
|
(port === 0 && !allowZero)
|
|
) {
|
|
throw new codes.ERR_SOCKET_BAD_PORT(name, port, allowZero);
|
|
}
|
|
|
|
return port;
|
|
}
|
|
|
|
/**
|
|
* @param {unknown} signal
|
|
* @param {string} name
|
|
*/
|
|
const validateAbortSignal = hideStackFrames(
|
|
(signal, name) => {
|
|
if (
|
|
signal !== undefined &&
|
|
(signal === null ||
|
|
typeof signal !== "object" ||
|
|
!("aborted" in signal))
|
|
) {
|
|
throw new codes.ERR_INVALID_ARG_TYPE(name, "AbortSignal", signal);
|
|
}
|
|
},
|
|
);
|
|
|
|
/**
|
|
* @param {unknown} value
|
|
* @param {string} name
|
|
*/
|
|
const validateFunction = hideStackFrames(
|
|
(value, name) => {
|
|
if (typeof value !== "function") {
|
|
throw new codes.ERR_INVALID_ARG_TYPE(name, "Function", value);
|
|
}
|
|
},
|
|
);
|
|
|
|
/**
|
|
* @param {unknown} value
|
|
* @param {string} name
|
|
*/
|
|
const validateArray = hideStackFrames(
|
|
(value, name, minLength = 0) => {
|
|
if (!Array.isArray(value)) {
|
|
throw new codes.ERR_INVALID_ARG_TYPE(name, "Array", value);
|
|
}
|
|
if (value.length < minLength) {
|
|
const reason = `must be longer than ${minLength}`;
|
|
throw new codes.ERR_INVALID_ARG_VALUE(name, value, reason);
|
|
}
|
|
},
|
|
);
|
|
|
|
export default {
|
|
isInt32,
|
|
isUint32,
|
|
parseFileMode,
|
|
validateAbortSignal,
|
|
validateArray,
|
|
validateBoolean,
|
|
validateBuffer,
|
|
validateFunction,
|
|
validateInt32,
|
|
validateInteger,
|
|
validateNumber,
|
|
validateObject,
|
|
validateOneOf,
|
|
validatePort,
|
|
validateString,
|
|
validateUint32,
|
|
};
|
|
export {
|
|
isInt32,
|
|
isUint32,
|
|
parseFileMode,
|
|
validateAbortSignal,
|
|
validateArray,
|
|
validateBoolean,
|
|
validateBuffer,
|
|
validateFunction,
|
|
validateInt32,
|
|
validateInteger,
|
|
validateNumber,
|
|
validateObject,
|
|
validateOneOf,
|
|
validatePort,
|
|
validateString,
|
|
validateUint32,
|
|
};
|