WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -0,0 +1,187 @@
|
||||
'use strict';
|
||||
|
||||
/* eslint-disable jsdoc/valid-types -- doesn't allow `readonly`.
|
||||
TODO: remove eslint-disable when https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/164 is fixed
|
||||
*/
|
||||
/**
|
||||
* @typedef {{ readonly [type: string]: ReadonlyArray<string> }} VisitorKeys
|
||||
*/
|
||||
/* eslint-enable jsdoc/valid-types -- doesn't allow `readonly string[]`. TODO: check why */
|
||||
|
||||
/**
|
||||
* @type {VisitorKeys}
|
||||
*/
|
||||
const KEYS = {
|
||||
ArrayExpression: ["elements"],
|
||||
ArrayPattern: ["elements"],
|
||||
ArrowFunctionExpression: ["params", "body"],
|
||||
AssignmentExpression: ["left", "right"],
|
||||
AssignmentPattern: ["left", "right"],
|
||||
AwaitExpression: ["argument"],
|
||||
BinaryExpression: ["left", "right"],
|
||||
BlockStatement: ["body"],
|
||||
BreakStatement: ["label"],
|
||||
CallExpression: ["callee", "arguments"],
|
||||
CatchClause: ["param", "body"],
|
||||
ChainExpression: ["expression"],
|
||||
ClassBody: ["body"],
|
||||
ClassDeclaration: ["id", "superClass", "body"],
|
||||
ClassExpression: ["id", "superClass", "body"],
|
||||
ConditionalExpression: ["test", "consequent", "alternate"],
|
||||
ContinueStatement: ["label"],
|
||||
DebuggerStatement: [],
|
||||
DoWhileStatement: ["body", "test"],
|
||||
EmptyStatement: [],
|
||||
ExperimentalRestProperty: ["argument"],
|
||||
ExperimentalSpreadProperty: ["argument"],
|
||||
ExportAllDeclaration: ["exported", "source", "attributes"],
|
||||
ExportDefaultDeclaration: ["declaration"],
|
||||
ExportNamedDeclaration: [
|
||||
"declaration",
|
||||
"specifiers",
|
||||
"source",
|
||||
"attributes",
|
||||
],
|
||||
ExportSpecifier: ["local", "exported"],
|
||||
ExpressionStatement: ["expression"],
|
||||
ForInStatement: ["left", "right", "body"],
|
||||
ForOfStatement: ["left", "right", "body"],
|
||||
ForStatement: ["init", "test", "update", "body"],
|
||||
FunctionDeclaration: ["id", "params", "body"],
|
||||
FunctionExpression: ["id", "params", "body"],
|
||||
Identifier: [],
|
||||
IfStatement: ["test", "consequent", "alternate"],
|
||||
ImportAttribute: ["key", "value"],
|
||||
ImportDeclaration: ["specifiers", "source", "attributes"],
|
||||
ImportDefaultSpecifier: ["local"],
|
||||
ImportExpression: ["source", "options"],
|
||||
ImportNamespaceSpecifier: ["local"],
|
||||
ImportSpecifier: ["imported", "local"],
|
||||
JSXAttribute: ["name", "value"],
|
||||
JSXClosingElement: ["name"],
|
||||
JSXClosingFragment: [],
|
||||
JSXElement: ["openingElement", "children", "closingElement"],
|
||||
JSXEmptyExpression: [],
|
||||
JSXExpressionContainer: ["expression"],
|
||||
JSXFragment: ["openingFragment", "children", "closingFragment"],
|
||||
JSXIdentifier: [],
|
||||
JSXMemberExpression: ["object", "property"],
|
||||
JSXNamespacedName: ["namespace", "name"],
|
||||
JSXOpeningElement: ["name", "attributes"],
|
||||
JSXOpeningFragment: [],
|
||||
JSXSpreadAttribute: ["argument"],
|
||||
JSXSpreadChild: ["expression"],
|
||||
JSXText: [],
|
||||
LabeledStatement: ["label", "body"],
|
||||
Literal: [],
|
||||
LogicalExpression: ["left", "right"],
|
||||
MemberExpression: ["object", "property"],
|
||||
MetaProperty: ["meta", "property"],
|
||||
MethodDefinition: ["key", "value"],
|
||||
NewExpression: ["callee", "arguments"],
|
||||
ObjectExpression: ["properties"],
|
||||
ObjectPattern: ["properties"],
|
||||
PrivateIdentifier: [],
|
||||
Program: ["body"],
|
||||
Property: ["key", "value"],
|
||||
PropertyDefinition: ["key", "value"],
|
||||
RestElement: ["argument"],
|
||||
ReturnStatement: ["argument"],
|
||||
SequenceExpression: ["expressions"],
|
||||
SpreadElement: ["argument"],
|
||||
StaticBlock: ["body"],
|
||||
Super: [],
|
||||
SwitchCase: ["test", "consequent"],
|
||||
SwitchStatement: ["discriminant", "cases"],
|
||||
TaggedTemplateExpression: ["tag", "quasi"],
|
||||
TemplateElement: [],
|
||||
TemplateLiteral: ["quasis", "expressions"],
|
||||
ThisExpression: [],
|
||||
ThrowStatement: ["argument"],
|
||||
TryStatement: ["block", "handler", "finalizer"],
|
||||
UnaryExpression: ["argument"],
|
||||
UpdateExpression: ["argument"],
|
||||
VariableDeclaration: ["declarations"],
|
||||
VariableDeclarator: ["id", "init"],
|
||||
WhileStatement: ["test", "body"],
|
||||
WithStatement: ["object", "body"],
|
||||
YieldExpression: ["argument"],
|
||||
};
|
||||
|
||||
// Types.
|
||||
const NODE_TYPES = Object.keys(KEYS);
|
||||
|
||||
// Freeze the keys.
|
||||
for (const type of NODE_TYPES) {
|
||||
Object.freeze(KEYS[type]);
|
||||
}
|
||||
Object.freeze(KEYS);
|
||||
|
||||
/**
|
||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
||||
* See LICENSE file in root directory for full license.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {import('./visitor-keys.js').VisitorKeys} VisitorKeys
|
||||
*/
|
||||
|
||||
// List to ignore keys.
|
||||
const KEY_BLACKLIST = new Set([
|
||||
"parent",
|
||||
"leadingComments",
|
||||
"trailingComments",
|
||||
]);
|
||||
|
||||
/**
|
||||
* Check whether a given key should be used or not.
|
||||
* @param {string} key The key to check.
|
||||
* @returns {boolean} `true` if the key should be used.
|
||||
*/
|
||||
function filterKey(key) {
|
||||
return !KEY_BLACKLIST.has(key) && key[0] !== "_";
|
||||
}
|
||||
|
||||
/* eslint-disable jsdoc/valid-types -- doesn't allow `readonly`.
|
||||
TODO: remove eslint-disable when https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/164 is fixed
|
||||
*/
|
||||
/**
|
||||
* Get visitor keys of a given node.
|
||||
* @param {Object} node The AST node to get keys.
|
||||
* @returns {readonly string[]} Visitor keys of the node.
|
||||
*/
|
||||
function getKeys(node) {
|
||||
return Object.keys(node).filter(filterKey);
|
||||
}
|
||||
/* eslint-enable jsdoc/valid-types -- doesn't allow `readonly` */
|
||||
|
||||
/**
|
||||
* Make the union set with `KEYS` and given keys.
|
||||
* @param {VisitorKeys} additionalKeys The additional keys.
|
||||
* @returns {VisitorKeys} The union set.
|
||||
*/
|
||||
function unionWith(additionalKeys) {
|
||||
const retv =
|
||||
/** @type {{ [type: string]: ReadonlyArray<string> }} */
|
||||
(Object.assign({}, KEYS));
|
||||
|
||||
for (const type of Object.keys(additionalKeys)) {
|
||||
if (Object.hasOwn(retv, type)) {
|
||||
const keys = new Set(additionalKeys[type]);
|
||||
|
||||
for (const key of retv[type]) {
|
||||
keys.add(key);
|
||||
}
|
||||
|
||||
retv[type] = Object.freeze(Array.from(keys));
|
||||
} else {
|
||||
retv[type] = Object.freeze(Array.from(additionalKeys[type]));
|
||||
}
|
||||
}
|
||||
|
||||
return Object.freeze(retv);
|
||||
}
|
||||
|
||||
exports.KEYS = KEYS;
|
||||
exports.getKeys = getKeys;
|
||||
exports.unionWith = unionWith;
|
||||
@@ -0,0 +1 @@
|
||||
export * from './dist/types.js'
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,477 @@
|
||||
// @ts-self-types="./retrier.d.ts"
|
||||
/**
|
||||
* @fileoverview A utility for retrying failed async method calls.
|
||||
*/
|
||||
|
||||
/* global setTimeout, clearTimeout */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constants
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const MAX_TASK_TIMEOUT = 60000;
|
||||
const MAX_TASK_DELAY = 100;
|
||||
const MAX_CONCURRENCY = 1000;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Logs a message to the console if the DEBUG environment variable is set.
|
||||
* @param {string} message The message to log.
|
||||
* @returns {void}
|
||||
*/
|
||||
function debug(message) {
|
||||
if (globalThis?.process?.env.DEBUG === "@hwc/retry") {
|
||||
console.debug(message);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The following logic has been extracted from graceful-fs.
|
||||
*
|
||||
* The ISC License
|
||||
*
|
||||
* Copyright (c) 2011-2023 Isaac Z. Schlueter, Ben Noordhuis, and Contributors
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Checks if it is time to retry a task based on the timestamp and last attempt time.
|
||||
* @param {RetryTask} task The task to check.
|
||||
* @param {number} maxDelay The maximum delay for the queue.
|
||||
* @returns {boolean} true if it is time to retry, false otherwise.
|
||||
*/
|
||||
function isTimeToRetry(task, maxDelay) {
|
||||
const timeSinceLastAttempt = Date.now() - task.lastAttempt;
|
||||
const timeSinceStart = Math.max(task.lastAttempt - task.timestamp, 1);
|
||||
const desiredDelay = Math.min(timeSinceStart * 1.2, maxDelay);
|
||||
|
||||
return timeSinceLastAttempt >= desiredDelay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if it is time to bail out based on the given timestamp.
|
||||
* @param {RetryTask} task The task to check.
|
||||
* @param {number} timeout The timeout for the queue.
|
||||
* @returns {boolean} true if it is time to bail, false otherwise.
|
||||
*/
|
||||
function isTimeToBail(task, timeout) {
|
||||
return task.age > timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new promise with resolve and reject functions.
|
||||
* @returns {{promise:Promise<any>, resolve:(value:any) => any, reject: (value:any) => any}} A new promise.
|
||||
*/
|
||||
function createPromise() {
|
||||
if (Promise.withResolvers) {
|
||||
return Promise.withResolvers();
|
||||
}
|
||||
|
||||
let resolve, reject;
|
||||
|
||||
const promise = new Promise((res, rej) => {
|
||||
resolve = res;
|
||||
reject = rej;
|
||||
});
|
||||
|
||||
if (resolve === undefined || reject === undefined) {
|
||||
throw new Error("Promise executor did not initialize resolve or reject.");
|
||||
}
|
||||
|
||||
return { promise, resolve, reject };
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A class to represent a task in the retry queue.
|
||||
*/
|
||||
class RetryTask {
|
||||
|
||||
/**
|
||||
* The unique ID for the task.
|
||||
* @type {string}
|
||||
*/
|
||||
id = Math.random().toString(36).slice(2);
|
||||
|
||||
/**
|
||||
* The function to call.
|
||||
* @type {Function}
|
||||
*/
|
||||
fn;
|
||||
|
||||
/**
|
||||
* The error that was thrown.
|
||||
* @type {Error}
|
||||
*/
|
||||
error;
|
||||
|
||||
/**
|
||||
* The timestamp of the task.
|
||||
* @type {number}
|
||||
*/
|
||||
timestamp = Date.now();
|
||||
|
||||
/**
|
||||
* The timestamp of the last attempt.
|
||||
* @type {number}
|
||||
*/
|
||||
lastAttempt = this.timestamp;
|
||||
|
||||
/**
|
||||
* The resolve function for the promise.
|
||||
* @type {Function}
|
||||
*/
|
||||
resolve;
|
||||
|
||||
/**
|
||||
* The reject function for the promise.
|
||||
* @type {Function}
|
||||
*/
|
||||
reject;
|
||||
|
||||
/**
|
||||
* The AbortSignal to monitor for cancellation.
|
||||
* @type {AbortSignal|undefined}
|
||||
*/
|
||||
signal;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Function} fn The function to call.
|
||||
* @param {Error} error The error that was thrown.
|
||||
* @param {Function} resolve The resolve function for the promise.
|
||||
* @param {Function} reject The reject function for the promise.
|
||||
* @param {AbortSignal|undefined} signal The AbortSignal to monitor for cancellation.
|
||||
*/
|
||||
constructor(fn, error, resolve, reject, signal) {
|
||||
this.fn = fn;
|
||||
this.error = error;
|
||||
this.timestamp = Date.now();
|
||||
this.lastAttempt = Date.now();
|
||||
this.resolve = resolve;
|
||||
this.reject = reject;
|
||||
this.signal = signal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the age of the task.
|
||||
* @returns {number} The age of the task in milliseconds.
|
||||
* @readonly
|
||||
*/
|
||||
get age() {
|
||||
return Date.now() - this.timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A class that manages a queue of retry jobs.
|
||||
*/
|
||||
class Retrier {
|
||||
|
||||
/**
|
||||
* Represents the queue for processing tasks.
|
||||
* @type {Array<RetryTask>}
|
||||
*/
|
||||
#retrying = [];
|
||||
|
||||
/**
|
||||
* Represents the queue for pending tasks.
|
||||
* @type {Array<Function>}
|
||||
*/
|
||||
#pending = [];
|
||||
|
||||
/**
|
||||
* The number of tasks currently being processed.
|
||||
* @type {number}
|
||||
*/
|
||||
#working = 0;
|
||||
|
||||
/**
|
||||
* The timeout for the queue.
|
||||
* @type {number}
|
||||
*/
|
||||
#timeout;
|
||||
|
||||
/**
|
||||
* The maximum delay for the queue.
|
||||
* @type {number}
|
||||
*/
|
||||
#maxDelay;
|
||||
|
||||
/**
|
||||
* The setTimeout() timer ID.
|
||||
* @type {NodeJS.Timeout|undefined}
|
||||
*/
|
||||
#timerId;
|
||||
|
||||
/**
|
||||
* The function to call.
|
||||
* @type {Function}
|
||||
*/
|
||||
#check;
|
||||
|
||||
/**
|
||||
* The maximum number of concurrent tasks.
|
||||
* @type {number}
|
||||
*/
|
||||
#concurrency;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Function} check The function to call.
|
||||
* @param {object} [options] The options for the instance.
|
||||
* @param {number} [options.timeout] The timeout for the queue.
|
||||
* @param {number} [options.maxDelay] The maximum delay for the queue.
|
||||
* @param {number} [options.concurrency] The maximum number of concurrent tasks.
|
||||
*/
|
||||
constructor(check, { timeout = MAX_TASK_TIMEOUT, maxDelay = MAX_TASK_DELAY, concurrency = MAX_CONCURRENCY } = {}) {
|
||||
|
||||
if (typeof check !== "function") {
|
||||
throw new Error("Missing function to check errors");
|
||||
}
|
||||
|
||||
this.#check = check;
|
||||
this.#timeout = timeout;
|
||||
this.#maxDelay = maxDelay;
|
||||
this.#concurrency = concurrency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of tasks waiting to be retried.
|
||||
* @returns {number} The number of tasks in the retry queue.
|
||||
*/
|
||||
get retrying() {
|
||||
return this.#retrying.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of tasks waiting to be processed in the pending queue.
|
||||
* @returns {number} The number of tasks in the pending queue.
|
||||
*/
|
||||
get pending() {
|
||||
return this.#pending.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of tasks currently being processed.
|
||||
* @returns {number} The number of tasks currently being processed.
|
||||
*/
|
||||
get working() {
|
||||
return this.#working;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the function and retries if it fails.
|
||||
* @param {Function} fn The function to call.
|
||||
* @param {Object} options The options for the job.
|
||||
* @param {AbortSignal} [options.signal] The AbortSignal to monitor for cancellation.
|
||||
* @param {Promise<any>} options.promise The promise to return when the function settles.
|
||||
* @param {Function} options.resolve The resolve function for the promise.
|
||||
* @param {Function} options.reject The reject function for the promise.
|
||||
* @returns {Promise<any>} A promise that resolves when the function is
|
||||
* called successfully.
|
||||
*/
|
||||
#call(fn, { signal, promise, resolve, reject }) {
|
||||
|
||||
let result;
|
||||
|
||||
try {
|
||||
result = fn();
|
||||
} catch (/** @type {any} */ error) {
|
||||
reject(new Error(`Synchronous error: ${error.message}`, { cause: error }));
|
||||
return promise;
|
||||
}
|
||||
|
||||
// if the result is not a promise then reject an error
|
||||
if (!result || typeof result.then !== "function") {
|
||||
reject(new Error("Result is not a promise."));
|
||||
return promise;
|
||||
}
|
||||
|
||||
this.#working++;
|
||||
promise.finally(() => {
|
||||
this.#working--;
|
||||
this.#processPending();
|
||||
})
|
||||
// `promise.finally` creates a new promise that may be rejected, so it must be handled.
|
||||
.catch(() => { });
|
||||
|
||||
// call the original function and catch any ENFILE or EMFILE errors
|
||||
Promise.resolve(result)
|
||||
.then(value => {
|
||||
debug("Function called successfully without retry.");
|
||||
resolve(value);
|
||||
})
|
||||
.catch(error => {
|
||||
if (!this.#check(error)) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
const task = new RetryTask(fn, error, resolve, reject, signal);
|
||||
|
||||
debug(`Function failed, queuing for retry with task ${task.id}.`);
|
||||
this.#retrying.push(task);
|
||||
|
||||
signal?.addEventListener("abort", () => {
|
||||
debug(`Task ${task.id} was aborted due to AbortSignal.`);
|
||||
reject(signal.reason);
|
||||
});
|
||||
|
||||
this.#processQueue();
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new retry job to the queue.
|
||||
* @template {(...args: unknown[]) => Promise<unknown>} Func
|
||||
* @template {Awaited<ReturnType<Func>>} RetVal
|
||||
* @param {Func} fn The function to call.
|
||||
* @param {object} [options] The options for the job.
|
||||
* @param {AbortSignal} [options.signal] The AbortSignal to monitor for cancellation.
|
||||
* @returns {Promise<RetVal>} A promise that resolves when the queue is processed.
|
||||
*/
|
||||
retry(fn, { signal } = {}) {
|
||||
|
||||
signal?.throwIfAborted();
|
||||
|
||||
const { promise, resolve, reject } = createPromise();
|
||||
|
||||
this.#pending.push(() => this.#call(fn, { signal, promise, resolve, reject }));
|
||||
this.#processPending();
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Processes the pending queue and the retry queue.
|
||||
* @returns {void}
|
||||
*/
|
||||
#processAll() {
|
||||
if (this.pending) {
|
||||
this.#processPending();
|
||||
}
|
||||
|
||||
if (this.retrying) {
|
||||
this.#processQueue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the pending queue to see which tasks can be started.
|
||||
* @returns {void}
|
||||
*/
|
||||
#processPending() {
|
||||
|
||||
debug(`Processing pending tasks: ${this.pending} pending, ${this.working} working.`);
|
||||
|
||||
const available = this.#concurrency - this.working;
|
||||
|
||||
if (available <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const count = Math.min(this.pending, available);
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const task = this.#pending.shift();
|
||||
task?.();
|
||||
}
|
||||
|
||||
debug(`Processed pending tasks: ${this.pending} pending, ${this.working} working.`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the queue.
|
||||
* @returns {void}
|
||||
*/
|
||||
#processQueue() {
|
||||
// clear any timer because we're going to check right now
|
||||
clearTimeout(this.#timerId);
|
||||
this.#timerId = undefined;
|
||||
|
||||
debug(`Processing retry queue: ${this.retrying} retrying, ${this.working} working.`);
|
||||
|
||||
const processAgain = () => {
|
||||
this.#timerId = setTimeout(() => this.#processAll(), 0);
|
||||
};
|
||||
|
||||
// if there's nothing in the queue, we're done
|
||||
const task = this.#retrying.shift();
|
||||
if (!task) {
|
||||
debug("Queue is empty, exiting.");
|
||||
|
||||
if (this.pending) {
|
||||
processAgain();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// if it's time to bail, then bail
|
||||
if (isTimeToBail(task, this.#timeout)) {
|
||||
debug(`Task ${task.id} was abandoned due to timeout.`);
|
||||
task.reject(task.error);
|
||||
processAgain();
|
||||
return;
|
||||
}
|
||||
|
||||
// if it's not time to retry, then wait and try again
|
||||
if (!isTimeToRetry(task, this.#maxDelay)) {
|
||||
debug(`Task ${task.id} is not ready to retry, skipping.`);
|
||||
this.#retrying.push(task);
|
||||
processAgain();
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise, try again
|
||||
task.lastAttempt = Date.now();
|
||||
|
||||
// Promise.resolve needed in case it's a thenable but not a Promise
|
||||
Promise.resolve(task.fn())
|
||||
// @ts-ignore because we know it's any
|
||||
.then(result => {
|
||||
debug(`Task ${task.id} succeeded after ${task.age}ms.`);
|
||||
task.resolve(result);
|
||||
})
|
||||
|
||||
// @ts-ignore because we know it's any
|
||||
.catch(error => {
|
||||
if (!this.#check(error)) {
|
||||
debug(`Task ${task.id} failed with non-retryable error: ${error.message}.`);
|
||||
task.reject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
// update the task timestamp and push to back of queue to try again
|
||||
task.lastAttempt = Date.now();
|
||||
this.#retrying.push(task);
|
||||
debug(`Task ${task.id} failed, requeueing to try again.`);
|
||||
})
|
||||
.finally(() => {
|
||||
this.#processAll();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export { Retrier };
|
||||
@@ -0,0 +1,36 @@
|
||||
'use strict'
|
||||
|
||||
const test = require('node:test')
|
||||
const assert = require('node:assert')
|
||||
const { PassThrough } = require('node:stream')
|
||||
|
||||
const { sink, once } = require('./helper')
|
||||
const pino = require('../')
|
||||
|
||||
test('Proxy and stream objects', async () => {
|
||||
const s = new PassThrough()
|
||||
s.resume()
|
||||
s.write('', () => {})
|
||||
const obj = { s, p: new Proxy({}, { get () { throw new Error('kaboom') } }) }
|
||||
const stream = sink()
|
||||
const instance = pino(stream)
|
||||
instance.info({ obj })
|
||||
|
||||
const result = await once(stream, 'data')
|
||||
|
||||
assert.equal(result.obj, '[unable to serialize, circular reference is too complex to analyze]')
|
||||
})
|
||||
|
||||
test('Proxy and stream objects', async () => {
|
||||
const s = new PassThrough()
|
||||
s.resume()
|
||||
s.write('', () => {})
|
||||
const obj = { s, p: new Proxy({}, { get () { throw new Error('kaboom') } }) }
|
||||
const stream = sink()
|
||||
const instance = pino(stream)
|
||||
instance.info(obj)
|
||||
|
||||
const result = await once(stream, 'data')
|
||||
|
||||
assert.equal(result.p, '[unable to serialize, circular reference is too complex to analyze]')
|
||||
})
|
||||
@@ -0,0 +1,50 @@
|
||||
import type { Node, NodeArray } from "./ast.ts";
|
||||
/**
|
||||
* A callback that receives a node and returns a visited node (or undefined to remove it).
|
||||
*/
|
||||
export type Visitor = (node: Node) => Node | undefined;
|
||||
/**
|
||||
* Visits a Node using the supplied visitor, possibly returning a new Node in its place.
|
||||
*
|
||||
* - If the input node is undefined, then the output is undefined.
|
||||
* - If the visitor returns undefined, then the output is undefined.
|
||||
* - If the output node is not undefined, then it will satisfy the test function.
|
||||
* - In order to obtain a return type that is more specific than `Node`, a test
|
||||
* function must be provided, and that function must be a type predicate.
|
||||
*
|
||||
* @param node The Node to visit.
|
||||
* @param visitor The callback used to visit the Node.
|
||||
* @param test A callback to execute to verify the Node is valid.
|
||||
*/
|
||||
export declare function visitNode<TIn extends Node | undefined, TOut extends Node>(node: TIn, visitor: Visitor, test: (node: Node) => node is TOut): TOut | (TIn & undefined);
|
||||
/**
|
||||
* Visits a Node using the supplied visitor, possibly returning a new Node in its place.
|
||||
*
|
||||
* - If the input node is undefined, then the output is undefined.
|
||||
* - If the visitor returns undefined, then the output is undefined.
|
||||
*
|
||||
* @param node The Node to visit.
|
||||
* @param visitor The callback used to visit the Node.
|
||||
* @param test An optional callback to execute to verify the Node is valid.
|
||||
*/
|
||||
export declare function visitNode<TIn extends Node | undefined>(node: TIn, visitor: Visitor, test?: (node: Node) => boolean): Node | (TIn & undefined);
|
||||
/**
|
||||
* Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place.
|
||||
*
|
||||
* - If the input node array is undefined, the output is undefined.
|
||||
* - If the visitor returns undefined for a node, that node is dropped from the result.
|
||||
*/
|
||||
export declare function visitNodes<T extends Node>(nodes: NodeArray<T>, visitor: Visitor): NodeArray<T>;
|
||||
export declare function visitNodes<T extends Node>(nodes: NodeArray<T> | undefined, visitor: Visitor): NodeArray<T> | undefined;
|
||||
export declare function visitNodesArray<T extends Node>(nodes: readonly T[], visitor: Visitor): readonly T[];
|
||||
export declare function visitNodesArray<T extends Node>(nodes: readonly T[] | undefined, visitor: Visitor): readonly T[] | undefined;
|
||||
/**
|
||||
* Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place.
|
||||
*
|
||||
* @param node The Node whose children will be visited.
|
||||
* @param visitor The callback used to visit each child.
|
||||
* @returns The original node if no children changed, or a new node with visited children.
|
||||
*/
|
||||
export declare function visitEachChild<T extends Node>(node: T, visitor: Visitor): T;
|
||||
export declare function visitEachChild<T extends Node>(node: T | undefined, visitor: Visitor): T | undefined;
|
||||
//# sourceMappingURL=visitor.generated.d.ts.map
|
||||
@@ -0,0 +1,31 @@
|
||||
"use strict";
|
||||
|
||||
function _ts_generator(thisArg, body) {
|
||||
var f, y, t, _ = { label: 0, sent: function () { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
|
||||
return d(g, "next", { value: verb(0) }), d(g, "throw", { value: verb(1) }), d(g, "return", { value: verb(2) }), typeof Symbol === "function" && d(g, Symbol.iterator, { value: function () { return this; } }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
}
|
||||
|
||||
exports._ = _ts_generator;
|
||||
@@ -0,0 +1,52 @@
|
||||
import { SolanaError } from './error';
|
||||
type TransactionError = string | {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
/**
|
||||
* Keep in sync with https://github.com/anza-xyz/agave/blob/master/rpc-client-types/src/response.rs
|
||||
* @hidden
|
||||
*/
|
||||
export interface RpcSimulateTransactionResult {
|
||||
accounts: ({
|
||||
data: string | {
|
||||
parsed: unknown;
|
||||
program: string;
|
||||
space: number;
|
||||
} | [encodedBytes: string, encoding: 'base58' | 'base64' | 'base64+zstd' | 'binary' | 'jsonParsed'];
|
||||
executable: boolean;
|
||||
lamports: number;
|
||||
owner: string;
|
||||
rentEpoch: number;
|
||||
space?: number;
|
||||
} | null)[] | null;
|
||||
err: TransactionError | null;
|
||||
innerInstructions?: {
|
||||
index: number;
|
||||
instructions: ({
|
||||
accounts: number[];
|
||||
data: string;
|
||||
programIdIndex: number;
|
||||
stackHeight?: number;
|
||||
} | {
|
||||
parsed: unknown;
|
||||
program: string;
|
||||
programId: string;
|
||||
stackHeight?: number;
|
||||
} | {
|
||||
accounts: string[];
|
||||
data: string;
|
||||
programId: string;
|
||||
stackHeight?: number;
|
||||
})[];
|
||||
}[] | null;
|
||||
logs: string[] | null;
|
||||
replacementBlockhash: string | null;
|
||||
returnData: {
|
||||
data: [string, 'base64'];
|
||||
programId: string;
|
||||
} | null;
|
||||
unitsConsumed: bigint | null;
|
||||
}
|
||||
export declare function getSolanaErrorFromJsonRpcError(putativeErrorResponse: unknown): SolanaError;
|
||||
export {};
|
||||
//# sourceMappingURL=json-rpc-error.d.ts.map
|
||||
@@ -0,0 +1,92 @@
|
||||
// Generated by LiveScript 1.6.0
|
||||
var split, join, lines, unlines, words, unwords, chars, unchars, reverse, repeat, capitalize, camelize, dasherize;
|
||||
split = curry$(function(sep, str){
|
||||
return str.split(sep);
|
||||
});
|
||||
join = curry$(function(sep, xs){
|
||||
return xs.join(sep);
|
||||
});
|
||||
lines = function(str){
|
||||
if (!str.length) {
|
||||
return [];
|
||||
}
|
||||
return str.split('\n');
|
||||
};
|
||||
unlines = function(it){
|
||||
return it.join('\n');
|
||||
};
|
||||
words = function(str){
|
||||
if (!str.length) {
|
||||
return [];
|
||||
}
|
||||
return str.split(/[ ]+/);
|
||||
};
|
||||
unwords = function(it){
|
||||
return it.join(' ');
|
||||
};
|
||||
chars = function(it){
|
||||
return it.split('');
|
||||
};
|
||||
unchars = function(it){
|
||||
return it.join('');
|
||||
};
|
||||
reverse = function(str){
|
||||
return str.split('').reverse().join('');
|
||||
};
|
||||
repeat = curry$(function(n, str){
|
||||
var result, i$;
|
||||
result = '';
|
||||
for (i$ = 0; i$ < n; ++i$) {
|
||||
result += str;
|
||||
}
|
||||
return result;
|
||||
});
|
||||
capitalize = function(str){
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
};
|
||||
camelize = function(it){
|
||||
return it.replace(/[-_]+(.)?/g, function(arg$, c){
|
||||
return (c != null ? c : '').toUpperCase();
|
||||
});
|
||||
};
|
||||
dasherize = function(str){
|
||||
return str.replace(/([^-A-Z])([A-Z]+)/g, function(arg$, lower, upper){
|
||||
return lower + "-" + (upper.length > 1
|
||||
? upper
|
||||
: upper.toLowerCase());
|
||||
}).replace(/^([A-Z]+)/, function(arg$, upper){
|
||||
if (upper.length > 1) {
|
||||
return upper + "-";
|
||||
} else {
|
||||
return upper.toLowerCase();
|
||||
}
|
||||
});
|
||||
};
|
||||
module.exports = {
|
||||
split: split,
|
||||
join: join,
|
||||
lines: lines,
|
||||
unlines: unlines,
|
||||
words: words,
|
||||
unwords: unwords,
|
||||
chars: chars,
|
||||
unchars: unchars,
|
||||
reverse: reverse,
|
||||
repeat: repeat,
|
||||
capitalize: capitalize,
|
||||
camelize: camelize,
|
||||
dasherize: dasherize
|
||||
};
|
||||
function curry$(f, bound){
|
||||
var context,
|
||||
_curry = function(args) {
|
||||
return f.length > 1 ? function(){
|
||||
var params = args ? args.concat() : [];
|
||||
context = bound ? context || this : this;
|
||||
return params.push.apply(params, arguments) <
|
||||
f.length && arguments.length ?
|
||||
_curry.call(context, params) : f.apply(context, params);
|
||||
} : f;
|
||||
};
|
||||
return _curry();
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
'use strict'
|
||||
|
||||
const test = require('node:test')
|
||||
const assert = require('node:assert')
|
||||
const os = require('node:os')
|
||||
const { join } = require('node:path')
|
||||
const { readFile, symlink, unlink, mkdir, writeFile } = require('node:fs').promises
|
||||
const { once } = require('node:events')
|
||||
const execa = require('execa')
|
||||
const rimraf = require('rimraf')
|
||||
|
||||
const { isWin, isYarnPnp, watchFileCreated, file } = require('../helper')
|
||||
const pino = require('../../')
|
||||
|
||||
const { pid } = process
|
||||
const hostname = os.hostname()
|
||||
|
||||
async function installTransportModule (target) {
|
||||
if (isYarnPnp) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
await uninstallTransportModule()
|
||||
} catch {}
|
||||
|
||||
if (!target) {
|
||||
target = join(__dirname, '..', '..')
|
||||
}
|
||||
|
||||
await symlink(
|
||||
join(__dirname, '..', 'fixtures', 'transport'),
|
||||
join(target, 'node_modules', 'transport')
|
||||
)
|
||||
}
|
||||
|
||||
async function uninstallTransportModule () {
|
||||
if (isYarnPnp) {
|
||||
return
|
||||
}
|
||||
await unlink(join(__dirname, '..', '..', 'node_modules', 'transport'))
|
||||
}
|
||||
|
||||
// TODO make this test pass on Windows
|
||||
test('pino.transport with package', { skip: isWin }, async (t) => {
|
||||
const destination = file()
|
||||
|
||||
await installTransportModule()
|
||||
|
||||
const transport = pino.transport({
|
||||
target: 'transport',
|
||||
options: { destination }
|
||||
})
|
||||
|
||||
t.after(async () => {
|
||||
await uninstallTransportModule()
|
||||
transport.end()
|
||||
})
|
||||
const instance = pino(transport)
|
||||
instance.info('hello')
|
||||
await watchFileCreated(destination)
|
||||
const result = JSON.parse(await readFile(destination))
|
||||
delete result.time
|
||||
assert.deepEqual(result, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
|
||||
// TODO make this test pass on Windows
|
||||
test('pino.transport with package as a target', { skip: isWin }, async (t) => {
|
||||
const destination = file()
|
||||
|
||||
await installTransportModule()
|
||||
|
||||
const transport = pino.transport({
|
||||
targets: [{
|
||||
target: 'transport',
|
||||
options: { destination }
|
||||
}]
|
||||
})
|
||||
t.after(async () => {
|
||||
await uninstallTransportModule()
|
||||
transport.end()
|
||||
})
|
||||
const instance = pino(transport)
|
||||
instance.info('hello')
|
||||
await watchFileCreated(destination)
|
||||
const result = JSON.parse(await readFile(destination))
|
||||
delete result.time
|
||||
assert.deepEqual(result, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
|
||||
// TODO make this test pass on Windows
|
||||
test('pino({ transport })', { skip: isWin || isYarnPnp }, async (t) => {
|
||||
const folder = join(
|
||||
os.tmpdir(),
|
||||
'_' + Math.random().toString(36).substr(2, 9)
|
||||
)
|
||||
|
||||
t.after(() => {
|
||||
rimraf.sync(folder)
|
||||
})
|
||||
|
||||
const destination = join(folder, 'output')
|
||||
|
||||
await mkdir(join(folder, 'node_modules'), { recursive: true })
|
||||
|
||||
// Link pino
|
||||
await symlink(
|
||||
join(__dirname, '..', '..'),
|
||||
join(folder, 'node_modules', 'pino')
|
||||
)
|
||||
|
||||
await installTransportModule(folder)
|
||||
|
||||
const toRun = join(folder, 'index.js')
|
||||
|
||||
const toRunContent = `
|
||||
const pino = require('pino')
|
||||
const logger = pino({
|
||||
transport: {
|
||||
target: 'transport',
|
||||
options: { destination: '${destination}' }
|
||||
}
|
||||
})
|
||||
logger.info('hello')
|
||||
`
|
||||
|
||||
await writeFile(toRun, toRunContent)
|
||||
|
||||
const child = execa(process.argv[0], [toRun])
|
||||
|
||||
await once(child, 'close')
|
||||
|
||||
const result = JSON.parse(await readFile(destination))
|
||||
delete result.time
|
||||
assert.deepEqual(result, {
|
||||
pid: child.pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
|
||||
// TODO make this test pass on Windows
|
||||
test('pino({ transport }) from a wrapped dependency', { skip: isWin || isYarnPnp }, async (t) => {
|
||||
const folder = join(
|
||||
os.tmpdir(),
|
||||
'_' + Math.random().toString(36).substr(2, 9)
|
||||
)
|
||||
|
||||
const wrappedFolder = join(
|
||||
os.tmpdir(),
|
||||
'_' + Math.random().toString(36).substr(2, 9)
|
||||
)
|
||||
|
||||
const destination = join(folder, 'output')
|
||||
|
||||
await mkdir(join(folder, 'node_modules'), { recursive: true })
|
||||
await mkdir(join(wrappedFolder, 'node_modules'), { recursive: true })
|
||||
|
||||
t.after(() => {
|
||||
rimraf.sync(wrappedFolder)
|
||||
rimraf.sync(folder)
|
||||
})
|
||||
|
||||
// Link pino
|
||||
await symlink(
|
||||
join(__dirname, '..', '..'),
|
||||
join(wrappedFolder, 'node_modules', 'pino')
|
||||
)
|
||||
|
||||
// Link get-caller-file
|
||||
await symlink(
|
||||
join(__dirname, '..', '..', 'node_modules', 'get-caller-file'),
|
||||
join(wrappedFolder, 'node_modules', 'get-caller-file')
|
||||
)
|
||||
|
||||
// Link wrapped
|
||||
await symlink(
|
||||
wrappedFolder,
|
||||
join(folder, 'node_modules', 'wrapped')
|
||||
)
|
||||
|
||||
await installTransportModule(folder)
|
||||
|
||||
const pkgjsonContent = {
|
||||
name: 'pino'
|
||||
}
|
||||
|
||||
await writeFile(join(wrappedFolder, 'package.json'), JSON.stringify(pkgjsonContent))
|
||||
|
||||
const wrapped = join(wrappedFolder, 'index.js')
|
||||
|
||||
const wrappedContent = `
|
||||
const pino = require('pino')
|
||||
const getCaller = require('get-caller-file')
|
||||
|
||||
module.exports = function build () {
|
||||
const logger = pino({
|
||||
transport: {
|
||||
caller: getCaller(),
|
||||
target: 'transport',
|
||||
options: { destination: '${destination}' }
|
||||
}
|
||||
})
|
||||
return logger
|
||||
}
|
||||
`
|
||||
|
||||
await writeFile(wrapped, wrappedContent)
|
||||
|
||||
const toRun = join(folder, 'index.js')
|
||||
|
||||
const toRunContent = `
|
||||
const logger = require('wrapped')()
|
||||
logger.info('hello')
|
||||
`
|
||||
|
||||
await writeFile(toRun, toRunContent)
|
||||
|
||||
const child = execa(process.argv[0], [toRun])
|
||||
|
||||
await once(child, 'close')
|
||||
|
||||
const result = JSON.parse(await readFile(destination))
|
||||
delete result.time
|
||||
assert.deepEqual(result, {
|
||||
pid: child.pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,2 @@
|
||||
// This is a syntax error
|
||||
import
|
||||
@@ -0,0 +1,24 @@
|
||||
export * from './account';
|
||||
export * from './blockhash';
|
||||
export * from './bpf-loader-deprecated';
|
||||
export * from './bpf-loader';
|
||||
export * from './connection';
|
||||
export * from './epoch-schedule';
|
||||
export * from './errors';
|
||||
export * from './fee-calculator';
|
||||
export * from './keypair';
|
||||
export * from './loader';
|
||||
export * from './message';
|
||||
export * from './nonce-account';
|
||||
export * from './programs';
|
||||
export * from './publickey';
|
||||
export * from './transaction';
|
||||
export * from './validator-info';
|
||||
export * from './vote-account';
|
||||
export * from './sysvar';
|
||||
export * from './utils';
|
||||
|
||||
/**
|
||||
* There are 1-billion lamports in one SOL
|
||||
*/
|
||||
export const LAMPORTS_PER_SOL = 1000000000;
|
||||
@@ -0,0 +1,331 @@
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
const toStringFunction = Function.prototype.toString;
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
const toStringObject = Object.prototype.toString;
|
||||
/**
|
||||
* Get an empty version of the object with the same prototype it has.
|
||||
*/
|
||||
function getCleanClone(prototype) {
|
||||
if (!prototype) {
|
||||
return Object.create(null);
|
||||
}
|
||||
const Constructor = prototype.constructor;
|
||||
if (Constructor === Object) {
|
||||
return prototype === Object.prototype ? {} : Object.create(prototype);
|
||||
}
|
||||
if (Constructor && ~toStringFunction.call(Constructor).indexOf('[native code]')) {
|
||||
try {
|
||||
return new Constructor();
|
||||
}
|
||||
catch (_a) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
return Object.create(prototype);
|
||||
}
|
||||
/**
|
||||
* Get the tag of the value passed, so that the correct copier can be used.
|
||||
*/
|
||||
function getTag(value) {
|
||||
const stringTag = value[Symbol.toStringTag];
|
||||
if (stringTag) {
|
||||
return stringTag;
|
||||
}
|
||||
const type = toStringObject.call(value);
|
||||
return type.substring(8, type.length - 1);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
const { propertyIsEnumerable } = Object.prototype;
|
||||
function copyOwnDescriptor(original, clone, property, state) {
|
||||
const ownDescriptor = Object.getOwnPropertyDescriptor(original, property) || {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
value: original[property],
|
||||
writable: true,
|
||||
};
|
||||
const descriptor = ownDescriptor.get || ownDescriptor.set
|
||||
? ownDescriptor
|
||||
: {
|
||||
configurable: ownDescriptor.configurable,
|
||||
enumerable: ownDescriptor.enumerable,
|
||||
value: state.copier(ownDescriptor.value, state),
|
||||
writable: ownDescriptor.writable,
|
||||
};
|
||||
try {
|
||||
Object.defineProperty(clone, property, descriptor);
|
||||
}
|
||||
catch (_a) {
|
||||
// The above can fail on node in extreme edge cases, so fall back to the loose assignment.
|
||||
clone[property] = descriptor.get ? descriptor.get() : descriptor.value;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Strictly copy all properties contained on the object.
|
||||
*/
|
||||
function copyOwnPropertiesStrict(value, clone, state) {
|
||||
for (const name of Object.getOwnPropertyNames(value)) {
|
||||
copyOwnDescriptor(value, clone, name, state);
|
||||
}
|
||||
for (const symbol of Object.getOwnPropertySymbols(value)) {
|
||||
copyOwnDescriptor(value, clone, symbol, state);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
/**
|
||||
* Deeply copy the indexed values in the array.
|
||||
*/
|
||||
function copyArrayLoose(array, state) {
|
||||
const clone = new state.Constructor();
|
||||
// set in the cache immediately to be able to reuse the object recursively
|
||||
state.cache.set(array, clone);
|
||||
for (let index = 0; index < array.length; ++index) {
|
||||
clone[index] = state.copier(array[index], state);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
/**
|
||||
* Deeply copy the indexed values in the array, as well as any custom properties.
|
||||
*/
|
||||
function copyArrayStrict(array, state) {
|
||||
const clone = new state.Constructor();
|
||||
// set in the cache immediately to be able to reuse the object recursively
|
||||
state.cache.set(array, clone);
|
||||
return copyOwnPropertiesStrict(array, clone, state);
|
||||
}
|
||||
/**
|
||||
* Copy the contents of the ArrayBuffer.
|
||||
*/
|
||||
function copyArrayBuffer(arrayBuffer, _state) {
|
||||
return arrayBuffer.slice(0);
|
||||
}
|
||||
/**
|
||||
* Create a new Blob with the contents of the original.
|
||||
*/
|
||||
function copyBlob(blob, _state) {
|
||||
return blob.slice(0, blob.size, blob.type);
|
||||
}
|
||||
/**
|
||||
* Create a new DataView with the contents of the original.
|
||||
*/
|
||||
function copyDataView(dataView, state) {
|
||||
return new state.Constructor(copyArrayBuffer(dataView.buffer));
|
||||
}
|
||||
/**
|
||||
* Create a new Date based on the time of the original.
|
||||
*/
|
||||
function copyDate(date, state) {
|
||||
return new state.Constructor(date.getTime());
|
||||
}
|
||||
/**
|
||||
* Deeply copy the keys and values of the original.
|
||||
*/
|
||||
function copyMapLoose(map, state) {
|
||||
const clone = new state.Constructor();
|
||||
// set in the cache immediately to be able to reuse the object recursively
|
||||
state.cache.set(map, clone);
|
||||
for (const [key, value] of map) {
|
||||
clone.set(key, state.copier(value, state));
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
/**
|
||||
* Deeply copy the keys and values of the original, as well as any custom properties.
|
||||
*/
|
||||
function copyMapStrict(map, state) {
|
||||
return copyOwnPropertiesStrict(map, copyMapLoose(map, state), state);
|
||||
}
|
||||
/**
|
||||
* Deeply copy the properties (keys and symbols) and values of the original.
|
||||
*/
|
||||
function copyObjectLoose(object, state) {
|
||||
const clone = getCleanClone(state.prototype);
|
||||
// set in the cache immediately to be able to reuse the object recursively
|
||||
state.cache.set(object, clone);
|
||||
for (const key of Object.keys(object)) {
|
||||
clone[key] = state.copier(object[key], state);
|
||||
}
|
||||
for (const symbol of Object.getOwnPropertySymbols(object)) {
|
||||
if (propertyIsEnumerable.call(object, symbol)) {
|
||||
clone[symbol] = state.copier(object[symbol], state);
|
||||
}
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
/**
|
||||
* Deeply copy the properties (keys and symbols) and values of the original, as well
|
||||
* as any hidden or non-enumerable properties.
|
||||
*/
|
||||
function copyObjectStrict(object, state) {
|
||||
const clone = getCleanClone(state.prototype);
|
||||
// set in the cache immediately to be able to reuse the object recursively
|
||||
state.cache.set(object, clone);
|
||||
return copyOwnPropertiesStrict(object, clone, state);
|
||||
}
|
||||
/**
|
||||
* Create a new primitive wrapper from the value of the original.
|
||||
*/
|
||||
function copyPrimitiveWrapper(primitiveObject, state) {
|
||||
return new state.Constructor(primitiveObject.valueOf());
|
||||
}
|
||||
/**
|
||||
* Create a new RegExp based on the value and flags of the original.
|
||||
*/
|
||||
function copyRegExp(regExp, state) {
|
||||
const clone = new state.Constructor(regExp.source, regExp.flags);
|
||||
clone.lastIndex = regExp.lastIndex;
|
||||
return clone;
|
||||
}
|
||||
/**
|
||||
* Return the original value (an identity function).
|
||||
*
|
||||
* @note
|
||||
* THis is used for objects that cannot be copied, such as WeakMap.
|
||||
*/
|
||||
function copySelf(value, _state) {
|
||||
return value;
|
||||
}
|
||||
/**
|
||||
* Deeply copy the values of the original.
|
||||
*/
|
||||
function copySetLoose(set, state) {
|
||||
const clone = new state.Constructor();
|
||||
// set in the cache immediately to be able to reuse the object recursively
|
||||
state.cache.set(set, clone);
|
||||
for (const value of set) {
|
||||
clone.add(state.copier(value, state));
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
/**
|
||||
* Deeply copy the values of the original, as well as any custom properties.
|
||||
*/
|
||||
function copySetStrict(set, state) {
|
||||
return copyOwnPropertiesStrict(set, copySetLoose(set, state), state);
|
||||
}
|
||||
|
||||
function createDefaultCache() {
|
||||
return new WeakMap();
|
||||
}
|
||||
function getOptions({ createCache: createCacheOverride, methods: methodsOverride, strict, }) {
|
||||
const defaultMethods = {
|
||||
array: strict ? copyArrayStrict : copyArrayLoose,
|
||||
arrayBuffer: copyArrayBuffer,
|
||||
asyncGenerator: copySelf,
|
||||
blob: copyBlob,
|
||||
dataView: copyDataView,
|
||||
date: copyDate,
|
||||
error: copySelf,
|
||||
generator: copySelf,
|
||||
map: strict ? copyMapStrict : copyMapLoose,
|
||||
object: strict ? copyObjectStrict : copyObjectLoose,
|
||||
regExp: copyRegExp,
|
||||
set: strict ? copySetStrict : copySetLoose,
|
||||
};
|
||||
const methods = methodsOverride ? Object.assign(defaultMethods, methodsOverride) : defaultMethods;
|
||||
const copiers = getTagSpecificCopiers(methods);
|
||||
const createCache = createCacheOverride || createDefaultCache;
|
||||
// Extra safety check to ensure that object and array copiers are always provided,
|
||||
// avoiding runtime errors.
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (!copiers.Object || !copiers.Array) {
|
||||
throw new Error('An object and array copier must be provided.');
|
||||
}
|
||||
return { createCache, copiers, methods, strict: Boolean(strict) };
|
||||
}
|
||||
/**
|
||||
* Get the copiers used for each specific object tag.
|
||||
*/
|
||||
function getTagSpecificCopiers(methods) {
|
||||
return {
|
||||
Arguments: methods.object,
|
||||
Array: methods.array,
|
||||
ArrayBuffer: methods.arrayBuffer,
|
||||
AsyncGenerator: methods.asyncGenerator,
|
||||
BigInt64Array: methods.arrayBuffer,
|
||||
BigUint64Array: methods.arrayBuffer,
|
||||
Blob: methods.blob,
|
||||
Boolean: copyPrimitiveWrapper,
|
||||
DataView: methods.dataView,
|
||||
Date: methods.date,
|
||||
Error: methods.error,
|
||||
Float32Array: methods.arrayBuffer,
|
||||
Float64Array: methods.arrayBuffer,
|
||||
Generator: methods.generator,
|
||||
Int8Array: methods.arrayBuffer,
|
||||
Int16Array: methods.arrayBuffer,
|
||||
Int32Array: methods.arrayBuffer,
|
||||
Map: methods.map,
|
||||
Number: copyPrimitiveWrapper,
|
||||
Object: methods.object,
|
||||
Promise: copySelf,
|
||||
RegExp: methods.regExp,
|
||||
Set: methods.set,
|
||||
String: copyPrimitiveWrapper,
|
||||
WeakMap: copySelf,
|
||||
WeakSet: copySelf,
|
||||
Uint8Array: methods.arrayBuffer,
|
||||
Uint8ClampedArray: methods.arrayBuffer,
|
||||
Uint16Array: methods.arrayBuffer,
|
||||
Uint32Array: methods.arrayBuffer,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a custom copier based on custom options for any of the following:
|
||||
* - `createCache` method to create a cache for copied objects
|
||||
* - custom copier `methods` for specific object types
|
||||
* - `strict` mode to copy all properties with their descriptors
|
||||
*/
|
||||
function createCopier(options = {}) {
|
||||
const { createCache, copiers } = getOptions(options);
|
||||
const { Array: copyArray, Object: copyObject } = copiers;
|
||||
function copier(value, state) {
|
||||
state.prototype = state.Constructor = undefined;
|
||||
if (!value || typeof value !== 'object') {
|
||||
return value;
|
||||
}
|
||||
if (state.cache.has(value)) {
|
||||
return state.cache.get(value);
|
||||
}
|
||||
state.prototype = Object.getPrototypeOf(value);
|
||||
// Using logical AND for speed, since optional chaining transforms to
|
||||
// a local variable usage.
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
|
||||
state.Constructor = state.prototype && state.prototype.constructor;
|
||||
// plain objects
|
||||
if (!state.Constructor || state.Constructor === Object) {
|
||||
return copyObject(value, state);
|
||||
}
|
||||
// arrays
|
||||
if (Array.isArray(value)) {
|
||||
return copyArray(value, state);
|
||||
}
|
||||
const tagSpecificCopier = copiers[getTag(value)];
|
||||
if (tagSpecificCopier) {
|
||||
return tagSpecificCopier(value, state);
|
||||
}
|
||||
return typeof value.then === 'function' ? value : copyObject(value, state);
|
||||
}
|
||||
return function copy(value) {
|
||||
return copier(value, {
|
||||
Constructor: undefined,
|
||||
cache: createCache(),
|
||||
copier,
|
||||
prototype: undefined,
|
||||
});
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Copy an value deeply as much as possible, where strict recreation of object properties
|
||||
* are maintained. All properties (including non-enumerable ones) are copied with their
|
||||
* original property descriptors on both objects and arrays.
|
||||
*/
|
||||
const copyStrict = createCopier({ strict: true });
|
||||
/**
|
||||
* Copy an value deeply as much as possible.
|
||||
*/
|
||||
const copy = createCopier();
|
||||
|
||||
export { copy, copyStrict, createCopier };
|
||||
//# sourceMappingURL=index.mjs.map
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "acorn",
|
||||
"description": "ECMAScript parser",
|
||||
"homepage": "https://github.com/acornjs/acorn",
|
||||
"main": "dist/acorn.js",
|
||||
"types": "dist/acorn.d.ts",
|
||||
"module": "dist/acorn.mjs",
|
||||
"exports": {
|
||||
".": [
|
||||
{
|
||||
"import": "./dist/acorn.mjs",
|
||||
"require": "./dist/acorn.js",
|
||||
"default": "./dist/acorn.js"
|
||||
},
|
||||
"./dist/acorn.js"
|
||||
],
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"version": "8.18.0",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Marijn Haverbeke",
|
||||
"email": "marijn@haverbeke.berlin",
|
||||
"web": "https://marijnhaverbeke.nl"
|
||||
},
|
||||
{
|
||||
"name": "Ingvar Stepanyan",
|
||||
"email": "me@rreverser.com",
|
||||
"web": "https://rreverser.com/"
|
||||
},
|
||||
{
|
||||
"name": "Adrian Heine",
|
||||
"web": "http://adrianheine.de"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/acornjs/acorn.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"prepare": "cd ..; npm run build:main"
|
||||
},
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,488 @@
|
||||
'use strict';
|
||||
|
||||
const XHTMLEntities = require('./xhtml');
|
||||
|
||||
const hexNumber = /^[\da-fA-F]+$/;
|
||||
const decimalNumber = /^\d+$/;
|
||||
|
||||
// The map to `acorn-jsx` tokens from `acorn` namespace objects.
|
||||
const acornJsxMap = new WeakMap();
|
||||
|
||||
// Get the original tokens for the given `acorn` namespace object.
|
||||
function getJsxTokens(acorn) {
|
||||
acorn = acorn.Parser.acorn || acorn;
|
||||
let acornJsx = acornJsxMap.get(acorn);
|
||||
if (!acornJsx) {
|
||||
const tt = acorn.tokTypes;
|
||||
const TokContext = acorn.TokContext;
|
||||
const TokenType = acorn.TokenType;
|
||||
const tc_oTag = new TokContext('<tag', false);
|
||||
const tc_cTag = new TokContext('</tag', false);
|
||||
const tc_expr = new TokContext('<tag>...</tag>', true, true);
|
||||
const tokContexts = {
|
||||
tc_oTag: tc_oTag,
|
||||
tc_cTag: tc_cTag,
|
||||
tc_expr: tc_expr
|
||||
};
|
||||
const tokTypes = {
|
||||
jsxName: new TokenType('jsxName'),
|
||||
jsxText: new TokenType('jsxText', {beforeExpr: true}),
|
||||
jsxTagStart: new TokenType('jsxTagStart', {startsExpr: true}),
|
||||
jsxTagEnd: new TokenType('jsxTagEnd')
|
||||
};
|
||||
|
||||
tokTypes.jsxTagStart.updateContext = function() {
|
||||
this.context.push(tc_expr); // treat as beginning of JSX expression
|
||||
this.context.push(tc_oTag); // start opening tag context
|
||||
this.exprAllowed = false;
|
||||
};
|
||||
tokTypes.jsxTagEnd.updateContext = function(prevType) {
|
||||
let out = this.context.pop();
|
||||
if (out === tc_oTag && prevType === tt.slash || out === tc_cTag) {
|
||||
this.context.pop();
|
||||
this.exprAllowed = this.curContext() === tc_expr;
|
||||
} else {
|
||||
this.exprAllowed = true;
|
||||
}
|
||||
};
|
||||
|
||||
acornJsx = { tokContexts: tokContexts, tokTypes: tokTypes };
|
||||
acornJsxMap.set(acorn, acornJsx);
|
||||
}
|
||||
|
||||
return acornJsx;
|
||||
}
|
||||
|
||||
// Transforms JSX element name to string.
|
||||
|
||||
function getQualifiedJSXName(object) {
|
||||
if (!object)
|
||||
return object;
|
||||
|
||||
if (object.type === 'JSXIdentifier')
|
||||
return object.name;
|
||||
|
||||
if (object.type === 'JSXNamespacedName')
|
||||
return object.namespace.name + ':' + object.name.name;
|
||||
|
||||
if (object.type === 'JSXMemberExpression')
|
||||
return getQualifiedJSXName(object.object) + '.' +
|
||||
getQualifiedJSXName(object.property);
|
||||
}
|
||||
|
||||
module.exports = function(options) {
|
||||
options = options || {};
|
||||
return function(Parser) {
|
||||
return plugin({
|
||||
allowNamespaces: options.allowNamespaces !== false,
|
||||
allowNamespacedObjects: !!options.allowNamespacedObjects
|
||||
}, Parser);
|
||||
};
|
||||
};
|
||||
|
||||
// This is `tokTypes` of the peer dep.
|
||||
// This can be different instances from the actual `tokTypes` this plugin uses.
|
||||
Object.defineProperty(module.exports, "tokTypes", {
|
||||
get: function get_tokTypes() {
|
||||
return getJsxTokens(require("acorn")).tokTypes;
|
||||
},
|
||||
configurable: true,
|
||||
enumerable: true
|
||||
});
|
||||
|
||||
function plugin(options, Parser) {
|
||||
const acorn = Parser.acorn || require("acorn");
|
||||
const acornJsx = getJsxTokens(acorn);
|
||||
const tt = acorn.tokTypes;
|
||||
const tok = acornJsx.tokTypes;
|
||||
const tokContexts = acorn.tokContexts;
|
||||
const tc_oTag = acornJsx.tokContexts.tc_oTag;
|
||||
const tc_cTag = acornJsx.tokContexts.tc_cTag;
|
||||
const tc_expr = acornJsx.tokContexts.tc_expr;
|
||||
const isNewLine = acorn.isNewLine;
|
||||
const isIdentifierStart = acorn.isIdentifierStart;
|
||||
const isIdentifierChar = acorn.isIdentifierChar;
|
||||
|
||||
return class extends Parser {
|
||||
// Expose actual `tokTypes` and `tokContexts` to other plugins.
|
||||
static get acornJsx() {
|
||||
return acornJsx;
|
||||
}
|
||||
|
||||
// Reads inline JSX contents token.
|
||||
jsx_readToken() {
|
||||
let out = '', chunkStart = this.pos;
|
||||
for (;;) {
|
||||
if (this.pos >= this.input.length)
|
||||
this.raise(this.start, 'Unterminated JSX contents');
|
||||
let ch = this.input.charCodeAt(this.pos);
|
||||
|
||||
switch (ch) {
|
||||
case 60: // '<'
|
||||
case 123: // '{'
|
||||
if (this.pos === this.start) {
|
||||
if (ch === 60 && this.exprAllowed) {
|
||||
++this.pos;
|
||||
return this.finishToken(tok.jsxTagStart);
|
||||
}
|
||||
return this.getTokenFromCode(ch);
|
||||
}
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
return this.finishToken(tok.jsxText, out);
|
||||
|
||||
case 38: // '&'
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
out += this.jsx_readEntity();
|
||||
chunkStart = this.pos;
|
||||
break;
|
||||
|
||||
case 62: // '>'
|
||||
case 125: // '}'
|
||||
this.raise(
|
||||
this.pos,
|
||||
"Unexpected token `" + this.input[this.pos] + "`. Did you mean `" +
|
||||
(ch === 62 ? ">" : "}") + "` or " + "`{\"" + this.input[this.pos] + "\"}" + "`?"
|
||||
);
|
||||
|
||||
default:
|
||||
if (isNewLine(ch)) {
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
out += this.jsx_readNewLine(true);
|
||||
chunkStart = this.pos;
|
||||
} else {
|
||||
++this.pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jsx_readNewLine(normalizeCRLF) {
|
||||
let ch = this.input.charCodeAt(this.pos);
|
||||
let out;
|
||||
++this.pos;
|
||||
if (ch === 13 && this.input.charCodeAt(this.pos) === 10) {
|
||||
++this.pos;
|
||||
out = normalizeCRLF ? '\n' : '\r\n';
|
||||
} else {
|
||||
out = String.fromCharCode(ch);
|
||||
}
|
||||
if (this.options.locations) {
|
||||
++this.curLine;
|
||||
this.lineStart = this.pos;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
jsx_readString(quote) {
|
||||
let out = '', chunkStart = ++this.pos;
|
||||
for (;;) {
|
||||
if (this.pos >= this.input.length)
|
||||
this.raise(this.start, 'Unterminated string constant');
|
||||
let ch = this.input.charCodeAt(this.pos);
|
||||
if (ch === quote) break;
|
||||
if (ch === 38) { // '&'
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
out += this.jsx_readEntity();
|
||||
chunkStart = this.pos;
|
||||
} else if (isNewLine(ch)) {
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
out += this.jsx_readNewLine(false);
|
||||
chunkStart = this.pos;
|
||||
} else {
|
||||
++this.pos;
|
||||
}
|
||||
}
|
||||
out += this.input.slice(chunkStart, this.pos++);
|
||||
return this.finishToken(tt.string, out);
|
||||
}
|
||||
|
||||
jsx_readEntity() {
|
||||
let str = '', count = 0, entity;
|
||||
let ch = this.input[this.pos];
|
||||
if (ch !== '&')
|
||||
this.raise(this.pos, 'Entity must start with an ampersand');
|
||||
let startPos = ++this.pos;
|
||||
while (this.pos < this.input.length && count++ < 10) {
|
||||
ch = this.input[this.pos++];
|
||||
if (ch === ';') {
|
||||
if (str[0] === '#') {
|
||||
if (str[1] === 'x') {
|
||||
str = str.substr(2);
|
||||
if (hexNumber.test(str))
|
||||
entity = String.fromCharCode(parseInt(str, 16));
|
||||
} else {
|
||||
str = str.substr(1);
|
||||
if (decimalNumber.test(str))
|
||||
entity = String.fromCharCode(parseInt(str, 10));
|
||||
}
|
||||
} else {
|
||||
entity = XHTMLEntities[str];
|
||||
}
|
||||
break;
|
||||
}
|
||||
str += ch;
|
||||
}
|
||||
if (!entity) {
|
||||
this.pos = startPos;
|
||||
return '&';
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
// Read a JSX identifier (valid tag or attribute name).
|
||||
//
|
||||
// Optimized version since JSX identifiers can't contain
|
||||
// escape characters and so can be read as single slice.
|
||||
// Also assumes that first character was already checked
|
||||
// by isIdentifierStart in readToken.
|
||||
|
||||
jsx_readWord() {
|
||||
let ch, start = this.pos;
|
||||
do {
|
||||
ch = this.input.charCodeAt(++this.pos);
|
||||
} while (isIdentifierChar(ch) || ch === 45); // '-'
|
||||
return this.finishToken(tok.jsxName, this.input.slice(start, this.pos));
|
||||
}
|
||||
|
||||
// Parse next token as JSX identifier
|
||||
|
||||
jsx_parseIdentifier() {
|
||||
let node = this.startNode();
|
||||
if (this.type === tok.jsxName)
|
||||
node.name = this.value;
|
||||
else if (this.type.keyword)
|
||||
node.name = this.type.keyword;
|
||||
else
|
||||
this.unexpected();
|
||||
this.next();
|
||||
return this.finishNode(node, 'JSXIdentifier');
|
||||
}
|
||||
|
||||
// Parse namespaced identifier.
|
||||
|
||||
jsx_parseNamespacedName() {
|
||||
let startPos = this.start, startLoc = this.startLoc;
|
||||
let name = this.jsx_parseIdentifier();
|
||||
if (!options.allowNamespaces || !this.eat(tt.colon)) return name;
|
||||
var node = this.startNodeAt(startPos, startLoc);
|
||||
node.namespace = name;
|
||||
node.name = this.jsx_parseIdentifier();
|
||||
return this.finishNode(node, 'JSXNamespacedName');
|
||||
}
|
||||
|
||||
// Parses element name in any form - namespaced, member
|
||||
// or single identifier.
|
||||
|
||||
jsx_parseElementName() {
|
||||
if (this.type === tok.jsxTagEnd) return '';
|
||||
let startPos = this.start, startLoc = this.startLoc;
|
||||
let node = this.jsx_parseNamespacedName();
|
||||
if (this.type === tt.dot && node.type === 'JSXNamespacedName' && !options.allowNamespacedObjects) {
|
||||
this.unexpected();
|
||||
}
|
||||
while (this.eat(tt.dot)) {
|
||||
let newNode = this.startNodeAt(startPos, startLoc);
|
||||
newNode.object = node;
|
||||
newNode.property = this.jsx_parseIdentifier();
|
||||
node = this.finishNode(newNode, 'JSXMemberExpression');
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
// Parses any type of JSX attribute value.
|
||||
|
||||
jsx_parseAttributeValue() {
|
||||
switch (this.type) {
|
||||
case tt.braceL:
|
||||
let node = this.jsx_parseExpressionContainer();
|
||||
if (node.expression.type === 'JSXEmptyExpression')
|
||||
this.raise(node.start, 'JSX attributes must only be assigned a non-empty expression');
|
||||
return node;
|
||||
|
||||
case tok.jsxTagStart:
|
||||
case tt.string:
|
||||
return this.parseExprAtom();
|
||||
|
||||
default:
|
||||
this.raise(this.start, 'JSX value should be either an expression or a quoted JSX text');
|
||||
}
|
||||
}
|
||||
|
||||
// JSXEmptyExpression is unique type since it doesn't actually parse anything,
|
||||
// and so it should start at the end of last read token (left brace) and finish
|
||||
// at the beginning of the next one (right brace).
|
||||
|
||||
jsx_parseEmptyExpression() {
|
||||
let node = this.startNodeAt(this.lastTokEnd, this.lastTokEndLoc);
|
||||
return this.finishNodeAt(node, 'JSXEmptyExpression', this.start, this.startLoc);
|
||||
}
|
||||
|
||||
// Parses JSX expression enclosed into curly brackets.
|
||||
|
||||
jsx_parseExpressionContainer() {
|
||||
let node = this.startNode();
|
||||
this.next();
|
||||
node.expression = this.type === tt.braceR
|
||||
? this.jsx_parseEmptyExpression()
|
||||
: this.parseExpression();
|
||||
this.expect(tt.braceR);
|
||||
return this.finishNode(node, 'JSXExpressionContainer');
|
||||
}
|
||||
|
||||
// Parses following JSX attribute name-value pair.
|
||||
|
||||
jsx_parseAttribute() {
|
||||
let node = this.startNode();
|
||||
if (this.eat(tt.braceL)) {
|
||||
this.expect(tt.ellipsis);
|
||||
node.argument = this.parseMaybeAssign();
|
||||
this.expect(tt.braceR);
|
||||
return this.finishNode(node, 'JSXSpreadAttribute');
|
||||
}
|
||||
node.name = this.jsx_parseNamespacedName();
|
||||
node.value = this.eat(tt.eq) ? this.jsx_parseAttributeValue() : null;
|
||||
return this.finishNode(node, 'JSXAttribute');
|
||||
}
|
||||
|
||||
// Parses JSX opening tag starting after '<'.
|
||||
|
||||
jsx_parseOpeningElementAt(startPos, startLoc) {
|
||||
let node = this.startNodeAt(startPos, startLoc);
|
||||
node.attributes = [];
|
||||
let nodeName = this.jsx_parseElementName();
|
||||
if (nodeName) node.name = nodeName;
|
||||
while (this.type !== tt.slash && this.type !== tok.jsxTagEnd)
|
||||
node.attributes.push(this.jsx_parseAttribute());
|
||||
node.selfClosing = this.eat(tt.slash);
|
||||
this.expect(tok.jsxTagEnd);
|
||||
return this.finishNode(node, nodeName ? 'JSXOpeningElement' : 'JSXOpeningFragment');
|
||||
}
|
||||
|
||||
// Parses JSX closing tag starting after '</'.
|
||||
|
||||
jsx_parseClosingElementAt(startPos, startLoc) {
|
||||
let node = this.startNodeAt(startPos, startLoc);
|
||||
let nodeName = this.jsx_parseElementName();
|
||||
if (nodeName) node.name = nodeName;
|
||||
this.expect(tok.jsxTagEnd);
|
||||
return this.finishNode(node, nodeName ? 'JSXClosingElement' : 'JSXClosingFragment');
|
||||
}
|
||||
|
||||
// Parses entire JSX element, including it's opening tag
|
||||
// (starting after '<'), attributes, contents and closing tag.
|
||||
|
||||
jsx_parseElementAt(startPos, startLoc) {
|
||||
let node = this.startNodeAt(startPos, startLoc);
|
||||
let children = [];
|
||||
let openingElement = this.jsx_parseOpeningElementAt(startPos, startLoc);
|
||||
let closingElement = null;
|
||||
|
||||
if (!openingElement.selfClosing) {
|
||||
contents: for (;;) {
|
||||
switch (this.type) {
|
||||
case tok.jsxTagStart:
|
||||
startPos = this.start; startLoc = this.startLoc;
|
||||
this.next();
|
||||
if (this.eat(tt.slash)) {
|
||||
closingElement = this.jsx_parseClosingElementAt(startPos, startLoc);
|
||||
break contents;
|
||||
}
|
||||
children.push(this.jsx_parseElementAt(startPos, startLoc));
|
||||
break;
|
||||
|
||||
case tok.jsxText:
|
||||
children.push(this.parseExprAtom());
|
||||
break;
|
||||
|
||||
case tt.braceL:
|
||||
children.push(this.jsx_parseExpressionContainer());
|
||||
break;
|
||||
|
||||
default:
|
||||
this.unexpected();
|
||||
}
|
||||
}
|
||||
if (getQualifiedJSXName(closingElement.name) !== getQualifiedJSXName(openingElement.name)) {
|
||||
this.raise(
|
||||
closingElement.start,
|
||||
'Expected corresponding JSX closing tag for <' + getQualifiedJSXName(openingElement.name) + '>');
|
||||
}
|
||||
}
|
||||
let fragmentOrElement = openingElement.name ? 'Element' : 'Fragment';
|
||||
|
||||
node['opening' + fragmentOrElement] = openingElement;
|
||||
node['closing' + fragmentOrElement] = closingElement;
|
||||
node.children = children;
|
||||
if (this.type === tt.relational && this.value === "<") {
|
||||
this.raise(this.start, "Adjacent JSX elements must be wrapped in an enclosing tag");
|
||||
}
|
||||
return this.finishNode(node, 'JSX' + fragmentOrElement);
|
||||
}
|
||||
|
||||
// Parse JSX text
|
||||
|
||||
jsx_parseText() {
|
||||
let node = this.parseLiteral(this.value);
|
||||
node.type = "JSXText";
|
||||
return node;
|
||||
}
|
||||
|
||||
// Parses entire JSX element from current position.
|
||||
|
||||
jsx_parseElement() {
|
||||
let startPos = this.start, startLoc = this.startLoc;
|
||||
this.next();
|
||||
return this.jsx_parseElementAt(startPos, startLoc);
|
||||
}
|
||||
|
||||
parseExprAtom(refShortHandDefaultPos) {
|
||||
if (this.type === tok.jsxText)
|
||||
return this.jsx_parseText();
|
||||
else if (this.type === tok.jsxTagStart)
|
||||
return this.jsx_parseElement();
|
||||
else
|
||||
return super.parseExprAtom(refShortHandDefaultPos);
|
||||
}
|
||||
|
||||
readToken(code) {
|
||||
let context = this.curContext();
|
||||
|
||||
if (context === tc_expr) return this.jsx_readToken();
|
||||
|
||||
if (context === tc_oTag || context === tc_cTag) {
|
||||
if (isIdentifierStart(code)) return this.jsx_readWord();
|
||||
|
||||
if (code == 62) {
|
||||
++this.pos;
|
||||
return this.finishToken(tok.jsxTagEnd);
|
||||
}
|
||||
|
||||
if ((code === 34 || code === 39) && context == tc_oTag)
|
||||
return this.jsx_readString(code);
|
||||
}
|
||||
|
||||
if (code === 60 && this.exprAllowed && this.input.charCodeAt(this.pos + 1) !== 33) {
|
||||
++this.pos;
|
||||
return this.finishToken(tok.jsxTagStart);
|
||||
}
|
||||
return super.readToken(code);
|
||||
}
|
||||
|
||||
updateContext(prevType) {
|
||||
if (this.type == tt.braceL) {
|
||||
var curContext = this.curContext();
|
||||
if (curContext == tc_oTag) this.context.push(tokContexts.b_expr);
|
||||
else if (curContext == tc_expr) this.context.push(tokContexts.b_tmpl);
|
||||
else super.updateContext(prevType);
|
||||
this.exprAllowed = true;
|
||||
} else if (this.type === tt.slash && prevType === tok.jsxTagStart) {
|
||||
this.context.length -= 2; // do not consider JSX expr -> JSX open tag -> ... anymore
|
||||
this.context.push(tc_cTag); // reconsider as closing tag context
|
||||
this.exprAllowed = false;
|
||||
} else {
|
||||
return super.updateContext(prevType);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
"use strict";
|
||||
|
||||
function _define_property(obj, key, value) {
|
||||
if (key in obj) {
|
||||
Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true });
|
||||
} else obj[key] = value;
|
||||
|
||||
return obj;
|
||||
}
|
||||
exports._ = _define_property;
|
||||
@@ -0,0 +1,335 @@
|
||||
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
||||
//#region \0rolldown/runtime.js
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
||||
key = keys[i];
|
||||
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
||||
get: ((k) => from[k]).bind(null, key),
|
||||
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
||||
});
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
||||
value: mod,
|
||||
enumerable: true
|
||||
}) : target, mod));
|
||||
//#endregion
|
||||
let fs = require("fs");
|
||||
let path = require("path");
|
||||
let url = require("url");
|
||||
let fdir = require("fdir");
|
||||
let picomatch = require("picomatch");
|
||||
picomatch = __toESM(picomatch, 1);
|
||||
//#region src/utils.ts
|
||||
const isReadonlyArray = Array.isArray;
|
||||
const BACKSLASHES = /\\/g;
|
||||
const DRIVE_RELATIVE_PATH = /^[A-Za-z]:$/;
|
||||
const isWin = process.platform === "win32";
|
||||
const ONLY_PARENT_DIRECTORIES = /^(\/?\.\.)+$/;
|
||||
function getPartialMatcher(patterns, options = {}) {
|
||||
const patternsCount = patterns.length;
|
||||
const patternsParts = Array(patternsCount);
|
||||
const matchers = Array(patternsCount);
|
||||
let i, j;
|
||||
for (i = 0; i < patternsCount; i++) {
|
||||
const parts = splitPattern(patterns[i]);
|
||||
patternsParts[i] = parts;
|
||||
const partsCount = parts.length;
|
||||
const partMatchers = Array(partsCount);
|
||||
for (j = 0; j < partsCount; j++) partMatchers[j] = (0, picomatch.default)(parts[j], options);
|
||||
matchers[i] = partMatchers;
|
||||
}
|
||||
return (input) => {
|
||||
const inputParts = input.split("/");
|
||||
if (inputParts[0] === ".." && ONLY_PARENT_DIRECTORIES.test(input)) return true;
|
||||
for (i = 0; i < patternsCount; i++) {
|
||||
const patternParts = patternsParts[i];
|
||||
const matcher = matchers[i];
|
||||
const inputPatternCount = inputParts.length;
|
||||
const minParts = Math.min(inputPatternCount, patternParts.length);
|
||||
j = 0;
|
||||
while (j < minParts) {
|
||||
const part = patternParts[j];
|
||||
if (part.includes("/")) return true;
|
||||
if (!matcher[j](inputParts[j])) break;
|
||||
if (!options.noglobstar && part === "**") return true;
|
||||
j++;
|
||||
}
|
||||
if (j === inputPatternCount) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
/* node:coverage ignore next 2 */
|
||||
const WIN32_ROOT_DIR = /^[A-Z]:\/$/i;
|
||||
const isRoot = isWin ? (p) => WIN32_ROOT_DIR.test(p) : (p) => p === "/";
|
||||
function buildFormat(cwd, root, absolute) {
|
||||
if (cwd === root || root.startsWith(`${cwd}/`)) {
|
||||
if (absolute) {
|
||||
const start = cwd.length + +!isRoot(cwd);
|
||||
return (p, isDir) => p.slice(start, isDir ? -1 : void 0) || ".";
|
||||
}
|
||||
const prefix = root.slice(cwd.length + 1);
|
||||
if (prefix) return (p, isDir) => {
|
||||
if (p === ".") return prefix;
|
||||
const result = `${prefix}/${p}`;
|
||||
return isDir ? result.slice(0, -1) : result;
|
||||
};
|
||||
return (p, isDir) => isDir && p !== "." ? p.slice(0, -1) : p;
|
||||
}
|
||||
if (absolute) return (p) => path.posix.relative(cwd, p) || ".";
|
||||
return (p) => path.posix.relative(cwd, `${root}/${p}`) || ".";
|
||||
}
|
||||
function buildRelative(cwd, root) {
|
||||
if (root.startsWith(`${cwd}/`)) {
|
||||
const prefix = root.slice(cwd.length + 1);
|
||||
return (p) => `${prefix}/${p}`;
|
||||
}
|
||||
return (p) => {
|
||||
const result = path.posix.relative(cwd, `${root}/${p}`);
|
||||
return p[p.length - 1] === "/" && result !== "" ? `${result}/` : result || ".";
|
||||
};
|
||||
}
|
||||
function ensureNonDriveRelativePath(path$1) {
|
||||
return path$1.replace(DRIVE_RELATIVE_PATH, (match) => `${match}/`);
|
||||
}
|
||||
const splitPatternOptions = { parts: true };
|
||||
function splitPattern(path$2) {
|
||||
var _result$parts;
|
||||
const result = picomatch.default.scan(path$2, splitPatternOptions);
|
||||
return ((_result$parts = result.parts) === null || _result$parts === void 0 ? void 0 : _result$parts.length) ? result.parts : [path$2];
|
||||
}
|
||||
const ESCAPED_WIN32_BACKSLASHES = /\\(?![()[\]{}!+@])/g;
|
||||
function convertPosixPathToPattern(path$3) {
|
||||
return escapePosixPath(path$3);
|
||||
}
|
||||
function convertWin32PathToPattern(path$4) {
|
||||
return escapeWin32Path(path$4).replace(ESCAPED_WIN32_BACKSLASHES, "/");
|
||||
}
|
||||
/**
|
||||
* Converts a path to a pattern depending on the platform.
|
||||
* Identical to {@link escapePath} on POSIX systems.
|
||||
* @see {@link https://superchupu.dev/tinyglobby/documentation#convertPathToPattern}
|
||||
*/
|
||||
/* node:coverage ignore next 3 */
|
||||
const convertPathToPattern = isWin ? convertWin32PathToPattern : convertPosixPathToPattern;
|
||||
const POSIX_UNESCAPED_GLOB_SYMBOLS = /(?<!\\)([()[\]{}*?|]|^!|[!+@](?=\()|\\(?![()[\]{}!*+?@|]))/g;
|
||||
const WIN32_UNESCAPED_GLOB_SYMBOLS = /(?<!\\)([()[\]{}]|^!|[!+@](?=\())/g;
|
||||
const escapePosixPath = (path$5) => path$5.replace(POSIX_UNESCAPED_GLOB_SYMBOLS, "\\$&");
|
||||
const escapeWin32Path = (path$6) => path$6.replace(WIN32_UNESCAPED_GLOB_SYMBOLS, "\\$&");
|
||||
/**
|
||||
* Escapes a path's special characters depending on the platform.
|
||||
* @see {@link https://superchupu.dev/tinyglobby/documentation#escapePath}
|
||||
*/
|
||||
/* node:coverage ignore next */
|
||||
const escapePath = isWin ? escapeWin32Path : escapePosixPath;
|
||||
/**
|
||||
* Checks if a pattern has dynamic parts.
|
||||
*
|
||||
* Has a few minor differences with [`fast-glob`](https://github.com/mrmlnc/fast-glob) for better accuracy:
|
||||
*
|
||||
* - Doesn't necessarily return `false` on patterns that include `\`.
|
||||
* - Returns `true` if the pattern includes parentheses, regardless of them representing one single pattern or not.
|
||||
* - Returns `true` for unfinished glob extensions i.e. `(h`, `+(h`.
|
||||
* - Returns `true` for unfinished brace expansions as long as they include `,` or `..`.
|
||||
*
|
||||
* @see {@link https://superchupu.dev/tinyglobby/documentation#isDynamicPattern}
|
||||
*/
|
||||
function isDynamicPattern(pattern, options) {
|
||||
if ((options === null || options === void 0 ? void 0 : options.caseSensitiveMatch) === false) return true;
|
||||
const scan = picomatch.default.scan(pattern);
|
||||
return scan.isGlob || scan.negated;
|
||||
}
|
||||
function log(...tasks) {
|
||||
console.log(`[tinyglobby ${(/* @__PURE__ */ new Date()).toLocaleTimeString("es")}]`, ...tasks);
|
||||
}
|
||||
function ensureStringArray(value) {
|
||||
return typeof value === "string" ? [value] : value !== null && value !== void 0 ? value : [];
|
||||
}
|
||||
//#endregion
|
||||
//#region src/patterns.ts
|
||||
const PARENT_DIRECTORY = /^(\/?\.\.)+/;
|
||||
const ESCAPING_BACKSLASHES = /\\(?=[()[\]{}!*+?@|])/g;
|
||||
function normalizePattern(pattern, opts, props, isIgnore) {
|
||||
var _PARENT_DIRECTORY$exe;
|
||||
const cwd = opts.cwd;
|
||||
let result = pattern;
|
||||
if (pattern[pattern.length - 1] === "/") result = pattern.slice(0, -1);
|
||||
if (result[result.length - 1] !== "*" && opts.expandDirectories) result += "/**";
|
||||
const escapedCwd = escapePath(cwd);
|
||||
result = (0, path.isAbsolute)(result.replace(ESCAPING_BACKSLASHES, "")) ? path.posix.relative(escapedCwd, result) : path.posix.normalize(result);
|
||||
const parentDir = (_PARENT_DIRECTORY$exe = PARENT_DIRECTORY.exec(result)) === null || _PARENT_DIRECTORY$exe === void 0 ? void 0 : _PARENT_DIRECTORY$exe[0];
|
||||
const parts = splitPattern(result);
|
||||
if (parentDir) {
|
||||
const n = (parentDir.length + 1) / 3;
|
||||
let i = 0;
|
||||
const cwdParts = escapedCwd.split("/");
|
||||
while (i < n && parts[i + n] === cwdParts[cwdParts.length + i - n]) {
|
||||
result = result.slice(0, (n - i - 1) * 3) + result.slice((n - i) * 3 + parts[i + n].length + 1) || ".";
|
||||
i++;
|
||||
}
|
||||
const potentialRoot = path.posix.join(cwd, parentDir.slice(i * 3));
|
||||
if (potentialRoot[0] !== "." && props.root.length > potentialRoot.length) {
|
||||
props.root = ensureNonDriveRelativePath(potentialRoot);
|
||||
props.depthOffset = -n + i;
|
||||
}
|
||||
}
|
||||
if (!isIgnore && props.depthOffset >= 0) {
|
||||
var _props$commonPath;
|
||||
(_props$commonPath = props.commonPath) !== null && _props$commonPath !== void 0 || (props.commonPath = parts);
|
||||
const newCommonPath = [];
|
||||
const length = Math.min(props.commonPath.length, parts.length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
const part = parts[i];
|
||||
if (part === "**" && !parts[i + 1]) {
|
||||
newCommonPath.pop();
|
||||
break;
|
||||
}
|
||||
if (i === parts.length - 1 || part !== props.commonPath[i] || isDynamicPattern(part)) break;
|
||||
newCommonPath.push(part);
|
||||
}
|
||||
props.depthOffset = newCommonPath.length;
|
||||
props.commonPath = newCommonPath;
|
||||
props.root = ensureNonDriveRelativePath(newCommonPath.length > 0 ? path.posix.join(cwd, ...newCommonPath) : cwd);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function processPatterns(options, patterns, props) {
|
||||
const matchPatterns = [];
|
||||
const ignorePatterns = [];
|
||||
for (const pattern of options.ignore) {
|
||||
if (!pattern) continue;
|
||||
if (pattern[0] !== "!" || pattern[1] === "(") ignorePatterns.push(normalizePattern(pattern, options, props, true));
|
||||
}
|
||||
for (const pattern of patterns) {
|
||||
if (!pattern) continue;
|
||||
if (pattern[0] !== "!" || pattern[1] === "(") matchPatterns.push(normalizePattern(pattern, options, props, false));
|
||||
else if (pattern[1] !== "!" || pattern[2] === "(") ignorePatterns.push(normalizePattern(pattern.slice(1), options, props, true));
|
||||
}
|
||||
return {
|
||||
match: matchPatterns,
|
||||
ignore: ignorePatterns
|
||||
};
|
||||
}
|
||||
//#endregion
|
||||
//#region src/crawler.ts
|
||||
function buildCrawler(options, patterns) {
|
||||
const cwd = options.cwd;
|
||||
const props = {
|
||||
root: cwd,
|
||||
depthOffset: 0
|
||||
};
|
||||
const processed = processPatterns(options, patterns, props);
|
||||
if (options.debug) log("internal processing patterns:", processed);
|
||||
const { absolute, caseSensitiveMatch, debug, dot, followSymbolicLinks, onlyDirectories } = options;
|
||||
const root = props.root.replace(BACKSLASHES, "");
|
||||
const matchOptions = {
|
||||
dot,
|
||||
nobrace: options.braceExpansion === false,
|
||||
nocase: !caseSensitiveMatch,
|
||||
noextglob: options.extglob === false,
|
||||
noglobstar: options.globstar === false,
|
||||
posix: true
|
||||
};
|
||||
const matcher = (0, picomatch.default)(processed.match, matchOptions);
|
||||
const ignore = (0, picomatch.default)(processed.ignore, matchOptions);
|
||||
const partialMatcher = getPartialMatcher(processed.match, matchOptions);
|
||||
const format = buildFormat(cwd, root, absolute);
|
||||
const excludeFormatter = absolute ? format : buildFormat(cwd, root, true);
|
||||
const excludePredicate = (_, p) => {
|
||||
const relativePath = excludeFormatter(p, true);
|
||||
return relativePath !== "." && !partialMatcher(relativePath) || ignore(relativePath);
|
||||
};
|
||||
let maxDepth;
|
||||
if (options.deep !== void 0) maxDepth = Math.round(options.deep - props.depthOffset);
|
||||
const crawler = new fdir.fdir({
|
||||
filters: [debug ? (p, isDirectory) => {
|
||||
const path = format(p, isDirectory);
|
||||
const matches = matcher(path) && !ignore(path);
|
||||
if (matches) log(`matched ${path}`);
|
||||
return matches;
|
||||
} : (p, isDirectory) => {
|
||||
const path = format(p, isDirectory);
|
||||
return matcher(path) && !ignore(path);
|
||||
}],
|
||||
exclude: debug ? (_, p) => {
|
||||
const skipped = excludePredicate(_, p);
|
||||
log(`${skipped ? "skipped" : "crawling"} ${p}`);
|
||||
return skipped;
|
||||
} : excludePredicate,
|
||||
fs: options.fs,
|
||||
pathSeparator: "/",
|
||||
relativePaths: !absolute,
|
||||
resolvePaths: absolute,
|
||||
includeBasePath: absolute,
|
||||
resolveSymlinks: followSymbolicLinks,
|
||||
excludeSymlinks: !followSymbolicLinks,
|
||||
excludeFiles: onlyDirectories,
|
||||
includeDirs: onlyDirectories || !options.onlyFiles,
|
||||
maxDepth,
|
||||
signal: options.signal
|
||||
}).crawl(root);
|
||||
if (options.debug) log("internal properties:", {
|
||||
...props,
|
||||
root
|
||||
});
|
||||
return [crawler, cwd !== root && !absolute && buildRelative(cwd, root)];
|
||||
}
|
||||
//#endregion
|
||||
//#region src/index.ts
|
||||
function formatPaths(paths, mapper) {
|
||||
if (mapper) for (let i = paths.length - 1; i >= 0; i--) paths[i] = mapper(paths[i]);
|
||||
return paths;
|
||||
}
|
||||
const defaultOptions = {
|
||||
caseSensitiveMatch: true,
|
||||
debug: !!process.env.TINYGLOBBY_DEBUG,
|
||||
expandDirectories: true,
|
||||
followSymbolicLinks: true,
|
||||
onlyFiles: true
|
||||
};
|
||||
function getOptions(options) {
|
||||
const opts = Object.assign({}, options);
|
||||
for (const key in defaultOptions) if (opts[key] === void 0) Object.assign(opts, { [key]: defaultOptions[key] });
|
||||
opts.cwd = (opts.cwd instanceof URL ? (0, url.fileURLToPath)(opts.cwd) : (0, path.resolve)(opts.cwd || process.cwd())).replace(BACKSLASHES, "/");
|
||||
opts.ignore = ensureStringArray(opts.ignore);
|
||||
opts.fs && (opts.fs = {
|
||||
readdir: opts.fs.readdir || fs.readdir,
|
||||
readdirSync: opts.fs.readdirSync || fs.readdirSync,
|
||||
realpath: opts.fs.realpath || fs.realpath,
|
||||
realpathSync: opts.fs.realpathSync || fs.realpathSync,
|
||||
stat: opts.fs.stat || fs.stat,
|
||||
statSync: opts.fs.statSync || fs.statSync
|
||||
});
|
||||
if (opts.debug) log("globbing with options:", opts);
|
||||
return opts;
|
||||
}
|
||||
function getCrawler(globInput, inputOptions = {}) {
|
||||
var _ref;
|
||||
if (globInput && (inputOptions === null || inputOptions === void 0 ? void 0 : inputOptions.patterns)) throw new Error("Cannot pass patterns as both an argument and an option");
|
||||
const isModern = isReadonlyArray(globInput) || typeof globInput === "string";
|
||||
const patterns = ensureStringArray((_ref = isModern ? globInput : globInput.patterns) !== null && _ref !== void 0 ? _ref : "**/*");
|
||||
const options = getOptions(isModern ? inputOptions : globInput);
|
||||
return patterns.length > 0 ? buildCrawler(options, patterns) : [];
|
||||
}
|
||||
async function glob(globInput, options) {
|
||||
const [crawler, relative] = getCrawler(globInput, options);
|
||||
return crawler ? formatPaths(await crawler.withPromise(), relative) : [];
|
||||
}
|
||||
function globSync(globInput, options) {
|
||||
const [crawler, relative] = getCrawler(globInput, options);
|
||||
return crawler ? formatPaths(crawler.sync(), relative) : [];
|
||||
}
|
||||
//#endregion
|
||||
exports.convertPathToPattern = convertPathToPattern;
|
||||
exports.escapePath = escapePath;
|
||||
exports.glob = glob;
|
||||
exports.globSync = globSync;
|
||||
exports.isDynamicPattern = isDynamicPattern;
|
||||
@@ -0,0 +1,38 @@
|
||||
'use strict';
|
||||
|
||||
var parse = require('../');
|
||||
var test = require('tape');
|
||||
|
||||
test('nums', function (t) {
|
||||
var argv = parse([
|
||||
'-x', '1234',
|
||||
'-y', '5.67',
|
||||
'-z', '1e7',
|
||||
'-w', '10f',
|
||||
'--hex', '0xdeadbeef',
|
||||
'789',
|
||||
]);
|
||||
t.deepEqual(argv, {
|
||||
x: 1234,
|
||||
y: 5.67,
|
||||
z: 1e7,
|
||||
w: '10f',
|
||||
hex: 0xdeadbeef,
|
||||
_: [789],
|
||||
});
|
||||
t.deepEqual(typeof argv.x, 'number');
|
||||
t.deepEqual(typeof argv.y, 'number');
|
||||
t.deepEqual(typeof argv.z, 'number');
|
||||
t.deepEqual(typeof argv.w, 'string');
|
||||
t.deepEqual(typeof argv.hex, 'number');
|
||||
t.deepEqual(typeof argv._[0], 'number');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('already a number', function (t) {
|
||||
var argv = parse(['-x', 1234, 789]);
|
||||
t.deepEqual(argv, { x: 1234, _: [789] });
|
||||
t.deepEqual(typeof argv.x, 'number');
|
||||
t.deepEqual(typeof argv._[0], 'number');
|
||||
t.end();
|
||||
});
|
||||
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* @fileoverview Rule to disallow negating the left operand of relational operators
|
||||
* @author Toru Nagashima
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks whether the given operator is `in` or `instanceof`
|
||||
* @param {string} op The operator type to check.
|
||||
* @returns {boolean} `true` if the operator is `in` or `instanceof`
|
||||
*/
|
||||
function isInOrInstanceOfOperator(op) {
|
||||
return op === "in" || op === "instanceof";
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given operator is an ordering relational operator or not.
|
||||
* @param {string} op The operator type to check.
|
||||
* @returns {boolean} `true` if the operator is an ordering relational operator.
|
||||
*/
|
||||
function isOrderingRelationalOperator(op) {
|
||||
return op === "<" || op === ">" || op === ">=" || op === "<=";
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given node is a logical negation expression or not.
|
||||
* @param {ASTNode} node The node to check.
|
||||
* @returns {boolean} `true` if the node is a logical negation expression.
|
||||
*/
|
||||
function isNegation(node) {
|
||||
return node.type === "UnaryExpression" && node.operator === "!";
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
|
||||
defaultOptions: [
|
||||
{
|
||||
enforceForOrderingRelations: false,
|
||||
},
|
||||
],
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Disallow negating the left operand of relational operators",
|
||||
recommended: true,
|
||||
url: "https://eslint.org/docs/latest/rules/no-unsafe-negation",
|
||||
},
|
||||
|
||||
hasSuggestions: true,
|
||||
|
||||
schema: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
enforceForOrderingRelations: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
|
||||
fixable: null,
|
||||
|
||||
messages: {
|
||||
unexpected:
|
||||
"Unexpected negating the left operand of '{{operator}}' operator.",
|
||||
suggestNegatedExpression:
|
||||
"Negate '{{operator}}' expression instead of its left operand. This changes the current behavior.",
|
||||
suggestParenthesisedNegation:
|
||||
"Wrap negation in '()' to make the intention explicit. This preserves the current behavior.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
const [{ enforceForOrderingRelations }] = context.options;
|
||||
|
||||
return {
|
||||
BinaryExpression(node) {
|
||||
const operator = node.operator;
|
||||
const orderingRelationRuleApplies =
|
||||
enforceForOrderingRelations &&
|
||||
isOrderingRelationalOperator(operator);
|
||||
|
||||
if (
|
||||
(isInOrInstanceOfOperator(operator) ||
|
||||
orderingRelationRuleApplies) &&
|
||||
isNegation(node.left) &&
|
||||
!astUtils.isParenthesised(sourceCode, node.left)
|
||||
) {
|
||||
context.report({
|
||||
node,
|
||||
loc: node.left.loc,
|
||||
messageId: "unexpected",
|
||||
data: { operator },
|
||||
suggest: [
|
||||
{
|
||||
messageId: "suggestNegatedExpression",
|
||||
data: { operator },
|
||||
fix(fixer) {
|
||||
const negationToken =
|
||||
sourceCode.getFirstToken(node.left);
|
||||
const fixRange = [
|
||||
negationToken.range[1],
|
||||
node.range[1],
|
||||
];
|
||||
const text = sourceCode.text.slice(
|
||||
fixRange[0],
|
||||
fixRange[1],
|
||||
);
|
||||
|
||||
return fixer.replaceTextRange(
|
||||
fixRange,
|
||||
`(${text})`,
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
messageId: "suggestParenthesisedNegation",
|
||||
fix(fixer) {
|
||||
return fixer.replaceText(
|
||||
node.left,
|
||||
`(${sourceCode.getText(node.left)})`,
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"lib": [ "es2022" ],
|
||||
"module": "commonjs",
|
||||
"noEmit": true,
|
||||
"strict": true
|
||||
},
|
||||
"include": [
|
||||
"./test/types/*.test-d.ts",
|
||||
"./index.d.ts"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function ({ plugins }) {
|
||||
const isArrayOfStrings = typeof plugins[0] === "string";
|
||||
|
||||
return `
|
||||
A config object has a "plugins" key defined as an array${isArrayOfStrings ? " of strings" : ""}. It looks something like this:
|
||||
|
||||
{
|
||||
"plugins": ${JSON.stringify(plugins)}
|
||||
}
|
||||
|
||||
Flat config requires "plugins" to be an object, like this:
|
||||
|
||||
{
|
||||
plugins: {
|
||||
${isArrayOfStrings && plugins[0] ? plugins[0] : "namespace"}: pluginObject
|
||||
}
|
||||
}
|
||||
|
||||
Please see the following page for information on how to convert your config object into the correct format:
|
||||
https://eslint.org/docs/latest/use/configure/migration-guide#import-plugins-and-custom-parsers
|
||||
|
||||
If you're using a shareable config that you cannot rewrite in flat config format, then use the compatibility utility:
|
||||
https://eslint.org/docs/latest/use/configure/migration-guide#use-eslintrc-configs-in-flat-config
|
||||
`;
|
||||
};
|
||||
@@ -0,0 +1,103 @@
|
||||
{
|
||||
"name": "fdir",
|
||||
"version": "6.5.0",
|
||||
"description": "The fastest directory crawler & globbing alternative to glob, fast-glob, & tiny-glob. Crawls 1m files in < 1s",
|
||||
"main": "./dist/index.cjs",
|
||||
"types": "./dist/index.d.cts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"prepublishOnly": "npm run test && npm run build",
|
||||
"build": "tsdown",
|
||||
"format": "prettier --write src __tests__ benchmarks",
|
||||
"test": "vitest run __tests__/",
|
||||
"test:coverage": "vitest run --coverage __tests__/",
|
||||
"test:watch": "vitest __tests__/",
|
||||
"bench": "ts-node benchmarks/benchmark.js",
|
||||
"bench:glob": "ts-node benchmarks/glob-benchmark.ts",
|
||||
"bench:fdir": "ts-node benchmarks/fdir-benchmark.ts",
|
||||
"release": "./scripts/release.sh"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/thecodrr/fdir.git"
|
||||
},
|
||||
"keywords": [
|
||||
"util",
|
||||
"os",
|
||||
"sys",
|
||||
"fs",
|
||||
"walk",
|
||||
"crawler",
|
||||
"directory",
|
||||
"files",
|
||||
"io",
|
||||
"tiny-glob",
|
||||
"glob",
|
||||
"fast-glob",
|
||||
"speed",
|
||||
"javascript",
|
||||
"nodejs"
|
||||
],
|
||||
"author": "thecodrr <thecodrr@protonmail.com>",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/thecodrr/fdir/issues"
|
||||
},
|
||||
"homepage": "https://github.com/thecodrr/fdir#readme",
|
||||
"devDependencies": {
|
||||
"@types/glob": "^8.1.0",
|
||||
"@types/mock-fs": "^4.13.4",
|
||||
"@types/node": "^20.9.4",
|
||||
"@types/picomatch": "^4.0.0",
|
||||
"@types/tap": "^15.0.11",
|
||||
"@vitest/coverage-v8": "^0.34.6",
|
||||
"all-files-in-tree": "^1.1.2",
|
||||
"benny": "^3.7.1",
|
||||
"csv-to-markdown-table": "^1.3.1",
|
||||
"expect": "^29.7.0",
|
||||
"fast-glob": "^3.3.2",
|
||||
"fdir1": "npm:fdir@1.2.0",
|
||||
"fdir2": "npm:fdir@2.1.0",
|
||||
"fdir3": "npm:fdir@3.4.2",
|
||||
"fdir4": "npm:fdir@4.1.0",
|
||||
"fdir5": "npm:fdir@5.0.0",
|
||||
"fs-readdir-recursive": "^1.1.0",
|
||||
"get-all-files": "^4.1.0",
|
||||
"glob": "^10.3.10",
|
||||
"klaw-sync": "^6.0.0",
|
||||
"mock-fs": "^5.2.0",
|
||||
"picomatch": "^4.0.2",
|
||||
"prettier": "^3.5.3",
|
||||
"recur-readdir": "0.0.1",
|
||||
"recursive-files": "^1.0.2",
|
||||
"recursive-fs": "^2.1.0",
|
||||
"recursive-readdir": "^2.2.3",
|
||||
"rrdir": "^12.1.0",
|
||||
"systeminformation": "^5.21.17",
|
||||
"tiny-glob": "^0.2.9",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsdown": "^0.12.5",
|
||||
"typescript": "^5.3.2",
|
||||
"vitest": "^0.34.6",
|
||||
"walk-sync": "^3.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"picomatch": "^3 || ^4"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"picomatch": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"module": "./dist/index.mjs",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.mjs",
|
||||
"require": "./dist/index.cjs"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# Diagnostics
|
||||
|
||||
Pino provides [tracing channel](tc) events that allow insight into the
|
||||
internal workings of the library. The currently supported events are:
|
||||
|
||||
+ `tracing:pino_asJson:start`: emitted when the final serialization process
|
||||
of logs is started. The emitted event payload has the following fields:
|
||||
- `instance`: the Pino instance associated with the function
|
||||
- `arguments`: the arguments passed to the function
|
||||
+ `tracing:pino_asJson:end`: emitted at the end of the final serialization
|
||||
process. The emitted event payload has the following fields:
|
||||
- `instance`: the Pino instance associated with the function
|
||||
- `arguments`: the arguments passed to the function
|
||||
- `result`: the finalized, newline delimited, log line as a string
|
||||
|
||||
[tc]: https://nodejs.org/docs/latest/api/diagnostics_channel.html#tracingchannel-channels
|
||||
@@ -0,0 +1,9 @@
|
||||
// Code generated by Herebyfile.mjs generate:enums from internal/diagnostics/diagnostics.go. DO NOT EDIT.
|
||||
export var DiagnosticCategory;
|
||||
(function (DiagnosticCategory) {
|
||||
DiagnosticCategory[DiagnosticCategory["Warning"] = 0] = "Warning";
|
||||
DiagnosticCategory[DiagnosticCategory["Error"] = 1] = "Error";
|
||||
DiagnosticCategory[DiagnosticCategory["Suggestion"] = 2] = "Suggestion";
|
||||
DiagnosticCategory[DiagnosticCategory["Message"] = 3] = "Message";
|
||||
})(DiagnosticCategory || (DiagnosticCategory = {}));
|
||||
//# sourceMappingURL=diagnosticCategory.js.map
|
||||
@@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
// THIS CODE WAS AUTOMATICALLY GENERATED
|
||||
// DO NOT EDIT THIS CODE BY HAND
|
||||
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
|
||||
// npx nx generate-lib repo
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.es2017_string = void 0;
|
||||
const base_config_1 = require("./base-config");
|
||||
exports.es2017_string = {
|
||||
libs: [],
|
||||
variables: [['String', base_config_1.TYPE]],
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"nist.d.ts","sourceRoot":"","sources":["../src/nist.ts"],"names":[],"mappings":"AAOA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AA+E3E,2EAA2E;AAC3E,eAAO,MAAM,IAAI,EAAE,iBAGlB,CAAC;AACF,mEAAmE;AACnE,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAkBtC,CAAC;AAUL,+DAA+D;AAC/D,eAAO,MAAM,IAAI,EAAE,iBAGlB,CAAC;AACF,mEAAmE;AACnE,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAkBtC,CAAC;AAWL,+DAA+D;AAC/D,eAAO,MAAM,IAAI,EAAE,iBAGlB,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,SAAS,EAAE,OAAO,IAAW,CAAC;AAC3C,gEAAgE;AAChE,eAAO,MAAM,SAAS,EAAE,OAAO,IAAW,CAAC;AAC3C,gEAAgE;AAChE,eAAO,MAAM,SAAS,EAAE,OAAO,IAAW,CAAC;AAE3C,mEAAmE;AACnE,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAkBtC,CAAC"}
|
||||
@@ -0,0 +1,383 @@
|
||||
/**
|
||||
* @fileoverview Rule to require or disallow line breaks inside braces.
|
||||
* @author Toru Nagashima
|
||||
* @deprecated in ESLint v8.53.0
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Schema objects.
|
||||
const OPTION_VALUE = {
|
||||
oneOf: [
|
||||
{
|
||||
enum: ["always", "never"],
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
multiline: {
|
||||
type: "boolean",
|
||||
},
|
||||
minProperties: {
|
||||
type: "integer",
|
||||
minimum: 0,
|
||||
},
|
||||
consistent: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
minProperties: 1,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalizes a given option value.
|
||||
* @param {string|Object|undefined} value An option value to parse.
|
||||
* @returns {{multiline: boolean, minProperties: number, consistent: boolean}} Normalized option object.
|
||||
*/
|
||||
function normalizeOptionValue(value) {
|
||||
let multiline = false;
|
||||
let minProperties = Number.POSITIVE_INFINITY;
|
||||
let consistent = false;
|
||||
|
||||
if (value) {
|
||||
if (value === "always") {
|
||||
minProperties = 0;
|
||||
} else if (value === "never") {
|
||||
minProperties = Number.POSITIVE_INFINITY;
|
||||
} else {
|
||||
multiline = Boolean(value.multiline);
|
||||
minProperties = value.minProperties || Number.POSITIVE_INFINITY;
|
||||
consistent = Boolean(value.consistent);
|
||||
}
|
||||
} else {
|
||||
consistent = true;
|
||||
}
|
||||
|
||||
return { multiline, minProperties, consistent };
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a value is an object.
|
||||
* @param {any} value The value to check
|
||||
* @returns {boolean} `true` if the value is an object, otherwise `false`
|
||||
*/
|
||||
function isObject(value) {
|
||||
return typeof value === "object" && value !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an option is a node-specific option
|
||||
* @param {any} option The option to check
|
||||
* @returns {boolean} `true` if the option is node-specific, otherwise `false`
|
||||
*/
|
||||
function isNodeSpecificOption(option) {
|
||||
return isObject(option) || typeof option === "string";
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a given option value.
|
||||
* @param {string|Object|undefined} options An option value to parse.
|
||||
* @returns {{
|
||||
* ObjectExpression: {multiline: boolean, minProperties: number, consistent: boolean},
|
||||
* ObjectPattern: {multiline: boolean, minProperties: number, consistent: boolean},
|
||||
* ImportDeclaration: {multiline: boolean, minProperties: number, consistent: boolean},
|
||||
* ExportNamedDeclaration : {multiline: boolean, minProperties: number, consistent: boolean}
|
||||
* }} Normalized option object.
|
||||
*/
|
||||
function normalizeOptions(options) {
|
||||
if (
|
||||
isObject(options) &&
|
||||
Object.values(options).some(isNodeSpecificOption)
|
||||
) {
|
||||
return {
|
||||
ObjectExpression: normalizeOptionValue(options.ObjectExpression),
|
||||
ObjectPattern: normalizeOptionValue(options.ObjectPattern),
|
||||
ImportDeclaration: normalizeOptionValue(options.ImportDeclaration),
|
||||
ExportNamedDeclaration: normalizeOptionValue(
|
||||
options.ExportDeclaration,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
const value = normalizeOptionValue(options);
|
||||
|
||||
return {
|
||||
ObjectExpression: value,
|
||||
ObjectPattern: value,
|
||||
ImportDeclaration: value,
|
||||
ExportNamedDeclaration: value,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if ObjectExpression, ObjectPattern, ImportDeclaration or ExportNamedDeclaration
|
||||
* node needs to be checked for missing line breaks
|
||||
* @param {ASTNode} node Node under inspection
|
||||
* @param {Object} options option specific to node type
|
||||
* @param {Token} first First object property
|
||||
* @param {Token} last Last object property
|
||||
* @returns {boolean} `true` if node needs to be checked for missing line breaks
|
||||
*/
|
||||
function areLineBreaksRequired(node, options, first, last) {
|
||||
let objectProperties;
|
||||
|
||||
if (node.type === "ObjectExpression" || node.type === "ObjectPattern") {
|
||||
objectProperties = node.properties;
|
||||
} else {
|
||||
// is ImportDeclaration or ExportNamedDeclaration
|
||||
objectProperties = node.specifiers.filter(
|
||||
s => s.type === "ImportSpecifier" || s.type === "ExportSpecifier",
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
objectProperties.length >= options.minProperties ||
|
||||
(options.multiline &&
|
||||
objectProperties.length > 0 &&
|
||||
first.loc.start.line !== last.loc.end.line)
|
||||
);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
deprecated: {
|
||||
message: "Formatting rules are being moved out of ESLint core.",
|
||||
url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
|
||||
deprecatedSince: "8.53.0",
|
||||
availableUntil: "11.0.0",
|
||||
replacedBy: [
|
||||
{
|
||||
message:
|
||||
"ESLint Stylistic now maintains deprecated stylistic core rules.",
|
||||
url: "https://eslint.style/guide/migration",
|
||||
plugin: {
|
||||
name: "@stylistic/eslint-plugin",
|
||||
url: "https://eslint.style",
|
||||
},
|
||||
rule: {
|
||||
name: "object-curly-newline",
|
||||
url: "https://eslint.style/rules/object-curly-newline",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Enforce consistent line breaks after opening and before closing braces",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/object-curly-newline",
|
||||
},
|
||||
|
||||
fixable: "whitespace",
|
||||
|
||||
schema: [
|
||||
{
|
||||
oneOf: [
|
||||
OPTION_VALUE,
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
ObjectExpression: OPTION_VALUE,
|
||||
ObjectPattern: OPTION_VALUE,
|
||||
ImportDeclaration: OPTION_VALUE,
|
||||
ExportDeclaration: OPTION_VALUE,
|
||||
},
|
||||
additionalProperties: false,
|
||||
minProperties: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
messages: {
|
||||
unexpectedLinebreakBeforeClosingBrace:
|
||||
"Unexpected line break before this closing brace.",
|
||||
unexpectedLinebreakAfterOpeningBrace:
|
||||
"Unexpected line break after this opening brace.",
|
||||
expectedLinebreakBeforeClosingBrace:
|
||||
"Expected a line break before this closing brace.",
|
||||
expectedLinebreakAfterOpeningBrace:
|
||||
"Expected a line break after this opening brace.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
const normalizedOptions = normalizeOptions(context.options[0]);
|
||||
|
||||
/**
|
||||
* Reports a given node if it violated this rule.
|
||||
* @param {ASTNode} node A node to check. This is an ObjectExpression, ObjectPattern, ImportDeclaration or ExportNamedDeclaration node.
|
||||
* @returns {void}
|
||||
*/
|
||||
function check(node) {
|
||||
const options = normalizedOptions[node.type];
|
||||
|
||||
if (
|
||||
(node.type === "ImportDeclaration" &&
|
||||
!node.specifiers.some(
|
||||
specifier => specifier.type === "ImportSpecifier",
|
||||
)) ||
|
||||
(node.type === "ExportNamedDeclaration" &&
|
||||
!node.specifiers.some(
|
||||
specifier => specifier.type === "ExportSpecifier",
|
||||
))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const openBrace = sourceCode.getFirstToken(
|
||||
node,
|
||||
token => token.value === "{",
|
||||
);
|
||||
|
||||
let closeBrace;
|
||||
|
||||
if (node.typeAnnotation) {
|
||||
closeBrace = sourceCode.getTokenBefore(node.typeAnnotation);
|
||||
} else {
|
||||
closeBrace = sourceCode.getLastToken(
|
||||
node,
|
||||
token => token.value === "}",
|
||||
);
|
||||
}
|
||||
|
||||
let first = sourceCode.getTokenAfter(openBrace, {
|
||||
includeComments: true,
|
||||
});
|
||||
let last = sourceCode.getTokenBefore(closeBrace, {
|
||||
includeComments: true,
|
||||
});
|
||||
|
||||
const needsLineBreaks = areLineBreaksRequired(
|
||||
node,
|
||||
options,
|
||||
first,
|
||||
last,
|
||||
);
|
||||
|
||||
const hasCommentsFirstToken = astUtils.isCommentToken(first);
|
||||
const hasCommentsLastToken = astUtils.isCommentToken(last);
|
||||
|
||||
/*
|
||||
* Use tokens or comments to check multiline or not.
|
||||
* But use only tokens to check whether line breaks are needed.
|
||||
* This allows:
|
||||
* var obj = { // eslint-disable-line foo
|
||||
* a: 1
|
||||
* }
|
||||
*/
|
||||
first = sourceCode.getTokenAfter(openBrace);
|
||||
last = sourceCode.getTokenBefore(closeBrace);
|
||||
|
||||
if (needsLineBreaks) {
|
||||
if (astUtils.isTokenOnSameLine(openBrace, first)) {
|
||||
context.report({
|
||||
messageId: "expectedLinebreakAfterOpeningBrace",
|
||||
node,
|
||||
loc: openBrace.loc,
|
||||
fix(fixer) {
|
||||
if (hasCommentsFirstToken) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return fixer.insertTextAfter(openBrace, "\n");
|
||||
},
|
||||
});
|
||||
}
|
||||
if (astUtils.isTokenOnSameLine(last, closeBrace)) {
|
||||
context.report({
|
||||
messageId: "expectedLinebreakBeforeClosingBrace",
|
||||
node,
|
||||
loc: closeBrace.loc,
|
||||
fix(fixer) {
|
||||
if (hasCommentsLastToken) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return fixer.insertTextBefore(closeBrace, "\n");
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const consistent = options.consistent;
|
||||
const hasLineBreakBetweenOpenBraceAndFirst =
|
||||
!astUtils.isTokenOnSameLine(openBrace, first);
|
||||
const hasLineBreakBetweenCloseBraceAndLast =
|
||||
!astUtils.isTokenOnSameLine(last, closeBrace);
|
||||
|
||||
if (
|
||||
(!consistent && hasLineBreakBetweenOpenBraceAndFirst) ||
|
||||
(consistent &&
|
||||
hasLineBreakBetweenOpenBraceAndFirst &&
|
||||
!hasLineBreakBetweenCloseBraceAndLast)
|
||||
) {
|
||||
context.report({
|
||||
messageId: "unexpectedLinebreakAfterOpeningBrace",
|
||||
node,
|
||||
loc: openBrace.loc,
|
||||
fix(fixer) {
|
||||
if (hasCommentsFirstToken) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return fixer.removeRange([
|
||||
openBrace.range[1],
|
||||
first.range[0],
|
||||
]);
|
||||
},
|
||||
});
|
||||
}
|
||||
if (
|
||||
(!consistent && hasLineBreakBetweenCloseBraceAndLast) ||
|
||||
(consistent &&
|
||||
!hasLineBreakBetweenOpenBraceAndFirst &&
|
||||
hasLineBreakBetweenCloseBraceAndLast)
|
||||
) {
|
||||
context.report({
|
||||
messageId: "unexpectedLinebreakBeforeClosingBrace",
|
||||
node,
|
||||
loc: closeBrace.loc,
|
||||
fix(fixer) {
|
||||
if (hasCommentsLastToken) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return fixer.removeRange([
|
||||
last.range[1],
|
||||
closeBrace.range[0],
|
||||
]);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
ObjectExpression: check,
|
||||
ObjectPattern: check,
|
||||
ImportDeclaration: check,
|
||||
ExportNamedDeclaration: check,
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
import classApplyDescriptorDestructureSet from "./classApplyDescriptorDestructureSet.js";
|
||||
import assertClassBrand from "./assertClassBrand.js";
|
||||
import classCheckPrivateStaticFieldDescriptor from "./classCheckPrivateStaticFieldDescriptor.js";
|
||||
function _classStaticPrivateFieldDestructureSet(t, r, s) {
|
||||
return assertClassBrand(r, t), classCheckPrivateStaticFieldDescriptor(s, "set"), classApplyDescriptorDestructureSet(t, s);
|
||||
}
|
||||
export { _classStaticPrivateFieldDestructureSet as default };
|
||||
@@ -0,0 +1,718 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.psiFrobenius = psiFrobenius;
|
||||
exports.tower12 = tower12;
|
||||
/**
|
||||
* Towered extension fields.
|
||||
* Rather than implementing a massive 12th-degree extension directly, it is more efficient
|
||||
* to build it up from smaller extensions: a tower of extensions.
|
||||
*
|
||||
* For BLS12-381, the Fp12 field is implemented as a quadratic (degree two) extension,
|
||||
* on top of a cubic (degree three) extension, on top of a quadratic extension of Fp.
|
||||
*
|
||||
* For more info: "Pairings for beginners" by Costello, section 7.3.
|
||||
* @module
|
||||
*/
|
||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
const utils_ts_1 = require("../utils.js");
|
||||
const mod = require("./modular.js");
|
||||
// Be friendly to bad ECMAScript parsers by not using bigint literals
|
||||
// prettier-ignore
|
||||
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
|
||||
function calcFrobeniusCoefficients(Fp, nonResidue, modulus, degree, num = 1, divisor) {
|
||||
const _divisor = BigInt(divisor === undefined ? degree : divisor);
|
||||
const towerModulus = modulus ** BigInt(degree);
|
||||
const res = [];
|
||||
for (let i = 0; i < num; i++) {
|
||||
const a = BigInt(i + 1);
|
||||
const powers = [];
|
||||
for (let j = 0, qPower = _1n; j < degree; j++) {
|
||||
const power = ((a * qPower - a) / _divisor) % towerModulus;
|
||||
powers.push(Fp.pow(nonResidue, power));
|
||||
qPower *= modulus;
|
||||
}
|
||||
res.push(powers);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
// This works same at least for bls12-381, bn254 and bls12-377
|
||||
function psiFrobenius(Fp, Fp2, base) {
|
||||
// GLV endomorphism Ψ(P)
|
||||
const PSI_X = Fp2.pow(base, (Fp.ORDER - _1n) / _3n); // u^((p-1)/3)
|
||||
const PSI_Y = Fp2.pow(base, (Fp.ORDER - _1n) / _2n); // u^((p-1)/2)
|
||||
function psi(x, y) {
|
||||
// This x10 faster than previous version in bls12-381
|
||||
const x2 = Fp2.mul(Fp2.frobeniusMap(x, 1), PSI_X);
|
||||
const y2 = Fp2.mul(Fp2.frobeniusMap(y, 1), PSI_Y);
|
||||
return [x2, y2];
|
||||
}
|
||||
// Ψ²(P) endomorphism (psi2(x) = psi(psi(x)))
|
||||
const PSI2_X = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _3n); // u^((p^2 - 1)/3)
|
||||
// This equals -1, which causes y to be Fp2.neg(y).
|
||||
// But not sure if there are case when this is not true?
|
||||
const PSI2_Y = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _2n); // u^((p^2 - 1)/3)
|
||||
if (!Fp2.eql(PSI2_Y, Fp2.neg(Fp2.ONE)))
|
||||
throw new Error('psiFrobenius: PSI2_Y!==-1');
|
||||
function psi2(x, y) {
|
||||
return [Fp2.mul(x, PSI2_X), Fp2.neg(y)];
|
||||
}
|
||||
// Map points
|
||||
const mapAffine = (fn) => (c, P) => {
|
||||
const affine = P.toAffine();
|
||||
const p = fn(affine.x, affine.y);
|
||||
return c.fromAffine({ x: p[0], y: p[1] });
|
||||
};
|
||||
const G2psi = mapAffine(psi);
|
||||
const G2psi2 = mapAffine(psi2);
|
||||
return { psi, psi2, G2psi, G2psi2, PSI_X, PSI_Y, PSI2_X, PSI2_Y };
|
||||
}
|
||||
const Fp2fromBigTuple = (Fp, tuple) => {
|
||||
if (tuple.length !== 2)
|
||||
throw new Error('invalid tuple');
|
||||
const fps = tuple.map((n) => Fp.create(n));
|
||||
return { c0: fps[0], c1: fps[1] };
|
||||
};
|
||||
class _Field2 {
|
||||
constructor(Fp, opts = {}) {
|
||||
this.MASK = _1n;
|
||||
const ORDER = Fp.ORDER;
|
||||
const FP2_ORDER = ORDER * ORDER;
|
||||
this.Fp = Fp;
|
||||
this.ORDER = FP2_ORDER;
|
||||
this.BITS = (0, utils_ts_1.bitLen)(FP2_ORDER);
|
||||
this.BYTES = Math.ceil((0, utils_ts_1.bitLen)(FP2_ORDER) / 8);
|
||||
this.isLE = Fp.isLE;
|
||||
this.ZERO = { c0: Fp.ZERO, c1: Fp.ZERO };
|
||||
this.ONE = { c0: Fp.ONE, c1: Fp.ZERO };
|
||||
this.Fp_NONRESIDUE = Fp.create(opts.NONRESIDUE || BigInt(-1));
|
||||
this.Fp_div2 = Fp.div(Fp.ONE, _2n); // 1/2
|
||||
this.NONRESIDUE = Fp2fromBigTuple(Fp, opts.FP2_NONRESIDUE);
|
||||
// const Fp2Nonresidue = Fp2fromBigTuple(opts.FP2_NONRESIDUE);
|
||||
this.FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp, this.Fp_NONRESIDUE, Fp.ORDER, 2)[0];
|
||||
this.mulByB = opts.Fp2mulByB;
|
||||
Object.seal(this);
|
||||
}
|
||||
fromBigTuple(tuple) {
|
||||
return Fp2fromBigTuple(this.Fp, tuple);
|
||||
}
|
||||
create(num) {
|
||||
return num;
|
||||
}
|
||||
isValid({ c0, c1 }) {
|
||||
function isValidC(num, ORDER) {
|
||||
return typeof num === 'bigint' && _0n <= num && num < ORDER;
|
||||
}
|
||||
return isValidC(c0, this.ORDER) && isValidC(c1, this.ORDER);
|
||||
}
|
||||
is0({ c0, c1 }) {
|
||||
return this.Fp.is0(c0) && this.Fp.is0(c1);
|
||||
}
|
||||
isValidNot0(num) {
|
||||
return !this.is0(num) && this.isValid(num);
|
||||
}
|
||||
eql({ c0, c1 }, { c0: r0, c1: r1 }) {
|
||||
return this.Fp.eql(c0, r0) && this.Fp.eql(c1, r1);
|
||||
}
|
||||
neg({ c0, c1 }) {
|
||||
return { c0: this.Fp.neg(c0), c1: this.Fp.neg(c1) };
|
||||
}
|
||||
pow(num, power) {
|
||||
return mod.FpPow(this, num, power);
|
||||
}
|
||||
invertBatch(nums) {
|
||||
return mod.FpInvertBatch(this, nums);
|
||||
}
|
||||
// Normalized
|
||||
add(f1, f2) {
|
||||
const { c0, c1 } = f1;
|
||||
const { c0: r0, c1: r1 } = f2;
|
||||
return {
|
||||
c0: this.Fp.add(c0, r0),
|
||||
c1: this.Fp.add(c1, r1),
|
||||
};
|
||||
}
|
||||
sub({ c0, c1 }, { c0: r0, c1: r1 }) {
|
||||
return {
|
||||
c0: this.Fp.sub(c0, r0),
|
||||
c1: this.Fp.sub(c1, r1),
|
||||
};
|
||||
}
|
||||
mul({ c0, c1 }, rhs) {
|
||||
const { Fp } = this;
|
||||
if (typeof rhs === 'bigint')
|
||||
return { c0: Fp.mul(c0, rhs), c1: Fp.mul(c1, rhs) };
|
||||
// (a+bi)(c+di) = (ac−bd) + (ad+bc)i
|
||||
const { c0: r0, c1: r1 } = rhs;
|
||||
let t1 = Fp.mul(c0, r0); // c0 * o0
|
||||
let t2 = Fp.mul(c1, r1); // c1 * o1
|
||||
// (T1 - T2) + ((c0 + c1) * (r0 + r1) - (T1 + T2))*i
|
||||
const o0 = Fp.sub(t1, t2);
|
||||
const o1 = Fp.sub(Fp.mul(Fp.add(c0, c1), Fp.add(r0, r1)), Fp.add(t1, t2));
|
||||
return { c0: o0, c1: o1 };
|
||||
}
|
||||
sqr({ c0, c1 }) {
|
||||
const { Fp } = this;
|
||||
const a = Fp.add(c0, c1);
|
||||
const b = Fp.sub(c0, c1);
|
||||
const c = Fp.add(c0, c0);
|
||||
return { c0: Fp.mul(a, b), c1: Fp.mul(c, c1) };
|
||||
}
|
||||
// NonNormalized stuff
|
||||
addN(a, b) {
|
||||
return this.add(a, b);
|
||||
}
|
||||
subN(a, b) {
|
||||
return this.sub(a, b);
|
||||
}
|
||||
mulN(a, b) {
|
||||
return this.mul(a, b);
|
||||
}
|
||||
sqrN(a) {
|
||||
return this.sqr(a);
|
||||
}
|
||||
// Why inversion for bigint inside Fp instead of Fp2? it is even used in that context?
|
||||
div(lhs, rhs) {
|
||||
const { Fp } = this;
|
||||
// @ts-ignore
|
||||
return this.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : this.inv(rhs));
|
||||
}
|
||||
inv({ c0: a, c1: b }) {
|
||||
// We wish to find the multiplicative inverse of a nonzero
|
||||
// element a + bu in Fp2. We leverage an identity
|
||||
//
|
||||
// (a + bu)(a - bu) = a² + b²
|
||||
//
|
||||
// which holds because u² = -1. This can be rewritten as
|
||||
//
|
||||
// (a + bu)(a - bu)/(a² + b²) = 1
|
||||
//
|
||||
// because a² + b² = 0 has no nonzero solutions for (a, b).
|
||||
// This gives that (a - bu)/(a² + b²) is the inverse
|
||||
// of (a + bu). Importantly, this can be computing using
|
||||
// only a single inversion in Fp.
|
||||
const { Fp } = this;
|
||||
const factor = Fp.inv(Fp.create(a * a + b * b));
|
||||
return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) };
|
||||
}
|
||||
sqrt(num) {
|
||||
// This is generic for all quadratic extensions (Fp2)
|
||||
const { Fp } = this;
|
||||
const Fp2 = this;
|
||||
const { c0, c1 } = num;
|
||||
if (Fp.is0(c1)) {
|
||||
// if c0 is quadratic residue
|
||||
if (mod.FpLegendre(Fp, c0) === 1)
|
||||
return Fp2.create({ c0: Fp.sqrt(c0), c1: Fp.ZERO });
|
||||
else
|
||||
return Fp2.create({ c0: Fp.ZERO, c1: Fp.sqrt(Fp.div(c0, this.Fp_NONRESIDUE)) });
|
||||
}
|
||||
const a = Fp.sqrt(Fp.sub(Fp.sqr(c0), Fp.mul(Fp.sqr(c1), this.Fp_NONRESIDUE)));
|
||||
let d = Fp.mul(Fp.add(a, c0), this.Fp_div2);
|
||||
const legendre = mod.FpLegendre(Fp, d);
|
||||
// -1, Quadratic non residue
|
||||
if (legendre === -1)
|
||||
d = Fp.sub(d, a);
|
||||
const a0 = Fp.sqrt(d);
|
||||
const candidateSqrt = Fp2.create({ c0: a0, c1: Fp.div(Fp.mul(c1, this.Fp_div2), a0) });
|
||||
if (!Fp2.eql(Fp2.sqr(candidateSqrt), num))
|
||||
throw new Error('Cannot find square root');
|
||||
// Normalize root: at this point candidateSqrt ** 2 = num, but also -candidateSqrt ** 2 = num
|
||||
const x1 = candidateSqrt;
|
||||
const x2 = Fp2.neg(x1);
|
||||
const { re: re1, im: im1 } = Fp2.reim(x1);
|
||||
const { re: re2, im: im2 } = Fp2.reim(x2);
|
||||
if (im1 > im2 || (im1 === im2 && re1 > re2))
|
||||
return x1;
|
||||
return x2;
|
||||
}
|
||||
// Same as sgn0_m_eq_2 in RFC 9380
|
||||
isOdd(x) {
|
||||
const { re: x0, im: x1 } = this.reim(x);
|
||||
const sign_0 = x0 % _2n;
|
||||
const zero_0 = x0 === _0n;
|
||||
const sign_1 = x1 % _2n;
|
||||
return BigInt(sign_0 || (zero_0 && sign_1)) == _1n;
|
||||
}
|
||||
// Bytes util
|
||||
fromBytes(b) {
|
||||
const { Fp } = this;
|
||||
if (b.length !== this.BYTES)
|
||||
throw new Error('fromBytes invalid length=' + b.length);
|
||||
return { c0: Fp.fromBytes(b.subarray(0, Fp.BYTES)), c1: Fp.fromBytes(b.subarray(Fp.BYTES)) };
|
||||
}
|
||||
toBytes({ c0, c1 }) {
|
||||
return (0, utils_ts_1.concatBytes)(this.Fp.toBytes(c0), this.Fp.toBytes(c1));
|
||||
}
|
||||
cmov({ c0, c1 }, { c0: r0, c1: r1 }, c) {
|
||||
return {
|
||||
c0: this.Fp.cmov(c0, r0, c),
|
||||
c1: this.Fp.cmov(c1, r1, c),
|
||||
};
|
||||
}
|
||||
reim({ c0, c1 }) {
|
||||
return { re: c0, im: c1 };
|
||||
}
|
||||
Fp4Square(a, b) {
|
||||
const Fp2 = this;
|
||||
const a2 = Fp2.sqr(a);
|
||||
const b2 = Fp2.sqr(b);
|
||||
return {
|
||||
first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a²
|
||||
second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b²
|
||||
};
|
||||
}
|
||||
// multiply by u + 1
|
||||
mulByNonresidue({ c0, c1 }) {
|
||||
return this.mul({ c0, c1 }, this.NONRESIDUE);
|
||||
}
|
||||
frobeniusMap({ c0, c1 }, power) {
|
||||
return {
|
||||
c0,
|
||||
c1: this.Fp.mul(c1, this.FROBENIUS_COEFFICIENTS[power % 2]),
|
||||
};
|
||||
}
|
||||
}
|
||||
class _Field6 {
|
||||
constructor(Fp2) {
|
||||
this.MASK = _1n;
|
||||
this.Fp2 = Fp2;
|
||||
this.ORDER = Fp2.ORDER; // TODO: unused, but need to verify
|
||||
this.BITS = 3 * Fp2.BITS;
|
||||
this.BYTES = 3 * Fp2.BYTES;
|
||||
this.isLE = Fp2.isLE;
|
||||
this.ZERO = { c0: Fp2.ZERO, c1: Fp2.ZERO, c2: Fp2.ZERO };
|
||||
this.ONE = { c0: Fp2.ONE, c1: Fp2.ZERO, c2: Fp2.ZERO };
|
||||
const { Fp } = Fp2;
|
||||
const frob = calcFrobeniusCoefficients(Fp2, Fp2.NONRESIDUE, Fp.ORDER, 6, 2, 3);
|
||||
this.FROBENIUS_COEFFICIENTS_1 = frob[0];
|
||||
this.FROBENIUS_COEFFICIENTS_2 = frob[1];
|
||||
Object.seal(this);
|
||||
}
|
||||
add({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) {
|
||||
const { Fp2 } = this;
|
||||
return {
|
||||
c0: Fp2.add(c0, r0),
|
||||
c1: Fp2.add(c1, r1),
|
||||
c2: Fp2.add(c2, r2),
|
||||
};
|
||||
}
|
||||
sub({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) {
|
||||
const { Fp2 } = this;
|
||||
return {
|
||||
c0: Fp2.sub(c0, r0),
|
||||
c1: Fp2.sub(c1, r1),
|
||||
c2: Fp2.sub(c2, r2),
|
||||
};
|
||||
}
|
||||
mul({ c0, c1, c2 }, rhs) {
|
||||
const { Fp2 } = this;
|
||||
if (typeof rhs === 'bigint') {
|
||||
return {
|
||||
c0: Fp2.mul(c0, rhs),
|
||||
c1: Fp2.mul(c1, rhs),
|
||||
c2: Fp2.mul(c2, rhs),
|
||||
};
|
||||
}
|
||||
const { c0: r0, c1: r1, c2: r2 } = rhs;
|
||||
const t0 = Fp2.mul(c0, r0); // c0 * o0
|
||||
const t1 = Fp2.mul(c1, r1); // c1 * o1
|
||||
const t2 = Fp2.mul(c2, r2); // c2 * o2
|
||||
return {
|
||||
// t0 + (c1 + c2) * (r1 * r2) - (T1 + T2) * (u + 1)
|
||||
c0: Fp2.add(t0, Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), Fp2.add(r1, r2)), Fp2.add(t1, t2)))),
|
||||
// (c0 + c1) * (r0 + r1) - (T0 + T1) + T2 * (u + 1)
|
||||
c1: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c1), Fp2.add(r0, r1)), Fp2.add(t0, t1)), Fp2.mulByNonresidue(t2)),
|
||||
// T1 + (c0 + c2) * (r0 + r2) - T0 + T2
|
||||
c2: Fp2.sub(Fp2.add(t1, Fp2.mul(Fp2.add(c0, c2), Fp2.add(r0, r2))), Fp2.add(t0, t2)),
|
||||
};
|
||||
}
|
||||
sqr({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
let t0 = Fp2.sqr(c0); // c0²
|
||||
let t1 = Fp2.mul(Fp2.mul(c0, c1), _2n); // 2 * c0 * c1
|
||||
let t3 = Fp2.mul(Fp2.mul(c1, c2), _2n); // 2 * c1 * c2
|
||||
let t4 = Fp2.sqr(c2); // c2²
|
||||
return {
|
||||
c0: Fp2.add(Fp2.mulByNonresidue(t3), t0), // T3 * (u + 1) + T0
|
||||
c1: Fp2.add(Fp2.mulByNonresidue(t4), t1), // T4 * (u + 1) + T1
|
||||
// T1 + (c0 - c1 + c2)² + T3 - T0 - T4
|
||||
c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.sqr(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0), t4),
|
||||
};
|
||||
}
|
||||
addN(a, b) {
|
||||
return this.add(a, b);
|
||||
}
|
||||
subN(a, b) {
|
||||
return this.sub(a, b);
|
||||
}
|
||||
mulN(a, b) {
|
||||
return this.mul(a, b);
|
||||
}
|
||||
sqrN(a) {
|
||||
return this.sqr(a);
|
||||
}
|
||||
create(num) {
|
||||
return num;
|
||||
}
|
||||
isValid({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
return Fp2.isValid(c0) && Fp2.isValid(c1) && Fp2.isValid(c2);
|
||||
}
|
||||
is0({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
return Fp2.is0(c0) && Fp2.is0(c1) && Fp2.is0(c2);
|
||||
}
|
||||
isValidNot0(num) {
|
||||
return !this.is0(num) && this.isValid(num);
|
||||
}
|
||||
neg({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
return { c0: Fp2.neg(c0), c1: Fp2.neg(c1), c2: Fp2.neg(c2) };
|
||||
}
|
||||
eql({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) {
|
||||
const { Fp2 } = this;
|
||||
return Fp2.eql(c0, r0) && Fp2.eql(c1, r1) && Fp2.eql(c2, r2);
|
||||
}
|
||||
sqrt(_) {
|
||||
return (0, utils_ts_1.notImplemented)();
|
||||
}
|
||||
// Do we need division by bigint at all? Should be done via order:
|
||||
div(lhs, rhs) {
|
||||
const { Fp2 } = this;
|
||||
const { Fp } = Fp2;
|
||||
return this.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : this.inv(rhs));
|
||||
}
|
||||
pow(num, power) {
|
||||
return mod.FpPow(this, num, power);
|
||||
}
|
||||
invertBatch(nums) {
|
||||
return mod.FpInvertBatch(this, nums);
|
||||
}
|
||||
inv({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
let t0 = Fp2.sub(Fp2.sqr(c0), Fp2.mulByNonresidue(Fp2.mul(c2, c1))); // c0² - c2 * c1 * (u + 1)
|
||||
let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.sqr(c2)), Fp2.mul(c0, c1)); // c2² * (u + 1) - c0 * c1
|
||||
let t2 = Fp2.sub(Fp2.sqr(c1), Fp2.mul(c0, c2)); // c1² - c0 * c2
|
||||
// 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0)
|
||||
let t4 = Fp2.inv(Fp2.add(Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))), Fp2.mul(c0, t0)));
|
||||
return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) };
|
||||
}
|
||||
// Bytes utils
|
||||
fromBytes(b) {
|
||||
const { Fp2 } = this;
|
||||
if (b.length !== this.BYTES)
|
||||
throw new Error('fromBytes invalid length=' + b.length);
|
||||
const B2 = Fp2.BYTES;
|
||||
return {
|
||||
c0: Fp2.fromBytes(b.subarray(0, B2)),
|
||||
c1: Fp2.fromBytes(b.subarray(B2, B2 * 2)),
|
||||
c2: Fp2.fromBytes(b.subarray(2 * B2)),
|
||||
};
|
||||
}
|
||||
toBytes({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
return (0, utils_ts_1.concatBytes)(Fp2.toBytes(c0), Fp2.toBytes(c1), Fp2.toBytes(c2));
|
||||
}
|
||||
cmov({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }, c) {
|
||||
const { Fp2 } = this;
|
||||
return {
|
||||
c0: Fp2.cmov(c0, r0, c),
|
||||
c1: Fp2.cmov(c1, r1, c),
|
||||
c2: Fp2.cmov(c2, r2, c),
|
||||
};
|
||||
}
|
||||
fromBigSix(t) {
|
||||
const { Fp2 } = this;
|
||||
if (!Array.isArray(t) || t.length !== 6)
|
||||
throw new Error('invalid Fp6 usage');
|
||||
return {
|
||||
c0: Fp2.fromBigTuple(t.slice(0, 2)),
|
||||
c1: Fp2.fromBigTuple(t.slice(2, 4)),
|
||||
c2: Fp2.fromBigTuple(t.slice(4, 6)),
|
||||
};
|
||||
}
|
||||
frobeniusMap({ c0, c1, c2 }, power) {
|
||||
const { Fp2 } = this;
|
||||
return {
|
||||
c0: Fp2.frobeniusMap(c0, power),
|
||||
c1: Fp2.mul(Fp2.frobeniusMap(c1, power), this.FROBENIUS_COEFFICIENTS_1[power % 6]),
|
||||
c2: Fp2.mul(Fp2.frobeniusMap(c2, power), this.FROBENIUS_COEFFICIENTS_2[power % 6]),
|
||||
};
|
||||
}
|
||||
mulByFp2({ c0, c1, c2 }, rhs) {
|
||||
const { Fp2 } = this;
|
||||
return {
|
||||
c0: Fp2.mul(c0, rhs),
|
||||
c1: Fp2.mul(c1, rhs),
|
||||
c2: Fp2.mul(c2, rhs),
|
||||
};
|
||||
}
|
||||
mulByNonresidue({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
return { c0: Fp2.mulByNonresidue(c2), c1: c0, c2: c1 };
|
||||
}
|
||||
// Sparse multiplication
|
||||
mul1({ c0, c1, c2 }, b1) {
|
||||
const { Fp2 } = this;
|
||||
return {
|
||||
c0: Fp2.mulByNonresidue(Fp2.mul(c2, b1)),
|
||||
c1: Fp2.mul(c0, b1),
|
||||
c2: Fp2.mul(c1, b1),
|
||||
};
|
||||
}
|
||||
// Sparse multiplication
|
||||
mul01({ c0, c1, c2 }, b0, b1) {
|
||||
const { Fp2 } = this;
|
||||
let t0 = Fp2.mul(c0, b0); // c0 * b0
|
||||
let t1 = Fp2.mul(c1, b1); // c1 * b1
|
||||
return {
|
||||
// ((c1 + c2) * b1 - T1) * (u + 1) + T0
|
||||
c0: Fp2.add(Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), b1), t1)), t0),
|
||||
// (b0 + b1) * (c0 + c1) - T0 - T1
|
||||
c1: Fp2.sub(Fp2.sub(Fp2.mul(Fp2.add(b0, b1), Fp2.add(c0, c1)), t0), t1),
|
||||
// (c0 + c2) * b0 - T0 + T1
|
||||
c2: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c2), b0), t0), t1),
|
||||
};
|
||||
}
|
||||
}
|
||||
class _Field12 {
|
||||
constructor(Fp6, opts) {
|
||||
this.MASK = _1n;
|
||||
const { Fp2 } = Fp6;
|
||||
const { Fp } = Fp2;
|
||||
this.Fp6 = Fp6;
|
||||
this.ORDER = Fp2.ORDER; // TODO: verify if it's unuesd
|
||||
this.BITS = 2 * Fp6.BITS;
|
||||
this.BYTES = 2 * Fp6.BYTES;
|
||||
this.isLE = Fp6.isLE;
|
||||
this.ZERO = { c0: Fp6.ZERO, c1: Fp6.ZERO };
|
||||
this.ONE = { c0: Fp6.ONE, c1: Fp6.ZERO };
|
||||
this.FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp2, Fp2.NONRESIDUE, Fp.ORDER, 12, 1, 6)[0];
|
||||
this.X_LEN = opts.X_LEN;
|
||||
this.finalExponentiate = opts.Fp12finalExponentiate;
|
||||
}
|
||||
create(num) {
|
||||
return num;
|
||||
}
|
||||
isValid({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
return Fp6.isValid(c0) && Fp6.isValid(c1);
|
||||
}
|
||||
is0({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
return Fp6.is0(c0) && Fp6.is0(c1);
|
||||
}
|
||||
isValidNot0(num) {
|
||||
return !this.is0(num) && this.isValid(num);
|
||||
}
|
||||
neg({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
return { c0: Fp6.neg(c0), c1: Fp6.neg(c1) };
|
||||
}
|
||||
eql({ c0, c1 }, { c0: r0, c1: r1 }) {
|
||||
const { Fp6 } = this;
|
||||
return Fp6.eql(c0, r0) && Fp6.eql(c1, r1);
|
||||
}
|
||||
sqrt(_) {
|
||||
(0, utils_ts_1.notImplemented)();
|
||||
}
|
||||
inv({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
let t = Fp6.inv(Fp6.sub(Fp6.sqr(c0), Fp6.mulByNonresidue(Fp6.sqr(c1)))); // 1 / (c0² - c1² * v)
|
||||
return { c0: Fp6.mul(c0, t), c1: Fp6.neg(Fp6.mul(c1, t)) }; // ((C0 * T) * T) + (-C1 * T) * w
|
||||
}
|
||||
div(lhs, rhs) {
|
||||
const { Fp6 } = this;
|
||||
const { Fp2 } = Fp6;
|
||||
const { Fp } = Fp2;
|
||||
return this.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : this.inv(rhs));
|
||||
}
|
||||
pow(num, power) {
|
||||
return mod.FpPow(this, num, power);
|
||||
}
|
||||
invertBatch(nums) {
|
||||
return mod.FpInvertBatch(this, nums);
|
||||
}
|
||||
// Normalized
|
||||
add({ c0, c1 }, { c0: r0, c1: r1 }) {
|
||||
const { Fp6 } = this;
|
||||
return {
|
||||
c0: Fp6.add(c0, r0),
|
||||
c1: Fp6.add(c1, r1),
|
||||
};
|
||||
}
|
||||
sub({ c0, c1 }, { c0: r0, c1: r1 }) {
|
||||
const { Fp6 } = this;
|
||||
return {
|
||||
c0: Fp6.sub(c0, r0),
|
||||
c1: Fp6.sub(c1, r1),
|
||||
};
|
||||
}
|
||||
mul({ c0, c1 }, rhs) {
|
||||
const { Fp6 } = this;
|
||||
if (typeof rhs === 'bigint')
|
||||
return { c0: Fp6.mul(c0, rhs), c1: Fp6.mul(c1, rhs) };
|
||||
let { c0: r0, c1: r1 } = rhs;
|
||||
let t1 = Fp6.mul(c0, r0); // c0 * r0
|
||||
let t2 = Fp6.mul(c1, r1); // c1 * r1
|
||||
return {
|
||||
c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)), // T1 + T2 * v
|
||||
// (c0 + c1) * (r0 + r1) - (T1 + T2)
|
||||
c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)),
|
||||
};
|
||||
}
|
||||
sqr({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
let ab = Fp6.mul(c0, c1); // c0 * c1
|
||||
return {
|
||||
// (c1 * v + c0) * (c0 + c1) - AB - AB * v
|
||||
c0: Fp6.sub(Fp6.sub(Fp6.mul(Fp6.add(Fp6.mulByNonresidue(c1), c0), Fp6.add(c0, c1)), ab), Fp6.mulByNonresidue(ab)),
|
||||
c1: Fp6.add(ab, ab),
|
||||
}; // AB + AB
|
||||
}
|
||||
// NonNormalized stuff
|
||||
addN(a, b) {
|
||||
return this.add(a, b);
|
||||
}
|
||||
subN(a, b) {
|
||||
return this.sub(a, b);
|
||||
}
|
||||
mulN(a, b) {
|
||||
return this.mul(a, b);
|
||||
}
|
||||
sqrN(a) {
|
||||
return this.sqr(a);
|
||||
}
|
||||
// Bytes utils
|
||||
fromBytes(b) {
|
||||
const { Fp6 } = this;
|
||||
if (b.length !== this.BYTES)
|
||||
throw new Error('fromBytes invalid length=' + b.length);
|
||||
return {
|
||||
c0: Fp6.fromBytes(b.subarray(0, Fp6.BYTES)),
|
||||
c1: Fp6.fromBytes(b.subarray(Fp6.BYTES)),
|
||||
};
|
||||
}
|
||||
toBytes({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
return (0, utils_ts_1.concatBytes)(Fp6.toBytes(c0), Fp6.toBytes(c1));
|
||||
}
|
||||
cmov({ c0, c1 }, { c0: r0, c1: r1 }, c) {
|
||||
const { Fp6 } = this;
|
||||
return {
|
||||
c0: Fp6.cmov(c0, r0, c),
|
||||
c1: Fp6.cmov(c1, r1, c),
|
||||
};
|
||||
}
|
||||
// Utils
|
||||
// toString() {
|
||||
// return '' + 'Fp12(' + this.c0 + this.c1 + '* w');
|
||||
// },
|
||||
// fromTuple(c: [Fp6, Fp6]) {
|
||||
// return new Fp12(...c);
|
||||
// }
|
||||
fromBigTwelve(t) {
|
||||
const { Fp6 } = this;
|
||||
return {
|
||||
c0: Fp6.fromBigSix(t.slice(0, 6)),
|
||||
c1: Fp6.fromBigSix(t.slice(6, 12)),
|
||||
};
|
||||
}
|
||||
// Raises to q**i -th power
|
||||
frobeniusMap(lhs, power) {
|
||||
const { Fp6 } = this;
|
||||
const { Fp2 } = Fp6;
|
||||
const { c0, c1, c2 } = Fp6.frobeniusMap(lhs.c1, power);
|
||||
const coeff = this.FROBENIUS_COEFFICIENTS[power % 12];
|
||||
return {
|
||||
c0: Fp6.frobeniusMap(lhs.c0, power),
|
||||
c1: Fp6.create({
|
||||
c0: Fp2.mul(c0, coeff),
|
||||
c1: Fp2.mul(c1, coeff),
|
||||
c2: Fp2.mul(c2, coeff),
|
||||
}),
|
||||
};
|
||||
}
|
||||
mulByFp2({ c0, c1 }, rhs) {
|
||||
const { Fp6 } = this;
|
||||
return {
|
||||
c0: Fp6.mulByFp2(c0, rhs),
|
||||
c1: Fp6.mulByFp2(c1, rhs),
|
||||
};
|
||||
}
|
||||
conjugate({ c0, c1 }) {
|
||||
return { c0, c1: this.Fp6.neg(c1) };
|
||||
}
|
||||
// Sparse multiplication
|
||||
mul014({ c0, c1 }, o0, o1, o4) {
|
||||
const { Fp6 } = this;
|
||||
const { Fp2 } = Fp6;
|
||||
let t0 = Fp6.mul01(c0, o0, o1);
|
||||
let t1 = Fp6.mul1(c1, o4);
|
||||
return {
|
||||
c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0
|
||||
// (c1 + c0) * [o0, o1+o4] - T0 - T1
|
||||
c1: Fp6.sub(Fp6.sub(Fp6.mul01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1),
|
||||
};
|
||||
}
|
||||
mul034({ c0, c1 }, o0, o3, o4) {
|
||||
const { Fp6 } = this;
|
||||
const { Fp2 } = Fp6;
|
||||
const a = Fp6.create({
|
||||
c0: Fp2.mul(c0.c0, o0),
|
||||
c1: Fp2.mul(c0.c1, o0),
|
||||
c2: Fp2.mul(c0.c2, o0),
|
||||
});
|
||||
const b = Fp6.mul01(c1, o3, o4);
|
||||
const e = Fp6.mul01(Fp6.add(c0, c1), Fp2.add(o0, o3), o4);
|
||||
return {
|
||||
c0: Fp6.add(Fp6.mulByNonresidue(b), a),
|
||||
c1: Fp6.sub(e, Fp6.add(a, b)),
|
||||
};
|
||||
}
|
||||
// A cyclotomic group is a subgroup of Fp^n defined by
|
||||
// GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1}
|
||||
// The result of any pairing is in a cyclotomic subgroup
|
||||
// https://eprint.iacr.org/2009/565.pdf
|
||||
// https://eprint.iacr.org/2010/354.pdf
|
||||
_cyclotomicSquare({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
const { Fp2 } = Fp6;
|
||||
const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0;
|
||||
const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1;
|
||||
const { first: t3, second: t4 } = Fp2.Fp4Square(c0c0, c1c1);
|
||||
const { first: t5, second: t6 } = Fp2.Fp4Square(c1c0, c0c2);
|
||||
const { first: t7, second: t8 } = Fp2.Fp4Square(c0c1, c1c2);
|
||||
const t9 = Fp2.mulByNonresidue(t8); // T8 * (u + 1)
|
||||
return {
|
||||
c0: Fp6.create({
|
||||
c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3
|
||||
c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5
|
||||
c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7),
|
||||
}), // 2 * (T7 - c0c2) + T7
|
||||
c1: Fp6.create({
|
||||
c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9
|
||||
c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4
|
||||
c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6),
|
||||
}),
|
||||
}; // 2 * (T6 + c1c2) + T6
|
||||
}
|
||||
// https://eprint.iacr.org/2009/565.pdf
|
||||
_cyclotomicExp(num, n) {
|
||||
let z = this.ONE;
|
||||
for (let i = this.X_LEN - 1; i >= 0; i--) {
|
||||
z = this._cyclotomicSquare(z);
|
||||
if ((0, utils_ts_1.bitGet)(n, i))
|
||||
z = this.mul(z, num);
|
||||
}
|
||||
return z;
|
||||
}
|
||||
}
|
||||
function tower12(opts) {
|
||||
const Fp = mod.Field(opts.ORDER);
|
||||
const Fp2 = new _Field2(Fp, opts);
|
||||
const Fp6 = new _Field6(Fp2);
|
||||
const Fp12 = new _Field12(Fp6, opts);
|
||||
return { Fp, Fp2, Fp6, Fp12 };
|
||||
}
|
||||
//# sourceMappingURL=tower.js.map
|
||||
@@ -0,0 +1,85 @@
|
||||
# EventEmitter3
|
||||
|
||||
[](https://www.npmjs.com/package/eventemitter3)[](https://github.com/primus/eventemitter3/actions?query=workflow%3ACI+branch%3Amaster)[](https://coveralls.io/r/primus/eventemitter3?branch=master)
|
||||
|
||||
EventEmitter3 is a high performance EventEmitter. It has been micro-optimized
|
||||
for various of code paths making this, one of, if not the fastest EventEmitter
|
||||
available for Node.js and browsers. The module is API compatible with the
|
||||
EventEmitter that ships by default with Node.js but there are some slight
|
||||
differences:
|
||||
|
||||
- Domain support has been removed.
|
||||
- We do not `throw` an error when you emit an `error` event and nobody is
|
||||
listening.
|
||||
- The `newListener` and `removeListener` events have been removed as they
|
||||
are useful only in some uncommon use-cases.
|
||||
- The `setMaxListeners`, `getMaxListeners`, `prependListener` and
|
||||
`prependOnceListener` methods are not available.
|
||||
- Support for custom context for events so there is no need to use `fn.bind`.
|
||||
- The `removeListener` method removes all matching listeners, not only the
|
||||
first.
|
||||
|
||||
It's a drop in replacement for existing EventEmitters, but just faster. Free
|
||||
performance, who wouldn't want that? The EventEmitter is written in EcmaScript 3
|
||||
so it will work in the oldest browsers and node versions that you need to
|
||||
support.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
$ npm install --save eventemitter3
|
||||
```
|
||||
|
||||
## CDN
|
||||
|
||||
Recommended CDN:
|
||||
|
||||
```text
|
||||
https://unpkg.com/eventemitter3@latest/dist/eventemitter3.umd.min.js
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
After installation the only thing you need to do is require the module:
|
||||
|
||||
```js
|
||||
var EventEmitter = require('eventemitter3');
|
||||
```
|
||||
|
||||
And you're ready to create your own EventEmitter instances. For the API
|
||||
documentation, please follow the official Node.js documentation:
|
||||
|
||||
http://nodejs.org/api/events.html
|
||||
|
||||
### Contextual emits
|
||||
|
||||
We've upgraded the API of the `EventEmitter.on`, `EventEmitter.once` and
|
||||
`EventEmitter.removeListener` to accept an extra argument which is the `context`
|
||||
or `this` value that should be set for the emitted events. This means you no
|
||||
longer have the overhead of an event that required `fn.bind` in order to get a
|
||||
custom `this` value.
|
||||
|
||||
```js
|
||||
var EE = new EventEmitter()
|
||||
, context = { foo: 'bar' };
|
||||
|
||||
function emitted() {
|
||||
console.log(this === context); // true
|
||||
}
|
||||
|
||||
EE.once('event-name', emitted, context);
|
||||
EE.on('another-event', emitted, context);
|
||||
EE.removeListener('another-event', emitted, context);
|
||||
```
|
||||
|
||||
### Tests and benchmarks
|
||||
|
||||
To run tests run `npm test`. To run the benchmarks run `npm run benchmark`.
|
||||
|
||||
Tests and benchmarks are not included in the npm package. If you want to play
|
||||
with them you have to clone the GitHub repository. Note that you will have to
|
||||
run an additional `npm i` in the benchmarks folder before `npm run benchmark`.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
@@ -0,0 +1,46 @@
|
||||
{{# def.definitions }}
|
||||
{{# def.errors }}
|
||||
{{# def.setupKeyword }}
|
||||
{{# def.setupNextLevel }}
|
||||
|
||||
{{
|
||||
var $noEmptySchema = $schema.every(function($sch) {
|
||||
return {{# def.nonEmptySchema:$sch }};
|
||||
});
|
||||
}}
|
||||
{{? $noEmptySchema }}
|
||||
{{ var $currentBaseId = $it.baseId; }}
|
||||
var {{=$errs}} = errors;
|
||||
var {{=$valid}} = false;
|
||||
|
||||
{{# def.setCompositeRule }}
|
||||
|
||||
{{~ $schema:$sch:$i }}
|
||||
{{
|
||||
$it.schema = $sch;
|
||||
$it.schemaPath = $schemaPath + '[' + $i + ']';
|
||||
$it.errSchemaPath = $errSchemaPath + '/' + $i;
|
||||
}}
|
||||
|
||||
{{# def.insertSubschemaCode }}
|
||||
|
||||
{{=$valid}} = {{=$valid}} || {{=$nextValid}};
|
||||
|
||||
if (!{{=$valid}}) {
|
||||
{{ $closingBraces += '}'; }}
|
||||
{{~}}
|
||||
|
||||
{{# def.resetCompositeRule }}
|
||||
|
||||
{{= $closingBraces }}
|
||||
|
||||
if (!{{=$valid}}) {
|
||||
{{# def.extraError:'anyOf' }}
|
||||
} else {
|
||||
{{# def.resetErrors }}
|
||||
{{? it.opts.allErrors }} } {{?}}
|
||||
{{??}}
|
||||
{{? $breakOnError }}
|
||||
if (true) {
|
||||
{{?}}
|
||||
{{?}}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"blake2b.js","sourceRoot":"","sources":["src/blake2b.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,2CAA6D;AAC7D,+DAA+D;AAClD,QAAA,OAAO,GAAe,mBAAG,CAAC;AACvC,+DAA+D;AAClD,QAAA,OAAO,GAAe,mBAAG,CAAC"}
|
||||
@@ -0,0 +1,85 @@
|
||||
{
|
||||
"name": "superstruct",
|
||||
"description": "A simple and composable way to validate data in JavaScript (and TypeScript).",
|
||||
"version": "2.0.2",
|
||||
"license": "MIT",
|
||||
"repository": "git://github.com/ianstormtaylor/superstruct.git",
|
||||
"type": "module",
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"publishConfig": {
|
||||
"registry": "https://registry.npmjs.org"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-typescript": "^11.1.6",
|
||||
"@types/expect": "^24.3.0",
|
||||
"@types/lodash": "^4.14.144",
|
||||
"@types/node": "^18.7.14",
|
||||
"@typescript-eslint/eslint-plugin": "^7.1.1",
|
||||
"@typescript-eslint/parser": "^7.1.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"lodash": "^4.17.15",
|
||||
"np": "^10.0.0",
|
||||
"prettier": "^3.2.5",
|
||||
"rollup": "^4.12.1",
|
||||
"typescript": "^4.8.3",
|
||||
"vitest": "^1.6.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rm -rf ./{dist} && rollup --config ./rollup.config.js",
|
||||
"clean": "rm -rf ./{dist,node_modules}",
|
||||
"fix": "npm run fix:eslint && npm run fix:prettier",
|
||||
"fix:eslint": "npm run lint:eslint --fix",
|
||||
"fix:prettier": "prettier '**/*.{js,json,ts}' --write",
|
||||
"lint": "npm run lint:eslint && npm run lint:prettier",
|
||||
"lint:eslint": "eslint '{src,test}/*.{js,ts}'",
|
||||
"lint:prettier": "prettier '**/*.{js,json,ts}' --check",
|
||||
"release": "npm run build && npm run lint && np",
|
||||
"test": "npm run build && npm run test:types && npm run test:vitest",
|
||||
"test:types": "tsc --noEmit && tsc --project ./test/tsconfig.json --noEmit",
|
||||
"test:vitest": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"watch": "npm run build -- --watch"
|
||||
},
|
||||
"keywords": [
|
||||
"api",
|
||||
"array",
|
||||
"assert",
|
||||
"cast",
|
||||
"check",
|
||||
"checker",
|
||||
"collection",
|
||||
"data",
|
||||
"error",
|
||||
"express",
|
||||
"hapi",
|
||||
"interface",
|
||||
"invalid",
|
||||
"joi",
|
||||
"json",
|
||||
"list",
|
||||
"model",
|
||||
"object",
|
||||
"orm",
|
||||
"scalar",
|
||||
"schema",
|
||||
"struct",
|
||||
"throw",
|
||||
"type",
|
||||
"types",
|
||||
"valid",
|
||||
"validate",
|
||||
"validation",
|
||||
"validator"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024-present VoidZero Inc. & Contributors
|
||||
Copyright (c) 2023 Boshen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
Reference in New Issue
Block a user