WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,268 @@
|
||||
import { _ as _to_array } from "./_to_array.js";
|
||||
import { _ as _to_property_key } from "./_to_property_key.js";
|
||||
import { _ as _type_of } from "./_type_of.js";
|
||||
|
||||
function _decorate(decorators, factory, superClass) {
|
||||
var r = factory(function initialize(O) {
|
||||
_initializeInstanceElements(O, decorated.elements);
|
||||
}, superClass);
|
||||
var decorated = _decorateClass(_coalesceClassElements(r.d.map(_createElementDescriptor)), decorators);
|
||||
_initializeClassElements(r.F, decorated.elements);
|
||||
|
||||
return _runClassFinishers(r.F, decorated.finishers);
|
||||
}
|
||||
|
||||
function _createElementDescriptor(def) {
|
||||
var key = _to_property_key(def.key);
|
||||
var descriptor;
|
||||
|
||||
if (def.kind === "method") {
|
||||
descriptor = { value: def.value, writable: true, configurable: true, enumerable: false };
|
||||
Object.defineProperty(def.value, "name", { value: _type_of(key) === "symbol" ? "" : key, configurable: true });
|
||||
} else if (def.kind === "get") descriptor = { get: def.value, configurable: true, enumerable: false };
|
||||
else if (def.kind === "set") descriptor = { set: def.value, configurable: true, enumerable: false };
|
||||
else if (def.kind === "field") descriptor = { configurable: true, writable: true, enumerable: true };
|
||||
|
||||
var element = { kind: def.kind === "field" ? "field" : "method", key: key, placement: def.static ? "static" : def.kind === "field" ? "own" : "prototype", descriptor: descriptor };
|
||||
|
||||
if (def.decorators) element.decorators = def.decorators;
|
||||
|
||||
if (def.kind === "field") element.initializer = def.value;
|
||||
|
||||
return element;
|
||||
}
|
||||
function _coalesceGetterSetter(element, other) {
|
||||
if (element.descriptor.get !== undefined) other.descriptor.get = element.descriptor.get;
|
||||
else other.descriptor.set = element.descriptor.set;
|
||||
}
|
||||
function _coalesceClassElements(elements) {
|
||||
var newElements = [];
|
||||
var isSameElement = function isSameElement(other) {
|
||||
return other.kind === "method" && other.key === element.key && other.placement === element.placement;
|
||||
};
|
||||
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
var element = elements[i];
|
||||
var other;
|
||||
|
||||
if (element.kind === "method" && (other = newElements.find(isSameElement))) {
|
||||
if (_isDataDescriptor(element.descriptor) || _isDataDescriptor(other.descriptor)) {
|
||||
if (_hasDecorators(element) || _hasDecorators(other)) {
|
||||
throw new ReferenceError("Duplicated methods (" + element.key + ") can't be decorated.");
|
||||
}
|
||||
other.descriptor = element.descriptor;
|
||||
} else {
|
||||
if (_hasDecorators(element)) {
|
||||
if (_hasDecorators(other)) {
|
||||
throw new ReferenceError("Decorators can't be placed on different accessors with for " + "the same property (" + element.key + ").");
|
||||
}
|
||||
other.decorators = element.decorators;
|
||||
}
|
||||
_coalesceGetterSetter(element, other);
|
||||
}
|
||||
} else {
|
||||
newElements.push(element);
|
||||
}
|
||||
}
|
||||
|
||||
return newElements;
|
||||
}
|
||||
function _hasDecorators(element) {
|
||||
return element.decorators && element.decorators.length;
|
||||
}
|
||||
function _isDataDescriptor(desc) {
|
||||
return desc !== undefined && !(desc.value === undefined && desc.writable === undefined);
|
||||
}
|
||||
function _initializeClassElements(F, elements) {
|
||||
var proto = F.prototype;
|
||||
["method", "field"].forEach(function(kind) {
|
||||
elements.forEach(function(element) {
|
||||
var placement = element.placement;
|
||||
if (element.kind === kind && (placement === "static" || placement === "prototype")) {
|
||||
var receiver = placement === "static" ? F : proto;
|
||||
_defineClassElement(receiver, element);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
function _initializeInstanceElements(O, elements) {
|
||||
["method", "field"].forEach(function(kind) {
|
||||
elements.forEach(function(element) {
|
||||
if (element.kind === kind && element.placement === "own") _defineClassElement(O, element);
|
||||
});
|
||||
});
|
||||
}
|
||||
function _defineClassElement(receiver, element) {
|
||||
var descriptor = element.descriptor;
|
||||
if (element.kind === "field") {
|
||||
var initializer = element.initializer;
|
||||
descriptor = { enumerable: descriptor.enumerable, writable: descriptor.writable, configurable: descriptor.configurable, value: initializer === void 0 ? void 0 : initializer.call(receiver) };
|
||||
}
|
||||
Object.defineProperty(receiver, element.key, descriptor);
|
||||
}
|
||||
function _decorateClass(elements, decorators) {
|
||||
var newElements = [];
|
||||
var finishers = [];
|
||||
var placements = { static: [], prototype: [], own: [] };
|
||||
elements.forEach(function(element) {
|
||||
_addElementPlacement(element, placements);
|
||||
});
|
||||
elements.forEach(function(element) {
|
||||
if (!_hasDecorators(element)) return newElements.push(element);
|
||||
var elementFinishersExtras = _decorateElement(element, placements);
|
||||
newElements.push(elementFinishersExtras.element);
|
||||
newElements.push.apply(newElements, elementFinishersExtras.extras);
|
||||
finishers.push.apply(finishers, elementFinishersExtras.finishers);
|
||||
});
|
||||
if (!decorators) return { elements: newElements, finishers: finishers };
|
||||
var result = _decorateConstructor(newElements, decorators);
|
||||
finishers.push.apply(finishers, result.finishers);
|
||||
result.finishers = finishers;
|
||||
|
||||
return result;
|
||||
}
|
||||
function _addElementPlacement(element, placements, silent) {
|
||||
var keys = placements[element.placement];
|
||||
if (!silent && keys.indexOf(element.key) !== -1) throw new TypeError("Duplicated element (" + element.key + ")");
|
||||
keys.push(element.key);
|
||||
}
|
||||
function _decorateElement(element, placements) {
|
||||
var extras = [];
|
||||
var finishers = [];
|
||||
for (var decorators = element.decorators, i = decorators.length - 1; i >= 0; i--) {
|
||||
var keys = placements[element.placement];
|
||||
keys.splice(keys.indexOf(element.key), 1);
|
||||
var elementObject = _fromElementDescriptor(element);
|
||||
var elementFinisherExtras = _toElementFinisherExtras((0, decorators[i])(elementObject) || elementObject);
|
||||
element = elementFinisherExtras.element;
|
||||
_addElementPlacement(element, placements);
|
||||
if (elementFinisherExtras.finisher) finishers.push(elementFinisherExtras.finisher);
|
||||
var newExtras = elementFinisherExtras.extras;
|
||||
if (newExtras) {
|
||||
for (var j = 0; j < newExtras.length; j++) _addElementPlacement(newExtras[j], placements);
|
||||
extras.push.apply(extras, newExtras);
|
||||
}
|
||||
}
|
||||
|
||||
return { element: element, finishers: finishers, extras: extras };
|
||||
}
|
||||
function _decorateConstructor(elements, decorators) {
|
||||
var finishers = [];
|
||||
for (var i = decorators.length - 1; i >= 0; i--) {
|
||||
var obj = _fromClassDescriptor(elements);
|
||||
var elementsAndFinisher = _toClassDescriptor((0, decorators[i])(obj) || obj);
|
||||
if (elementsAndFinisher.finisher !== undefined) finishers.push(elementsAndFinisher.finisher);
|
||||
if (elementsAndFinisher.elements !== undefined) {
|
||||
elements = elementsAndFinisher.elements;
|
||||
for (var j = 0; j < elements.length - 1; j++) {
|
||||
for (var k = j + 1; k < elements.length; k++) {
|
||||
if (elements[j].key === elements[k].key && elements[j].placement === elements[k].placement) {
|
||||
throw new TypeError("Duplicated element (" + elements[j].key + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { elements: elements, finishers: finishers };
|
||||
}
|
||||
function _fromElementDescriptor(element) {
|
||||
var obj = { kind: element.kind, key: element.key, placement: element.placement, descriptor: element.descriptor };
|
||||
var desc = { value: "Descriptor", configurable: true };
|
||||
Object.defineProperty(obj, Symbol.toStringTag, desc);
|
||||
if (element.kind === "field") obj.initializer = element.initializer;
|
||||
|
||||
return obj;
|
||||
}
|
||||
function _toElementDescriptors(elementObjects) {
|
||||
if (elementObjects === undefined) return;
|
||||
|
||||
return _to_array(elementObjects).map(function(elementObject) {
|
||||
var element = _toElementDescriptor(elementObject);
|
||||
_disallowProperty(elementObject, "finisher", "An element descriptor");
|
||||
_disallowProperty(elementObject, "extras", "An element descriptor");
|
||||
|
||||
return element;
|
||||
});
|
||||
}
|
||||
function _toElementDescriptor(elementObject) {
|
||||
var kind = String(elementObject.kind);
|
||||
if (kind !== "method" && kind !== "field") {
|
||||
throw new TypeError("An element descriptor's .kind property must be either \"method\" or" + " \"field\", but a decorator created an element descriptor with" + " .kind \"" + kind + "\"");
|
||||
}
|
||||
var key = _to_property_key(elementObject.key);
|
||||
var placement = String(elementObject.placement);
|
||||
if (placement !== "static" && placement !== "prototype" && placement !== "own") {
|
||||
throw new TypeError(
|
||||
"An element descriptor's .placement property must be one of \"static\","
|
||||
+ " \"prototype\" or \"own\", but a decorator created an element descriptor"
|
||||
+ " with .placement \""
|
||||
+ placement
|
||||
+ "\""
|
||||
);
|
||||
}
|
||||
var descriptor = elementObject.descriptor;
|
||||
_disallowProperty(elementObject, "elements", "An element descriptor");
|
||||
var element = { kind: kind, key: key, placement: placement, descriptor: Object.assign({}, descriptor) };
|
||||
if (kind !== "field") _disallowProperty(elementObject, "initializer", "A method descriptor");
|
||||
else {
|
||||
_disallowProperty(descriptor, "get", "The property descriptor of a field descriptor");
|
||||
_disallowProperty(descriptor, "set", "The property descriptor of a field descriptor");
|
||||
_disallowProperty(descriptor, "value", "The property descriptor of a field descriptor");
|
||||
element.initializer = elementObject.initializer;
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
function _toElementFinisherExtras(elementObject) {
|
||||
var element = _toElementDescriptor(elementObject);
|
||||
var finisher = _optionalCallableProperty(elementObject, "finisher");
|
||||
var extras = _toElementDescriptors(elementObject.extras);
|
||||
|
||||
return { element: element, finisher: finisher, extras: extras };
|
||||
}
|
||||
function _fromClassDescriptor(elements) {
|
||||
var obj = { kind: "class", elements: elements.map(_fromElementDescriptor) };
|
||||
var desc = { value: "Descriptor", configurable: true };
|
||||
Object.defineProperty(obj, Symbol.toStringTag, desc);
|
||||
|
||||
return obj;
|
||||
}
|
||||
function _toClassDescriptor(obj) {
|
||||
var kind = String(obj.kind);
|
||||
if (kind !== "class") {
|
||||
throw new TypeError("A class descriptor's .kind property must be \"class\", but a decorator" + " created a class descriptor with .kind \"" + kind + "\"");
|
||||
}
|
||||
_disallowProperty(obj, "key", "A class descriptor");
|
||||
_disallowProperty(obj, "placement", "A class descriptor");
|
||||
_disallowProperty(obj, "descriptor", "A class descriptor");
|
||||
_disallowProperty(obj, "initializer", "A class descriptor");
|
||||
_disallowProperty(obj, "extras", "A class descriptor");
|
||||
var finisher = _optionalCallableProperty(obj, "finisher");
|
||||
var elements = _toElementDescriptors(obj.elements);
|
||||
|
||||
return { elements: elements, finisher: finisher };
|
||||
}
|
||||
function _disallowProperty(obj, name, objectType) {
|
||||
if (obj[name] !== undefined) throw new TypeError(objectType + " can't have a ." + name + " property.");
|
||||
}
|
||||
function _optionalCallableProperty(obj, name) {
|
||||
var value = obj[name];
|
||||
if (value !== undefined && typeof value !== "function") {
|
||||
throw new TypeError("Expected '" + name + "' to be a function");
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
function _runClassFinishers(constructor, finishers) {
|
||||
for (var i = 0; i < finishers.length; i++) {
|
||||
var newConstructor = (0, finishers[i])(constructor);
|
||||
if (newConstructor !== undefined) {
|
||||
if (typeof newConstructor !== "function") throw new TypeError("Finishers must return a constructor.");
|
||||
constructor = newConstructor;
|
||||
}
|
||||
}
|
||||
|
||||
return constructor;
|
||||
}
|
||||
export { _decorate as _ };
|
||||
@@ -0,0 +1,554 @@
|
||||
/**
|
||||
* ed25519 Twisted Edwards curve with following addons:
|
||||
* - X25519 ECDH
|
||||
* - Ristretto cofactor elimination
|
||||
* - Elligator hash-to-group / point indistinguishability
|
||||
* @module
|
||||
*/
|
||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
import { sha512 } from '@noble/hashes/sha2.js';
|
||||
import { abytes, concatBytes, utf8ToBytes } from '@noble/hashes/utils.js';
|
||||
import { pippenger, type AffinePoint } from './abstract/curve.ts';
|
||||
import {
|
||||
PrimeEdwardsPoint,
|
||||
twistedEdwards,
|
||||
type CurveFn,
|
||||
type EdwardsOpts,
|
||||
type EdwardsPoint,
|
||||
} from './abstract/edwards.ts';
|
||||
import {
|
||||
_DST_scalar,
|
||||
createHasher,
|
||||
expand_message_xmd,
|
||||
type H2CHasher,
|
||||
type H2CHasherBase,
|
||||
type H2CMethod,
|
||||
type htfBasicOpts,
|
||||
} from './abstract/hash-to-curve.ts';
|
||||
import {
|
||||
Field,
|
||||
FpInvertBatch,
|
||||
FpSqrtEven,
|
||||
isNegativeLE,
|
||||
mod,
|
||||
pow2,
|
||||
type IField,
|
||||
} from './abstract/modular.ts';
|
||||
import { montgomery, type MontgomeryECDH as XCurveFn } from './abstract/montgomery.ts';
|
||||
import { bytesToNumberLE, ensureBytes, equalBytes, type Hex } from './utils.ts';
|
||||
|
||||
// prettier-ignore
|
||||
const _0n = /* @__PURE__ */ BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
|
||||
// prettier-ignore
|
||||
const _5n = BigInt(5), _8n = BigInt(8);
|
||||
|
||||
// P = 2n**255n-19n
|
||||
const ed25519_CURVE_p = BigInt(
|
||||
'0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed'
|
||||
);
|
||||
|
||||
// N = 2n**252n + 27742317777372353535851937790883648493n
|
||||
// a = Fp.create(BigInt(-1))
|
||||
// d = -121665/121666 a.k.a. Fp.neg(121665 * Fp.inv(121666))
|
||||
const ed25519_CURVE: EdwardsOpts = /* @__PURE__ */ (() => ({
|
||||
p: ed25519_CURVE_p,
|
||||
n: BigInt('0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed'),
|
||||
h: _8n,
|
||||
a: BigInt('0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec'),
|
||||
d: BigInt('0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3'),
|
||||
Gx: BigInt('0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a'),
|
||||
Gy: BigInt('0x6666666666666666666666666666666666666666666666666666666666666658'),
|
||||
}))();
|
||||
|
||||
function ed25519_pow_2_252_3(x: bigint) {
|
||||
// prettier-ignore
|
||||
const _10n = BigInt(10), _20n = BigInt(20), _40n = BigInt(40), _80n = BigInt(80);
|
||||
const P = ed25519_CURVE_p;
|
||||
const x2 = (x * x) % P;
|
||||
const b2 = (x2 * x) % P; // x^3, 11
|
||||
const b4 = (pow2(b2, _2n, P) * b2) % P; // x^15, 1111
|
||||
const b5 = (pow2(b4, _1n, P) * x) % P; // x^31
|
||||
const b10 = (pow2(b5, _5n, P) * b5) % P;
|
||||
const b20 = (pow2(b10, _10n, P) * b10) % P;
|
||||
const b40 = (pow2(b20, _20n, P) * b20) % P;
|
||||
const b80 = (pow2(b40, _40n, P) * b40) % P;
|
||||
const b160 = (pow2(b80, _80n, P) * b80) % P;
|
||||
const b240 = (pow2(b160, _80n, P) * b80) % P;
|
||||
const b250 = (pow2(b240, _10n, P) * b10) % P;
|
||||
const pow_p_5_8 = (pow2(b250, _2n, P) * x) % P;
|
||||
// ^ To pow to (p+3)/8, multiply it by x.
|
||||
return { pow_p_5_8, b2 };
|
||||
}
|
||||
|
||||
function adjustScalarBytes(bytes: Uint8Array): Uint8Array {
|
||||
// Section 5: For X25519, in order to decode 32 random bytes as an integer scalar,
|
||||
// set the three least significant bits of the first byte
|
||||
bytes[0] &= 248; // 0b1111_1000
|
||||
// and the most significant bit of the last to zero,
|
||||
bytes[31] &= 127; // 0b0111_1111
|
||||
// set the second most significant bit of the last byte to 1
|
||||
bytes[31] |= 64; // 0b0100_0000
|
||||
return bytes;
|
||||
}
|
||||
|
||||
// √(-1) aka √(a) aka 2^((p-1)/4)
|
||||
// Fp.sqrt(Fp.neg(1))
|
||||
const ED25519_SQRT_M1 = /* @__PURE__ */ BigInt(
|
||||
'19681161376707505956807079304988542015446066515923890162744021073123829784752'
|
||||
);
|
||||
// sqrt(u/v)
|
||||
function uvRatio(u: bigint, v: bigint): { isValid: boolean; value: bigint } {
|
||||
const P = ed25519_CURVE_p;
|
||||
const v3 = mod(v * v * v, P); // v³
|
||||
const v7 = mod(v3 * v3 * v, P); // v⁷
|
||||
// (p+3)/8 and (p-5)/8
|
||||
const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8;
|
||||
let x = mod(u * v3 * pow, P); // (uv³)(uv⁷)^(p-5)/8
|
||||
const vx2 = mod(v * x * x, P); // vx²
|
||||
const root1 = x; // First root candidate
|
||||
const root2 = mod(x * ED25519_SQRT_M1, P); // Second root candidate
|
||||
const useRoot1 = vx2 === u; // If vx² = u (mod p), x is a square root
|
||||
const useRoot2 = vx2 === mod(-u, P); // If vx² = -u, set x <-- x * 2^((p-1)/4)
|
||||
const noRoot = vx2 === mod(-u * ED25519_SQRT_M1, P); // There is no valid root, vx² = -u√(-1)
|
||||
if (useRoot1) x = root1;
|
||||
if (useRoot2 || noRoot) x = root2; // We return root2 anyway, for const-time
|
||||
if (isNegativeLE(x, P)) x = mod(-x, P);
|
||||
return { isValid: useRoot1 || useRoot2, value: x };
|
||||
}
|
||||
|
||||
const Fp = /* @__PURE__ */ (() => Field(ed25519_CURVE.p, { isLE: true }))();
|
||||
const Fn = /* @__PURE__ */ (() => Field(ed25519_CURVE.n, { isLE: true }))();
|
||||
|
||||
const ed25519Defaults = /* @__PURE__ */ (() => ({
|
||||
...ed25519_CURVE,
|
||||
Fp,
|
||||
hash: sha512,
|
||||
adjustScalarBytes,
|
||||
// dom2
|
||||
// Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3.
|
||||
// Constant-time, u/√v
|
||||
uvRatio,
|
||||
}))();
|
||||
|
||||
/**
|
||||
* ed25519 curve with EdDSA signatures.
|
||||
* @example
|
||||
* import { ed25519 } from '@noble/curves/ed25519';
|
||||
* const { secretKey, publicKey } = ed25519.keygen();
|
||||
* const msg = new TextEncoder().encode('hello');
|
||||
* const sig = ed25519.sign(msg, priv);
|
||||
* ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215
|
||||
* ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5
|
||||
*/
|
||||
export const ed25519: CurveFn = /* @__PURE__ */ (() => twistedEdwards(ed25519Defaults))();
|
||||
|
||||
function ed25519_domain(data: Uint8Array, ctx: Uint8Array, phflag: boolean) {
|
||||
if (ctx.length > 255) throw new Error('Context is too big');
|
||||
return concatBytes(
|
||||
utf8ToBytes('SigEd25519 no Ed25519 collisions'),
|
||||
new Uint8Array([phflag ? 1 : 0, ctx.length]),
|
||||
ctx,
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
/** Context of ed25519. Uses context for domain separation. */
|
||||
export const ed25519ctx: CurveFn = /* @__PURE__ */ (() =>
|
||||
twistedEdwards({
|
||||
...ed25519Defaults,
|
||||
domain: ed25519_domain,
|
||||
}))();
|
||||
|
||||
/** Prehashed version of ed25519. Accepts already-hashed messages in sign() and verify(). */
|
||||
export const ed25519ph: CurveFn = /* @__PURE__ */ (() =>
|
||||
twistedEdwards(
|
||||
Object.assign({}, ed25519Defaults, {
|
||||
domain: ed25519_domain,
|
||||
prehash: sha512,
|
||||
})
|
||||
))();
|
||||
|
||||
/**
|
||||
* ECDH using curve25519 aka x25519.
|
||||
* @example
|
||||
* import { x25519 } from '@noble/curves/ed25519';
|
||||
* const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4';
|
||||
* const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c';
|
||||
* x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases
|
||||
* x25519.getPublicKey(priv) === x25519.scalarMultBase(priv);
|
||||
* x25519.getPublicKey(x25519.utils.randomSecretKey());
|
||||
*/
|
||||
export const x25519: XCurveFn = /* @__PURE__ */ (() => {
|
||||
const P = Fp.ORDER;
|
||||
return montgomery({
|
||||
P,
|
||||
type: 'x25519',
|
||||
powPminus2: (x: bigint): bigint => {
|
||||
// x^(p-2) aka x^(2^255-21)
|
||||
const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x);
|
||||
return mod(pow2(pow_p_5_8, _3n, P) * b2, P);
|
||||
},
|
||||
adjustScalarBytes,
|
||||
});
|
||||
})();
|
||||
|
||||
// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator)
|
||||
// NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since
|
||||
// SageMath returns different root first and everything falls apart
|
||||
const ELL2_C1 = /* @__PURE__ */ (() => (ed25519_CURVE_p + _3n) / _8n)(); // 1. c1 = (q + 3) / 8 # Integer arithmetic
|
||||
const ELL2_C2 = /* @__PURE__ */ (() => Fp.pow(_2n, ELL2_C1))(); // 2. c2 = 2^c1
|
||||
const ELL2_C3 = /* @__PURE__ */ (() => Fp.sqrt(Fp.neg(Fp.ONE)))(); // 3. c3 = sqrt(-1)
|
||||
|
||||
// prettier-ignore
|
||||
function map_to_curve_elligator2_curve25519(u: bigint) {
|
||||
const ELL2_C4 = (ed25519_CURVE_p - _5n) / _8n; // 4. c4 = (q - 5) / 8 # Integer arithmetic
|
||||
const ELL2_J = BigInt(486662);
|
||||
|
||||
let tv1 = Fp.sqr(u); // 1. tv1 = u^2
|
||||
tv1 = Fp.mul(tv1, _2n); // 2. tv1 = 2 * tv1
|
||||
let xd = Fp.add(tv1, Fp.ONE); // 3. xd = tv1 + 1 # Nonzero: -1 is square (mod p), tv1 is not
|
||||
let x1n = Fp.neg(ELL2_J); // 4. x1n = -J # x1 = x1n / xd = -J / (1 + 2 * u^2)
|
||||
let tv2 = Fp.sqr(xd); // 5. tv2 = xd^2
|
||||
let gxd = Fp.mul(tv2, xd); // 6. gxd = tv2 * xd # gxd = xd^3
|
||||
let gx1 = Fp.mul(tv1, ELL2_J);// 7. gx1 = J * tv1 # x1n + J * xd
|
||||
gx1 = Fp.mul(gx1, x1n); // 8. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd
|
||||
gx1 = Fp.add(gx1, tv2); // 9. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2
|
||||
gx1 = Fp.mul(gx1, x1n); // 10. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2
|
||||
let tv3 = Fp.sqr(gxd); // 11. tv3 = gxd^2
|
||||
tv2 = Fp.sqr(tv3); // 12. tv2 = tv3^2 # gxd^4
|
||||
tv3 = Fp.mul(tv3, gxd); // 13. tv3 = tv3 * gxd # gxd^3
|
||||
tv3 = Fp.mul(tv3, gx1); // 14. tv3 = tv3 * gx1 # gx1 * gxd^3
|
||||
tv2 = Fp.mul(tv2, tv3); // 15. tv2 = tv2 * tv3 # gx1 * gxd^7
|
||||
let y11 = Fp.pow(tv2, ELL2_C4); // 16. y11 = tv2^c4 # (gx1 * gxd^7)^((p - 5) / 8)
|
||||
y11 = Fp.mul(y11, tv3); // 17. y11 = y11 * tv3 # gx1*gxd^3*(gx1*gxd^7)^((p-5)/8)
|
||||
let y12 = Fp.mul(y11, ELL2_C3); // 18. y12 = y11 * c3
|
||||
tv2 = Fp.sqr(y11); // 19. tv2 = y11^2
|
||||
tv2 = Fp.mul(tv2, gxd); // 20. tv2 = tv2 * gxd
|
||||
let e1 = Fp.eql(tv2, gx1); // 21. e1 = tv2 == gx1
|
||||
let y1 = Fp.cmov(y12, y11, e1); // 22. y1 = CMOV(y12, y11, e1) # If g(x1) is square, this is its sqrt
|
||||
let x2n = Fp.mul(x1n, tv1); // 23. x2n = x1n * tv1 # x2 = x2n / xd = 2 * u^2 * x1n / xd
|
||||
let y21 = Fp.mul(y11, u); // 24. y21 = y11 * u
|
||||
y21 = Fp.mul(y21, ELL2_C2); // 25. y21 = y21 * c2
|
||||
let y22 = Fp.mul(y21, ELL2_C3); // 26. y22 = y21 * c3
|
||||
let gx2 = Fp.mul(gx1, tv1); // 27. gx2 = gx1 * tv1 # g(x2) = gx2 / gxd = 2 * u^2 * g(x1)
|
||||
tv2 = Fp.sqr(y21); // 28. tv2 = y21^2
|
||||
tv2 = Fp.mul(tv2, gxd); // 29. tv2 = tv2 * gxd
|
||||
let e2 = Fp.eql(tv2, gx2); // 30. e2 = tv2 == gx2
|
||||
let y2 = Fp.cmov(y22, y21, e2); // 31. y2 = CMOV(y22, y21, e2) # If g(x2) is square, this is its sqrt
|
||||
tv2 = Fp.sqr(y1); // 32. tv2 = y1^2
|
||||
tv2 = Fp.mul(tv2, gxd); // 33. tv2 = tv2 * gxd
|
||||
let e3 = Fp.eql(tv2, gx1); // 34. e3 = tv2 == gx1
|
||||
let xn = Fp.cmov(x2n, x1n, e3); // 35. xn = CMOV(x2n, x1n, e3) # If e3, x = x1, else x = x2
|
||||
let y = Fp.cmov(y2, y1, e3); // 36. y = CMOV(y2, y1, e3) # If e3, y = y1, else y = y2
|
||||
let e4 = Fp.isOdd!(y); // 37. e4 = sgn0(y) == 1 # Fix sign of y
|
||||
y = Fp.cmov(y, Fp.neg(y), e3 !== e4); // 38. y = CMOV(y, -y, e3 XOR e4)
|
||||
return { xMn: xn, xMd: xd, yMn: y, yMd: _1n }; // 39. return (xn, xd, y, 1)
|
||||
}
|
||||
|
||||
const ELL2_C1_EDWARDS = /* @__PURE__ */ (() => FpSqrtEven(Fp, Fp.neg(BigInt(486664))))(); // sgn0(c1) MUST equal 0
|
||||
function map_to_curve_elligator2_edwards25519(u: bigint) {
|
||||
const { xMn, xMd, yMn, yMd } = map_to_curve_elligator2_curve25519(u); // 1. (xMn, xMd, yMn, yMd) =
|
||||
// map_to_curve_elligator2_curve25519(u)
|
||||
let xn = Fp.mul(xMn, yMd); // 2. xn = xMn * yMd
|
||||
xn = Fp.mul(xn, ELL2_C1_EDWARDS); // 3. xn = xn * c1
|
||||
let xd = Fp.mul(xMd, yMn); // 4. xd = xMd * yMn # xn / xd = c1 * xM / yM
|
||||
let yn = Fp.sub(xMn, xMd); // 5. yn = xMn - xMd
|
||||
let yd = Fp.add(xMn, xMd); // 6. yd = xMn + xMd # (n / d - 1) / (n / d + 1) = (n - d) / (n + d)
|
||||
let tv1 = Fp.mul(xd, yd); // 7. tv1 = xd * yd
|
||||
let e = Fp.eql(tv1, Fp.ZERO); // 8. e = tv1 == 0
|
||||
xn = Fp.cmov(xn, Fp.ZERO, e); // 9. xn = CMOV(xn, 0, e)
|
||||
xd = Fp.cmov(xd, Fp.ONE, e); // 10. xd = CMOV(xd, 1, e)
|
||||
yn = Fp.cmov(yn, Fp.ONE, e); // 11. yn = CMOV(yn, 1, e)
|
||||
yd = Fp.cmov(yd, Fp.ONE, e); // 12. yd = CMOV(yd, 1, e)
|
||||
const [xd_inv, yd_inv] = FpInvertBatch(Fp, [xd, yd], true); // batch division
|
||||
return { x: Fp.mul(xn, xd_inv), y: Fp.mul(yn, yd_inv) }; // 13. return (xn, xd, yn, yd)
|
||||
}
|
||||
|
||||
/** Hashing to ed25519 points / field. RFC 9380 methods. */
|
||||
export const ed25519_hasher: H2CHasher<bigint> = /* @__PURE__ */ (() =>
|
||||
createHasher(
|
||||
ed25519.Point,
|
||||
(scalars: bigint[]) => map_to_curve_elligator2_edwards25519(scalars[0]),
|
||||
{
|
||||
DST: 'edwards25519_XMD:SHA-512_ELL2_RO_',
|
||||
encodeDST: 'edwards25519_XMD:SHA-512_ELL2_NU_',
|
||||
p: ed25519_CURVE_p,
|
||||
m: 1,
|
||||
k: 128,
|
||||
expand: 'xmd',
|
||||
hash: sha512,
|
||||
}
|
||||
))();
|
||||
|
||||
// √(-1) aka √(a) aka 2^((p-1)/4)
|
||||
const SQRT_M1 = ED25519_SQRT_M1;
|
||||
// √(ad - 1)
|
||||
const SQRT_AD_MINUS_ONE = /* @__PURE__ */ BigInt(
|
||||
'25063068953384623474111414158702152701244531502492656460079210482610430750235'
|
||||
);
|
||||
// 1 / √(a-d)
|
||||
const INVSQRT_A_MINUS_D = /* @__PURE__ */ BigInt(
|
||||
'54469307008909316920995813868745141605393597292927456921205312896311721017578'
|
||||
);
|
||||
// 1-d²
|
||||
const ONE_MINUS_D_SQ = /* @__PURE__ */ BigInt(
|
||||
'1159843021668779879193775521855586647937357759715417654439879720876111806838'
|
||||
);
|
||||
// (d-1)²
|
||||
const D_MINUS_ONE_SQ = /* @__PURE__ */ BigInt(
|
||||
'40440834346308536858101042469323190826248399146238708352240133220865137265952'
|
||||
);
|
||||
// Calculates 1/√(number)
|
||||
const invertSqrt = (number: bigint) => uvRatio(_1n, number);
|
||||
|
||||
const MAX_255B = /* @__PURE__ */ BigInt(
|
||||
'0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
);
|
||||
const bytes255ToNumberLE = (bytes: Uint8Array) =>
|
||||
ed25519.Point.Fp.create(bytesToNumberLE(bytes) & MAX_255B);
|
||||
|
||||
type ExtendedPoint = EdwardsPoint;
|
||||
|
||||
/**
|
||||
* Computes Elligator map for Ristretto255.
|
||||
* Described in [RFC9380](https://www.rfc-editor.org/rfc/rfc9380#appendix-B) and on
|
||||
* the [website](https://ristretto.group/formulas/elligator.html).
|
||||
*/
|
||||
function calcElligatorRistrettoMap(r0: bigint): ExtendedPoint {
|
||||
const { d } = ed25519_CURVE;
|
||||
const P = ed25519_CURVE_p;
|
||||
const mod = (n: bigint) => Fp.create(n);
|
||||
const r = mod(SQRT_M1 * r0 * r0); // 1
|
||||
const Ns = mod((r + _1n) * ONE_MINUS_D_SQ); // 2
|
||||
let c = BigInt(-1); // 3
|
||||
const D = mod((c - d * r) * mod(r + d)); // 4
|
||||
let { isValid: Ns_D_is_sq, value: s } = uvRatio(Ns, D); // 5
|
||||
let s_ = mod(s * r0); // 6
|
||||
if (!isNegativeLE(s_, P)) s_ = mod(-s_);
|
||||
if (!Ns_D_is_sq) s = s_; // 7
|
||||
if (!Ns_D_is_sq) c = r; // 8
|
||||
const Nt = mod(c * (r - _1n) * D_MINUS_ONE_SQ - D); // 9
|
||||
const s2 = s * s;
|
||||
const W0 = mod((s + s) * D); // 10
|
||||
const W1 = mod(Nt * SQRT_AD_MINUS_ONE); // 11
|
||||
const W2 = mod(_1n - s2); // 12
|
||||
const W3 = mod(_1n + s2); // 13
|
||||
return new ed25519.Point(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2));
|
||||
}
|
||||
|
||||
function ristretto255_map(bytes: Uint8Array): _RistrettoPoint {
|
||||
abytes(bytes, 64);
|
||||
const r1 = bytes255ToNumberLE(bytes.subarray(0, 32));
|
||||
const R1 = calcElligatorRistrettoMap(r1);
|
||||
const r2 = bytes255ToNumberLE(bytes.subarray(32, 64));
|
||||
const R2 = calcElligatorRistrettoMap(r2);
|
||||
return new _RistrettoPoint(R1.add(R2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper over Edwards Point for ristretto255.
|
||||
*
|
||||
* Each ed25519/ExtendedPoint has 8 different equivalent points. This can be
|
||||
* a source of bugs for protocols like ring signatures. Ristretto was created to solve this.
|
||||
* Ristretto point operates in X:Y:Z:T extended coordinates like ExtendedPoint,
|
||||
* but it should work in its own namespace: do not combine those two.
|
||||
* See [RFC9496](https://www.rfc-editor.org/rfc/rfc9496).
|
||||
*/
|
||||
class _RistrettoPoint extends PrimeEdwardsPoint<_RistrettoPoint> {
|
||||
// Do NOT change syntax: the following gymnastics is done,
|
||||
// because typescript strips comments, which makes bundlers disable tree-shaking.
|
||||
// prettier-ignore
|
||||
static BASE: _RistrettoPoint =
|
||||
/* @__PURE__ */ (() => new _RistrettoPoint(ed25519.Point.BASE))();
|
||||
// prettier-ignore
|
||||
static ZERO: _RistrettoPoint =
|
||||
/* @__PURE__ */ (() => new _RistrettoPoint(ed25519.Point.ZERO))();
|
||||
// prettier-ignore
|
||||
static Fp: IField<bigint> =
|
||||
/* @__PURE__ */ (() => Fp)();
|
||||
// prettier-ignore
|
||||
static Fn: IField<bigint> =
|
||||
/* @__PURE__ */ (() => Fn)();
|
||||
|
||||
constructor(ep: ExtendedPoint) {
|
||||
super(ep);
|
||||
}
|
||||
|
||||
static fromAffine(ap: AffinePoint<bigint>): _RistrettoPoint {
|
||||
return new _RistrettoPoint(ed25519.Point.fromAffine(ap));
|
||||
}
|
||||
|
||||
protected assertSame(other: _RistrettoPoint): void {
|
||||
if (!(other instanceof _RistrettoPoint)) throw new Error('RistrettoPoint expected');
|
||||
}
|
||||
|
||||
protected init(ep: EdwardsPoint): _RistrettoPoint {
|
||||
return new _RistrettoPoint(ep);
|
||||
}
|
||||
|
||||
/** @deprecated use `import { ristretto255_hasher } from '@noble/curves/ed25519.js';` */
|
||||
static hashToCurve(hex: Hex): _RistrettoPoint {
|
||||
return ristretto255_map(ensureBytes('ristrettoHash', hex, 64));
|
||||
}
|
||||
|
||||
static fromBytes(bytes: Uint8Array): _RistrettoPoint {
|
||||
abytes(bytes, 32);
|
||||
const { a, d } = ed25519_CURVE;
|
||||
const P = ed25519_CURVE_p;
|
||||
const mod = (n: bigint) => Fp.create(n);
|
||||
const s = bytes255ToNumberLE(bytes);
|
||||
// 1. Check that s_bytes is the canonical encoding of a field element, or else abort.
|
||||
// 3. Check that s is non-negative, or else abort
|
||||
if (!equalBytes(Fp.toBytes(s), bytes) || isNegativeLE(s, P))
|
||||
throw new Error('invalid ristretto255 encoding 1');
|
||||
const s2 = mod(s * s);
|
||||
const u1 = mod(_1n + a * s2); // 4 (a is -1)
|
||||
const u2 = mod(_1n - a * s2); // 5
|
||||
const u1_2 = mod(u1 * u1);
|
||||
const u2_2 = mod(u2 * u2);
|
||||
const v = mod(a * d * u1_2 - u2_2); // 6
|
||||
const { isValid, value: I } = invertSqrt(mod(v * u2_2)); // 7
|
||||
const Dx = mod(I * u2); // 8
|
||||
const Dy = mod(I * Dx * v); // 9
|
||||
let x = mod((s + s) * Dx); // 10
|
||||
if (isNegativeLE(x, P)) x = mod(-x); // 10
|
||||
const y = mod(u1 * Dy); // 11
|
||||
const t = mod(x * y); // 12
|
||||
if (!isValid || isNegativeLE(t, P) || y === _0n)
|
||||
throw new Error('invalid ristretto255 encoding 2');
|
||||
return new _RistrettoPoint(new ed25519.Point(x, y, _1n, t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts ristretto-encoded string to ristretto point.
|
||||
* Described in [RFC9496](https://www.rfc-editor.org/rfc/rfc9496#name-decode).
|
||||
* @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding
|
||||
*/
|
||||
static fromHex(hex: Hex): _RistrettoPoint {
|
||||
return _RistrettoPoint.fromBytes(ensureBytes('ristrettoHex', hex, 32));
|
||||
}
|
||||
|
||||
static msm(points: _RistrettoPoint[], scalars: bigint[]): _RistrettoPoint {
|
||||
return pippenger(_RistrettoPoint, ed25519.Point.Fn, points, scalars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes ristretto point to Uint8Array.
|
||||
* Described in [RFC9496](https://www.rfc-editor.org/rfc/rfc9496#name-encode).
|
||||
*/
|
||||
toBytes(): Uint8Array {
|
||||
let { X, Y, Z, T } = this.ep;
|
||||
const P = ed25519_CURVE_p;
|
||||
const mod = (n: bigint) => Fp.create(n);
|
||||
const u1 = mod(mod(Z + Y) * mod(Z - Y)); // 1
|
||||
const u2 = mod(X * Y); // 2
|
||||
// Square root always exists
|
||||
const u2sq = mod(u2 * u2);
|
||||
const { value: invsqrt } = invertSqrt(mod(u1 * u2sq)); // 3
|
||||
const D1 = mod(invsqrt * u1); // 4
|
||||
const D2 = mod(invsqrt * u2); // 5
|
||||
const zInv = mod(D1 * D2 * T); // 6
|
||||
let D: bigint; // 7
|
||||
if (isNegativeLE(T * zInv, P)) {
|
||||
let _x = mod(Y * SQRT_M1);
|
||||
let _y = mod(X * SQRT_M1);
|
||||
X = _x;
|
||||
Y = _y;
|
||||
D = mod(D1 * INVSQRT_A_MINUS_D);
|
||||
} else {
|
||||
D = D2; // 8
|
||||
}
|
||||
if (isNegativeLE(X * zInv, P)) Y = mod(-Y); // 9
|
||||
let s = mod((Z - Y) * D); // 10 (check footer's note, no sqrt(-a))
|
||||
if (isNegativeLE(s, P)) s = mod(-s);
|
||||
return Fp.toBytes(s); // 11
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two Ristretto points.
|
||||
* Described in [RFC9496](https://www.rfc-editor.org/rfc/rfc9496#name-equals).
|
||||
*/
|
||||
equals(other: _RistrettoPoint): boolean {
|
||||
this.assertSame(other);
|
||||
const { X: X1, Y: Y1 } = this.ep;
|
||||
const { X: X2, Y: Y2 } = other.ep;
|
||||
const mod = (n: bigint) => Fp.create(n);
|
||||
// (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2)
|
||||
const one = mod(X1 * Y2) === mod(Y1 * X2);
|
||||
const two = mod(Y1 * Y2) === mod(X1 * X2);
|
||||
return one || two;
|
||||
}
|
||||
|
||||
is0(): boolean {
|
||||
return this.equals(_RistrettoPoint.ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
export const ristretto255: {
|
||||
Point: typeof _RistrettoPoint;
|
||||
} = { Point: _RistrettoPoint };
|
||||
|
||||
/** Hashing to ristretto255 points / field. RFC 9380 methods. */
|
||||
export const ristretto255_hasher: H2CHasherBase<bigint> = {
|
||||
hashToCurve(msg: Uint8Array, options?: htfBasicOpts): _RistrettoPoint {
|
||||
const DST = options?.DST || 'ristretto255_XMD:SHA-512_R255MAP_RO_';
|
||||
const xmd = expand_message_xmd(msg, DST, 64, sha512);
|
||||
return ristretto255_map(xmd);
|
||||
},
|
||||
hashToScalar(msg: Uint8Array, options: htfBasicOpts = { DST: _DST_scalar }) {
|
||||
const xmd = expand_message_xmd(msg, options.DST, 64, sha512);
|
||||
return Fn.create(bytesToNumberLE(xmd));
|
||||
},
|
||||
};
|
||||
|
||||
// export const ristretto255_oprf: OPRF = createORPF({
|
||||
// name: 'ristretto255-SHA512',
|
||||
// Point: RistrettoPoint,
|
||||
// hash: sha512,
|
||||
// hashToGroup: ristretto255_hasher.hashToCurve,
|
||||
// hashToScalar: ristretto255_hasher.hashToScalar,
|
||||
// });
|
||||
|
||||
/**
|
||||
* Weird / bogus points, useful for debugging.
|
||||
* All 8 ed25519 points of 8-torsion subgroup can be generated from the point
|
||||
* T = `26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05`.
|
||||
* ⟨T⟩ = { O, T, 2T, 3T, 4T, 5T, 6T, 7T }
|
||||
*/
|
||||
export const ED25519_TORSION_SUBGROUP: string[] = [
|
||||
'0100000000000000000000000000000000000000000000000000000000000000',
|
||||
'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a',
|
||||
'0000000000000000000000000000000000000000000000000000000000000080',
|
||||
'26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05',
|
||||
'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
|
||||
'26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85',
|
||||
'0000000000000000000000000000000000000000000000000000000000000000',
|
||||
'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa',
|
||||
];
|
||||
|
||||
/** @deprecated use `ed25519.utils.toMontgomery` */
|
||||
export function edwardsToMontgomeryPub(edwardsPub: Hex): Uint8Array {
|
||||
return ed25519.utils.toMontgomery(ensureBytes('pub', edwardsPub));
|
||||
}
|
||||
/** @deprecated use `ed25519.utils.toMontgomery` */
|
||||
export const edwardsToMontgomery: typeof edwardsToMontgomeryPub = edwardsToMontgomeryPub;
|
||||
|
||||
/** @deprecated use `ed25519.utils.toMontgomerySecret` */
|
||||
export function edwardsToMontgomeryPriv(edwardsPriv: Uint8Array): Uint8Array {
|
||||
return ed25519.utils.toMontgomerySecret(ensureBytes('pub', edwardsPriv));
|
||||
}
|
||||
|
||||
/** @deprecated use `ristretto255.Point` */
|
||||
export const RistrettoPoint: typeof _RistrettoPoint = _RistrettoPoint;
|
||||
/** @deprecated use `import { ed25519_hasher } from '@noble/curves/ed25519.js';` */
|
||||
export const hashToCurve: H2CMethod<bigint> = /* @__PURE__ */ (() => ed25519_hasher.hashToCurve)();
|
||||
/** @deprecated use `import { ed25519_hasher } from '@noble/curves/ed25519.js';` */
|
||||
export const encodeToCurve: H2CMethod<bigint> = /* @__PURE__ */ (() =>
|
||||
ed25519_hasher.encodeToCurve)();
|
||||
type RistHasher = (msg: Uint8Array, options: htfBasicOpts) => _RistrettoPoint;
|
||||
/** @deprecated use `import { ristretto255_hasher } from '@noble/curves/ed25519.js';` */
|
||||
export const hashToRistretto255: RistHasher = /* @__PURE__ */ (() =>
|
||||
ristretto255_hasher.hashToCurve as RistHasher)();
|
||||
/** @deprecated use `import { ristretto255_hasher } from '@noble/curves/ed25519.js';` */
|
||||
export const hash_to_ristretto255: RistHasher = /* @__PURE__ */ (() =>
|
||||
ristretto255_hasher.hashToCurve as RistHasher)();
|
||||
@@ -0,0 +1,8 @@
|
||||
import type { AST_TOKEN_TYPES, TSESTree } from '../ts-estree';
|
||||
declare namespace AST {
|
||||
type TokenType = AST_TOKEN_TYPES;
|
||||
type Token = TSESTree.Token;
|
||||
type SourceLocation = TSESTree.SourceLocation;
|
||||
type Range = TSESTree.Range;
|
||||
}
|
||||
export type { AST };
|
||||
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* @fileoverview Disallows unnecessary `return await`
|
||||
* @author Jordan Harband
|
||||
* @deprecated in ESLint v8.46.0
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
hasSuggestions: true,
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "Disallow unnecessary `return await`",
|
||||
|
||||
recommended: false,
|
||||
|
||||
url: "https://eslint.org/docs/latest/rules/no-return-await",
|
||||
},
|
||||
|
||||
fixable: null,
|
||||
|
||||
deprecated: {
|
||||
message:
|
||||
"The original assumption of the rule no longer holds true because of engine optimization.",
|
||||
deprecatedSince: "8.46.0",
|
||||
availableUntil: null,
|
||||
replacedBy: [],
|
||||
},
|
||||
|
||||
schema: [],
|
||||
|
||||
messages: {
|
||||
removeAwait: "Remove redundant `await`.",
|
||||
redundantUseOfAwait: "Redundant use of `await` on a return value.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
/**
|
||||
* Reports a found unnecessary `await` expression.
|
||||
* @param {ASTNode} node The node representing the `await` expression to report
|
||||
* @returns {void}
|
||||
*/
|
||||
function reportUnnecessaryAwait(node) {
|
||||
context.report({
|
||||
node: context.sourceCode.getFirstToken(node),
|
||||
loc: node.loc,
|
||||
messageId: "redundantUseOfAwait",
|
||||
suggest: [
|
||||
{
|
||||
messageId: "removeAwait",
|
||||
fix(fixer) {
|
||||
const sourceCode = context.sourceCode;
|
||||
const [awaitToken, tokenAfterAwait] =
|
||||
sourceCode.getFirstTokens(node, 2);
|
||||
|
||||
const areAwaitAndAwaitedExpressionOnTheSameLine =
|
||||
awaitToken.loc.start.line ===
|
||||
tokenAfterAwait.loc.start.line;
|
||||
|
||||
if (!areAwaitAndAwaitedExpressionOnTheSameLine) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const [startOfAwait, endOfAwait] = awaitToken.range;
|
||||
|
||||
const characterAfterAwait =
|
||||
sourceCode.text[endOfAwait];
|
||||
const trimLength =
|
||||
characterAfterAwait === " " ? 1 : 0;
|
||||
|
||||
const range = [
|
||||
startOfAwait,
|
||||
endOfAwait + trimLength,
|
||||
];
|
||||
|
||||
return fixer.removeRange(range);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a thrown error from this node will be caught/handled within this function rather than immediately halting
|
||||
* this function. For example, a statement in a `try` block will always have an error handler. A statement in
|
||||
* a `catch` block will only have an error handler if there is also a `finally` block.
|
||||
* @param {ASTNode} node A node representing a location where an could be thrown
|
||||
* @returns {boolean} `true` if a thrown error will be caught/handled in this function
|
||||
*/
|
||||
function hasErrorHandler(node) {
|
||||
let ancestor = node;
|
||||
|
||||
while (
|
||||
!astUtils.isFunction(ancestor) &&
|
||||
ancestor.type !== "Program"
|
||||
) {
|
||||
if (
|
||||
ancestor.parent.type === "TryStatement" &&
|
||||
(ancestor === ancestor.parent.block ||
|
||||
(ancestor === ancestor.parent.handler &&
|
||||
ancestor.parent.finalizer))
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
ancestor = ancestor.parent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a node is placed in tail call position. Once `return` arguments (or arrow function expressions) can be a complex expression,
|
||||
* an `await` expression could or could not be unnecessary by the definition of this rule. So we're looking for `await` expressions that are in tail position.
|
||||
* @param {ASTNode} node A node representing the `await` expression to check
|
||||
* @returns {boolean} The checking result
|
||||
*/
|
||||
function isInTailCallPosition(node) {
|
||||
if (node.parent.type === "ArrowFunctionExpression") {
|
||||
return true;
|
||||
}
|
||||
if (node.parent.type === "ReturnStatement") {
|
||||
return !hasErrorHandler(node.parent);
|
||||
}
|
||||
if (
|
||||
node.parent.type === "ConditionalExpression" &&
|
||||
(node === node.parent.consequent ||
|
||||
node === node.parent.alternate)
|
||||
) {
|
||||
return isInTailCallPosition(node.parent);
|
||||
}
|
||||
if (
|
||||
node.parent.type === "LogicalExpression" &&
|
||||
node === node.parent.right
|
||||
) {
|
||||
return isInTailCallPosition(node.parent);
|
||||
}
|
||||
if (
|
||||
node.parent.type === "SequenceExpression" &&
|
||||
node === node.parent.expressions.at(-1)
|
||||
) {
|
||||
return isInTailCallPosition(node.parent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return {
|
||||
AwaitExpression(node) {
|
||||
if (isInTailCallPosition(node) && !hasErrorHandler(node)) {
|
||||
reportUnnecessaryAwait(node);
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
import type { LibDefinition } from '../variable';
|
||||
export declare const esnext_symbol: LibDefinition;
|
||||
@@ -0,0 +1 @@
|
||||
export { _ as default } from "../esm/_tagged_template_literal.js";
|
||||
@@ -0,0 +1,118 @@
|
||||
import type { $ZodStringFormats } from "../core/checks.js";
|
||||
import type * as errors from "../core/errors.js";
|
||||
import * as util from "../core/util.js";
|
||||
|
||||
const error: () => errors.$ZodErrorMap = () => {
|
||||
const Sizable: Record<string, { unit: string; verb: string }> = {
|
||||
string: { unit: "знаци", verb: "да имаат" },
|
||||
file: { unit: "бајти", verb: "да имаат" },
|
||||
array: { unit: "ставки", verb: "да имаат" },
|
||||
set: { unit: "ставки", verb: "да имаат" },
|
||||
};
|
||||
|
||||
function getSizing(origin: string): { unit: string; verb: string } | null {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
|
||||
const FormatDictionary: {
|
||||
[k in $ZodStringFormats | (string & {})]?: string;
|
||||
} = {
|
||||
regex: "внес",
|
||||
email: "адреса на е-пошта",
|
||||
url: "URL",
|
||||
emoji: "емоџи",
|
||||
uuid: "UUID",
|
||||
uuidv4: "UUIDv4",
|
||||
uuidv6: "UUIDv6",
|
||||
nanoid: "nanoid",
|
||||
guid: "GUID",
|
||||
cuid: "cuid",
|
||||
cuid2: "cuid2",
|
||||
ulid: "ULID",
|
||||
xid: "XID",
|
||||
ksuid: "KSUID",
|
||||
datetime: "ISO датум и време",
|
||||
date: "ISO датум",
|
||||
time: "ISO време",
|
||||
duration: "ISO времетраење",
|
||||
ipv4: "IPv4 адреса",
|
||||
ipv6: "IPv6 адреса",
|
||||
cidrv4: "IPv4 опсег",
|
||||
cidrv6: "IPv6 опсег",
|
||||
base64: "base64-енкодирана низа",
|
||||
base64url: "base64url-енкодирана низа",
|
||||
json_string: "JSON низа",
|
||||
e164: "E.164 број",
|
||||
jwt: "JWT",
|
||||
template_literal: "внес",
|
||||
};
|
||||
|
||||
const TypeDictionary: {
|
||||
[k in errors.$ZodInvalidTypeExpected | (string & {})]?: string;
|
||||
} = {
|
||||
nan: "NaN",
|
||||
number: "број",
|
||||
array: "низа",
|
||||
};
|
||||
|
||||
return (issue) => {
|
||||
switch (issue.code) {
|
||||
case "invalid_type": {
|
||||
const expected = TypeDictionary[issue.expected] ?? issue.expected;
|
||||
const receivedType = util.parsedType(issue.input);
|
||||
const received = TypeDictionary[receivedType] ?? receivedType;
|
||||
if (/^[A-Z]/.test(issue.expected)) {
|
||||
return `Грешен внес: се очекува instanceof ${issue.expected}, примено ${received}`;
|
||||
}
|
||||
return `Грешен внес: се очекува ${expected}, примено ${received}`;
|
||||
}
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1) return `Invalid input: expected ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `Грешана опција: се очекува една ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return `Премногу голем: се очекува ${issue.origin ?? "вредноста"} да има ${adj}${issue.maximum.toString()} ${sizing.unit ?? "елементи"}`;
|
||||
return `Премногу голем: се очекува ${issue.origin ?? "вредноста"} да биде ${adj}${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
return `Премногу мал: се очекува ${issue.origin} да има ${adj}${issue.minimum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
|
||||
return `Премногу мал: се очекува ${issue.origin} да биде ${adj}${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue as errors.$ZodStringFormatIssues;
|
||||
if (_issue.format === "starts_with") {
|
||||
return `Неважечка низа: мора да започнува со "${_issue.prefix}"`;
|
||||
}
|
||||
if (_issue.format === "ends_with") return `Неважечка низа: мора да завршува со "${_issue.suffix}"`;
|
||||
if (_issue.format === "includes") return `Неважечка низа: мора да вклучува "${_issue.includes}"`;
|
||||
if (_issue.format === "regex") return `Неважечка низа: мора да одгоара на патернот ${_issue.pattern}`;
|
||||
return `Invalid ${FormatDictionary[_issue.format] ?? issue.format}`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `Грешен број: мора да биде делив со ${issue.divisor}`;
|
||||
case "unrecognized_keys":
|
||||
return `${issue.keys.length > 1 ? "Непрепознаени клучеви" : "Непрепознаен клуч"}: ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return `Грешен клуч во ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "Грешен внес";
|
||||
case "invalid_element":
|
||||
return `Грешна вредност во ${issue.origin}`;
|
||||
default:
|
||||
return `Грешен внес`;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default function (): { localeError: errors.$ZodErrorMap } {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# Installation
|
||||
> `npm install --save @types/ws`
|
||||
|
||||
# Summary
|
||||
This package contains type definitions for ws (https://github.com/websockets/ws).
|
||||
|
||||
# Details
|
||||
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/ws.
|
||||
|
||||
### Additional Details
|
||||
* Last updated: Tue, 01 Apr 2025 02:59:53 GMT
|
||||
* Dependencies: [@types/node](https://npmjs.com/package/@types/node)
|
||||
|
||||
# Credits
|
||||
These definitions were written by [Paul Loyd](https://github.com/loyd), [Margus Lamp](https://github.com/mlamp), [Philippe D'Alva](https://github.com/TitaneBoy), [reduckted](https://github.com/reduckted), [teidesu](https://github.com/teidesu), [Bartosz Wojtkowiak](https://github.com/wojtkowiak), [Kyle Hensel](https://github.com/k-yle), and [Samuel Skeen](https://github.com/cwadrupldijjit).
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"rpc-enum-errors.d.ts","sourceRoot":"","sources":["../../src/rpc-enum-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGtC,KAAK,MAAM,GAAG,QAAQ,CAAC;IACnB;;;;;;;;;;;;;;;;OAgBG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,CACb,SAAS,EAAE,eAAe,EAC1B,YAAY,EAAE,MAAM,EACpB,eAAe,CAAC,EAAE,OAAO,KACxB,kBAAkB,CAAC,eAAe,CAAC,CAAC;IACzC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;CACrD,CAAC,CAAC;AAEH,wBAAgB,0BAA0B,CACtC,EAAE,mBAAmB,EAAE,eAAe,EAAE,iBAAiB,EAAE,YAAY,EAAE,EAAE,MAAM,EAEjF,cAAc,EAAE,QAAQ,GACzB,WAAW,CAeb"}
|
||||
@@ -0,0 +1,11 @@
|
||||
export type Options = [
|
||||
{
|
||||
ignoreParameters?: boolean;
|
||||
ignoreProperties?: boolean;
|
||||
}
|
||||
];
|
||||
export type MessageIds = 'noInferrableType';
|
||||
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"noInferrableType", Options, import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
||||
name: string;
|
||||
};
|
||||
export default _default;
|
||||
@@ -0,0 +1,183 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.default = default_1;
|
||||
const util = __importStar(require("../core/util.cjs"));
|
||||
function getRussianPlural(count, one, few, many) {
|
||||
const absCount = Math.abs(count);
|
||||
const lastDigit = absCount % 10;
|
||||
const lastTwoDigits = absCount % 100;
|
||||
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|
||||
return many;
|
||||
}
|
||||
if (lastDigit === 1) {
|
||||
return one;
|
||||
}
|
||||
if (lastDigit >= 2 && lastDigit <= 4) {
|
||||
return few;
|
||||
}
|
||||
return many;
|
||||
}
|
||||
const error = () => {
|
||||
const Sizable = {
|
||||
string: {
|
||||
unit: {
|
||||
one: "символ",
|
||||
few: "символа",
|
||||
many: "символов",
|
||||
},
|
||||
verb: "иметь",
|
||||
},
|
||||
file: {
|
||||
unit: {
|
||||
one: "байт",
|
||||
few: "байта",
|
||||
many: "байт",
|
||||
},
|
||||
verb: "иметь",
|
||||
},
|
||||
array: {
|
||||
unit: {
|
||||
one: "элемент",
|
||||
few: "элемента",
|
||||
many: "элементов",
|
||||
},
|
||||
verb: "иметь",
|
||||
},
|
||||
set: {
|
||||
unit: {
|
||||
one: "элемент",
|
||||
few: "элемента",
|
||||
many: "элементов",
|
||||
},
|
||||
verb: "иметь",
|
||||
},
|
||||
};
|
||||
function getSizing(origin) {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
const FormatDictionary = {
|
||||
regex: "ввод",
|
||||
email: "email адрес",
|
||||
url: "URL",
|
||||
emoji: "эмодзи",
|
||||
uuid: "UUID",
|
||||
uuidv4: "UUIDv4",
|
||||
uuidv6: "UUIDv6",
|
||||
nanoid: "nanoid",
|
||||
guid: "GUID",
|
||||
cuid: "cuid",
|
||||
cuid2: "cuid2",
|
||||
ulid: "ULID",
|
||||
xid: "XID",
|
||||
ksuid: "KSUID",
|
||||
datetime: "ISO дата и время",
|
||||
date: "ISO дата",
|
||||
time: "ISO время",
|
||||
duration: "ISO длительность",
|
||||
ipv4: "IPv4 адрес",
|
||||
ipv6: "IPv6 адрес",
|
||||
cidrv4: "IPv4 диапазон",
|
||||
cidrv6: "IPv6 диапазон",
|
||||
base64: "строка в формате base64",
|
||||
base64url: "строка в формате base64url",
|
||||
json_string: "JSON строка",
|
||||
e164: "номер E.164",
|
||||
jwt: "JWT",
|
||||
template_literal: "ввод",
|
||||
};
|
||||
const TypeDictionary = {
|
||||
nan: "NaN",
|
||||
number: "число",
|
||||
array: "массив",
|
||||
};
|
||||
return (issue) => {
|
||||
switch (issue.code) {
|
||||
case "invalid_type": {
|
||||
const expected = TypeDictionary[issue.expected] ?? issue.expected;
|
||||
const receivedType = util.parsedType(issue.input);
|
||||
const received = TypeDictionary[receivedType] ?? receivedType;
|
||||
if (/^[A-Z]/.test(issue.expected)) {
|
||||
return `Неверный ввод: ожидалось instanceof ${issue.expected}, получено ${received}`;
|
||||
}
|
||||
return `Неверный ввод: ожидалось ${expected}, получено ${received}`;
|
||||
}
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1)
|
||||
return `Неверный ввод: ожидалось ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `Неверный вариант: ожидалось одно из ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
const maxValue = Number(issue.maximum);
|
||||
const unit = getRussianPlural(maxValue, sizing.unit.one, sizing.unit.few, sizing.unit.many);
|
||||
return `Слишком большое значение: ожидалось, что ${issue.origin ?? "значение"} будет иметь ${adj}${issue.maximum.toString()} ${unit}`;
|
||||
}
|
||||
return `Слишком большое значение: ожидалось, что ${issue.origin ?? "значение"} будет ${adj}${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
const minValue = Number(issue.minimum);
|
||||
const unit = getRussianPlural(minValue, sizing.unit.one, sizing.unit.few, sizing.unit.many);
|
||||
return `Слишком маленькое значение: ожидалось, что ${issue.origin} будет иметь ${adj}${issue.minimum.toString()} ${unit}`;
|
||||
}
|
||||
return `Слишком маленькое значение: ожидалось, что ${issue.origin} будет ${adj}${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue;
|
||||
if (_issue.format === "starts_with")
|
||||
return `Неверная строка: должна начинаться с "${_issue.prefix}"`;
|
||||
if (_issue.format === "ends_with")
|
||||
return `Неверная строка: должна заканчиваться на "${_issue.suffix}"`;
|
||||
if (_issue.format === "includes")
|
||||
return `Неверная строка: должна содержать "${_issue.includes}"`;
|
||||
if (_issue.format === "regex")
|
||||
return `Неверная строка: должна соответствовать шаблону ${_issue.pattern}`;
|
||||
return `Неверный ${FormatDictionary[_issue.format] ?? issue.format}`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `Неверное число: должно быть кратным ${issue.divisor}`;
|
||||
case "unrecognized_keys":
|
||||
return `Нераспознанн${issue.keys.length > 1 ? "ые" : "ый"} ключ${issue.keys.length > 1 ? "и" : ""}: ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return `Неверный ключ в ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "Неверные входные данные";
|
||||
case "invalid_element":
|
||||
return `Неверное значение в ${issue.origin}`;
|
||||
default:
|
||||
return `Неверные входные данные`;
|
||||
}
|
||||
};
|
||||
};
|
||||
function default_1() {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
module.exports = exports.default;
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,107 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="esnext.temporal" />
|
||||
|
||||
declare namespace Intl {
|
||||
type FormattableTemporalObject = Temporal.PlainDate | Temporal.PlainYearMonth | Temporal.PlainMonthDay | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.Instant;
|
||||
|
||||
interface DateTimeFormat {
|
||||
format(date?: FormattableTemporalObject | Date | number): string;
|
||||
formatToParts(date?: FormattableTemporalObject | Date | number): DateTimeFormatPart[];
|
||||
formatRange(startDate: FormattableTemporalObject | Date | number, endDate: FormattableTemporalObject | Date | number): string;
|
||||
formatRangeToParts(startDate: FormattableTemporalObject | Date | number, endDate: FormattableTemporalObject | Date | number): DateTimeRangeFormatPart[];
|
||||
}
|
||||
|
||||
interface Locale {
|
||||
/**
|
||||
* Returns a list of one or more unique calendar identifiers for this locale.
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getCalendars)
|
||||
*/
|
||||
getCalendars(): string[];
|
||||
/**
|
||||
* Returns a list of one or more collation types for this locale.
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getCollations)
|
||||
*/
|
||||
getCollations(): string[];
|
||||
/**
|
||||
* Returns a list of one or more unique hour cycle identifiers for this locale.
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getHourCycles)
|
||||
*/
|
||||
getHourCycles(): string[];
|
||||
/**
|
||||
* Returns a list of one or more unique numbering system identifiers for this locale.
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getNumberingSystems)
|
||||
*/
|
||||
getNumberingSystems(): string[];
|
||||
/**
|
||||
* Returns the ordering of characters indicated by either ltr (left-to-right) or by rtl (right-to-left) for this locale.
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getTextInfo)
|
||||
*/
|
||||
getTextInfo(): TextInfo;
|
||||
/**
|
||||
* Returns a list of supported time zones for this locale.
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getTimeZones)
|
||||
*/
|
||||
getTimeZones(): string[] | undefined;
|
||||
/**
|
||||
* Returns a `WeekInfo` object with the properties `firstDay`, `weekend` and `minimalDays` for this locale.
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getWeekInfo)
|
||||
*/
|
||||
getWeekInfo(): WeekInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* An object representing text typesetting information associated with the Locale data specified in UTS 35's Layouts Elements.
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getTextInfo#return_value)
|
||||
*/
|
||||
interface TextInfo {
|
||||
/**
|
||||
* A string indicating the direction of text for the locale. Can be either "ltr" (left-to-right) or "rtl" (right-to-left).
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getTextInfo#direction)
|
||||
*/
|
||||
direction?: "ltr" | "rtl";
|
||||
}
|
||||
|
||||
/**
|
||||
* An object representing week information associated with the Locale data specified in UTS 35's Week Elements.
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getWeekInfo#return_value)
|
||||
*/
|
||||
interface WeekInfo {
|
||||
/**
|
||||
* An integer between 1 (Monday) and 7 (Sunday) indicating the first day of the week for the locale. Commonly 1, 5, 6, or 7.
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getWeekInfo#firstday)
|
||||
*/
|
||||
firstDay: number;
|
||||
/**
|
||||
* An array of integers between 1 and 7 indicating the weekend days for the locale.
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getWeekInfo#weekend)
|
||||
*/
|
||||
weekend: number[];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "joycon",
|
||||
"version": "3.1.1",
|
||||
"description": "Load config with ease.",
|
||||
"repository": {
|
||||
"url": "egoist/joycon",
|
||||
"type": "git"
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"types": "types/index.d.ts",
|
||||
"files": [
|
||||
"lib",
|
||||
"types/index.d.ts"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "jest --testPathPattern tests",
|
||||
"build": "babel src -d lib --no-comments",
|
||||
"prepublishOnly": "npm run build"
|
||||
},
|
||||
"author": "egoist <0x142857@gmail.com>",
|
||||
"license": "MIT",
|
||||
"jest": {
|
||||
"testEnvironment": "node"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.13.10",
|
||||
"@babel/core": "^7.13.10",
|
||||
"@babel/preset-env": "^7.13.10",
|
||||
"@egoist/prettier-config": "^0.1.0",
|
||||
"@types/node": "^14.14.33",
|
||||
"babel-jest": "^26.6.3",
|
||||
"babel-plugin-sync": "^0.1.0",
|
||||
"jest-cli": "^26.6.3",
|
||||
"prettier": "^2.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
'use strict'
|
||||
|
||||
const test = require('node:test')
|
||||
const assert = require('node:assert')
|
||||
const { once } = require('node:events')
|
||||
const { join } = require('node:path')
|
||||
const { MessageChannel } = require('node:worker_threads')
|
||||
const ThreadStream = require('thread-stream')
|
||||
const tspl = require('@matteo.collina/tspl')
|
||||
|
||||
const match = require('./match')
|
||||
|
||||
workerTest('transport-on-data.js')
|
||||
workerTest('transport-async-iteration.js', ' when using async iteration')
|
||||
|
||||
function workerTest (filename, description = '') {
|
||||
test(`does not wait for pino to send config by default${description}`, async function (t) {
|
||||
const plan = tspl(t, { plan: 4 })
|
||||
const { port1, port2 } = new MessageChannel()
|
||||
const stream = new ThreadStream({
|
||||
filename: join(__dirname, 'fixtures', filename),
|
||||
workerData: { port: port1 },
|
||||
workerOpts: {
|
||||
transferList: [port1]
|
||||
}
|
||||
})
|
||||
|
||||
const expected = [{
|
||||
level: 30,
|
||||
time: 1617955768092,
|
||||
pid: 2942,
|
||||
hostname: 'MacBook-Pro.local',
|
||||
msg: 'hello world'
|
||||
}, {
|
||||
level: 30,
|
||||
time: 1617955768092,
|
||||
pid: 2942,
|
||||
hostname: 'MacBook-Pro.local',
|
||||
msg: 'another message',
|
||||
prop: 42
|
||||
}]
|
||||
|
||||
const emptyPinoConfig = {
|
||||
levels: undefined,
|
||||
messageKey: undefined,
|
||||
errorKey: undefined
|
||||
}
|
||||
|
||||
port2.on('message', function (message) {
|
||||
match(expected.shift(), message.data, { assert: plan })
|
||||
match(emptyPinoConfig, message.pinoConfig, { assert: plan })
|
||||
})
|
||||
|
||||
const lines = expected.map(JSON.stringify).join('\n')
|
||||
stream.write(lines)
|
||||
stream.end()
|
||||
|
||||
await plan
|
||||
})
|
||||
|
||||
test(`does not wait for pino to send config if transport is not expecting it${description}`, async function (t) {
|
||||
const plan = tspl(t, { plan: 4 })
|
||||
const { port1, port2 } = new MessageChannel()
|
||||
const stream = new ThreadStream({
|
||||
filename: join(__dirname, 'fixtures', filename),
|
||||
workerData: {
|
||||
port: port1,
|
||||
pinoWillSendConfig: true
|
||||
},
|
||||
workerOpts: {
|
||||
transferList: [port1]
|
||||
}
|
||||
})
|
||||
|
||||
const expected = [{
|
||||
level: 30,
|
||||
time: 1617955768092,
|
||||
pid: 2942,
|
||||
hostname: 'MacBook-Pro.local',
|
||||
msg: 'hello world'
|
||||
}, {
|
||||
level: 30,
|
||||
time: 1617955768092,
|
||||
pid: 2942,
|
||||
hostname: 'MacBook-Pro.local',
|
||||
msg: 'another message',
|
||||
prop: 42
|
||||
}]
|
||||
|
||||
const emptyPinoConfig = {
|
||||
levels: undefined,
|
||||
messageKey: undefined,
|
||||
errorKey: undefined
|
||||
}
|
||||
|
||||
const pinoConfig = {
|
||||
levels: {
|
||||
labels: { 30: 'info' },
|
||||
values: { info: 30 }
|
||||
},
|
||||
messageKey: 'msg',
|
||||
errorKey: 'err'
|
||||
}
|
||||
|
||||
stream.emit('message', { code: 'PINO_CONFIG', config: pinoConfig })
|
||||
|
||||
port2.on('message', function (message) {
|
||||
match(expected.shift(), message.data, { assert: plan })
|
||||
match(emptyPinoConfig, message.pinoConfig, { assert: plan })
|
||||
})
|
||||
|
||||
const lines = expected.map(JSON.stringify).join('\n')
|
||||
stream.write(lines)
|
||||
stream.end()
|
||||
|
||||
await plan
|
||||
})
|
||||
|
||||
test(`waits for the pino config when pino intends to send it and the transport requests it${description}`, async function (t) {
|
||||
const plan = tspl(t, { plan: 4 })
|
||||
const { port1, port2 } = new MessageChannel()
|
||||
const stream = new ThreadStream({
|
||||
filename: join(__dirname, 'fixtures', filename),
|
||||
workerData: {
|
||||
port: port1,
|
||||
pinoWillSendConfig: true,
|
||||
opts: {
|
||||
expectPinoConfig: true
|
||||
}
|
||||
},
|
||||
workerOpts: {
|
||||
transferList: [port1]
|
||||
}
|
||||
})
|
||||
|
||||
const expected = [{
|
||||
level: 30,
|
||||
time: 1617955768092,
|
||||
pid: 2942,
|
||||
hostname: 'MacBook-Pro.local',
|
||||
msg: 'hello world'
|
||||
}, {
|
||||
level: 30,
|
||||
time: 1617955768092,
|
||||
pid: 2942,
|
||||
hostname: 'MacBook-Pro.local',
|
||||
msg: 'another message',
|
||||
prop: 42
|
||||
}]
|
||||
|
||||
const pinoConfig = {
|
||||
levels: {
|
||||
labels: { 30: 'info' },
|
||||
values: { info: 30 }
|
||||
},
|
||||
messageKey: 'msg',
|
||||
errorKey: 'err'
|
||||
}
|
||||
|
||||
port2.on('message', function (message) {
|
||||
match(expected.shift(), message.data, { assert: plan })
|
||||
match(pinoConfig, message.pinoConfig, { assert: plan })
|
||||
})
|
||||
|
||||
const lines = expected.map(JSON.stringify).join('\n')
|
||||
stream.emit('message', { code: 'PINO_CONFIG', config: pinoConfig })
|
||||
stream.write(lines)
|
||||
stream.end()
|
||||
|
||||
await plan
|
||||
})
|
||||
|
||||
test(`continues to listen if it receives a message that is not PINO_CONFIG${description}`, async function (t) {
|
||||
const plan = tspl(t, { plan: 4 })
|
||||
const { port1, port2 } = new MessageChannel()
|
||||
const stream = new ThreadStream({
|
||||
filename: join(__dirname, 'fixtures', 'transport-on-data.js'),
|
||||
workerData: {
|
||||
port: port1,
|
||||
pinoWillSendConfig: true,
|
||||
opts: {
|
||||
expectPinoConfig: true
|
||||
}
|
||||
},
|
||||
workerOpts: {
|
||||
transferList: [port1]
|
||||
}
|
||||
})
|
||||
|
||||
const expected = [{
|
||||
level: 30,
|
||||
time: 1617955768092,
|
||||
pid: 2942,
|
||||
hostname: 'MacBook-Pro.local',
|
||||
msg: 'hello world'
|
||||
}, {
|
||||
level: 30,
|
||||
time: 1617955768092,
|
||||
pid: 2942,
|
||||
hostname: 'MacBook-Pro.local',
|
||||
msg: 'another message',
|
||||
prop: 42
|
||||
}]
|
||||
|
||||
const pinoConfig = {
|
||||
levels: {
|
||||
labels: { 30: 'info' },
|
||||
values: { info: 30 }
|
||||
},
|
||||
messageKey: 'msg',
|
||||
errorKey: 'err'
|
||||
}
|
||||
|
||||
port2.on('message', function (message) {
|
||||
match(expected.shift(), message.data, { assert: plan })
|
||||
match(pinoConfig, message.pinoConfig, { assert: plan })
|
||||
})
|
||||
|
||||
const lines = expected.map(JSON.stringify).join('\n')
|
||||
stream.emit('message', 'not a PINO_CONFIG')
|
||||
stream.emit('message', { code: 'NOT_PINO_CONFIG', config: { levels: 'foo', messageKey: 'bar', errorKey: 'baz' } })
|
||||
stream.emit('message', { code: 'PINO_CONFIG', config: pinoConfig })
|
||||
stream.write(lines)
|
||||
stream.end()
|
||||
|
||||
await plan
|
||||
})
|
||||
|
||||
test(`waits for the pino config even if it is sent after write${description}`, async function (t) {
|
||||
const plan = tspl(t, { plan: 4 })
|
||||
const { port1, port2 } = new MessageChannel()
|
||||
const stream = new ThreadStream({
|
||||
filename: join(__dirname, 'fixtures', filename),
|
||||
workerData: {
|
||||
port: port1,
|
||||
pinoWillSendConfig: true,
|
||||
opts: {
|
||||
expectPinoConfig: true
|
||||
}
|
||||
},
|
||||
workerOpts: {
|
||||
transferList: [port1]
|
||||
}
|
||||
})
|
||||
|
||||
const expected = [{
|
||||
level: 30,
|
||||
time: 1617955768092,
|
||||
pid: 2942,
|
||||
hostname: 'MacBook-Pro.local',
|
||||
msg: 'hello world'
|
||||
}, {
|
||||
level: 30,
|
||||
time: 1617955768092,
|
||||
pid: 2942,
|
||||
hostname: 'MacBook-Pro.local',
|
||||
msg: 'another message',
|
||||
prop: 42
|
||||
}]
|
||||
|
||||
const pinoConfig = {
|
||||
levels: {
|
||||
labels: { 30: 'info' },
|
||||
values: { info: 30 }
|
||||
},
|
||||
messageKey: 'msg',
|
||||
errorKey: 'err'
|
||||
}
|
||||
|
||||
port2.on('message', function (message) {
|
||||
match(expected.shift(), message.data, { assert: plan })
|
||||
match(pinoConfig, message.pinoConfig, { assert: plan })
|
||||
})
|
||||
|
||||
const lines = expected.map(JSON.stringify).join('\n')
|
||||
stream.write(lines)
|
||||
stream.emit('message', { code: 'PINO_CONFIG', config: pinoConfig })
|
||||
stream.end()
|
||||
|
||||
await plan
|
||||
})
|
||||
|
||||
test(`emits an error if the transport expects pino to send the config, but pino is not going to${description}`, async function () {
|
||||
const stream = new ThreadStream({
|
||||
filename: join(__dirname, 'fixtures', filename),
|
||||
workerData: {
|
||||
opts: {
|
||||
expectPinoConfig: true
|
||||
}
|
||||
}
|
||||
})
|
||||
const [err] = await once(stream, 'error')
|
||||
assert.equal(err.message, 'This transport is not compatible with the current version of pino. Please upgrade pino to the latest version.')
|
||||
assert.ok(stream.destroyed)
|
||||
})
|
||||
}
|
||||
|
||||
test('waits for the pino config when pipelining', async function (t) {
|
||||
const plan = tspl(t, { plan: 2 })
|
||||
const { port1, port2 } = new MessageChannel()
|
||||
const stream = new ThreadStream({
|
||||
filename: join(__dirname, 'fixtures', 'worker-pipeline.js'),
|
||||
workerData: {
|
||||
pinoWillSendConfig: true,
|
||||
targets: [{
|
||||
target: './transport-transform.js',
|
||||
options: {
|
||||
opts: { expectPinoConfig: true }
|
||||
}
|
||||
}, {
|
||||
target: './transport-on-data.js',
|
||||
options: {
|
||||
port: port1
|
||||
}
|
||||
}]
|
||||
},
|
||||
workerOpts: {
|
||||
transferList: [port1]
|
||||
}
|
||||
})
|
||||
|
||||
const expected = [{
|
||||
level: 'info(30)',
|
||||
time: 1617955768092,
|
||||
pid: 2942,
|
||||
hostname: 'MacBook-Pro.local',
|
||||
msg: 'HELLO WORLD',
|
||||
service: 'from transform'
|
||||
}, {
|
||||
level: 'info(30)',
|
||||
time: 1617955768092,
|
||||
pid: 2942,
|
||||
hostname: 'MacBook-Pro.local',
|
||||
msg: 'ANOTHER MESSAGE',
|
||||
prop: 42,
|
||||
service: 'from transform'
|
||||
}]
|
||||
|
||||
const lines = [{
|
||||
level: 30,
|
||||
time: 1617955768092,
|
||||
pid: 2942,
|
||||
hostname: 'MacBook-Pro.local',
|
||||
msg: 'hello world'
|
||||
}, {
|
||||
level: 30,
|
||||
time: 1617955768092,
|
||||
pid: 2942,
|
||||
hostname: 'MacBook-Pro.local',
|
||||
msg: 'another message',
|
||||
prop: 42
|
||||
}].map(JSON.stringify).join('\n')
|
||||
|
||||
const pinoConfig = {
|
||||
levels: {
|
||||
labels: { 30: 'info' },
|
||||
values: { info: 30 }
|
||||
},
|
||||
messageKey: 'msg',
|
||||
errorKey: 'err'
|
||||
}
|
||||
|
||||
port2.on('message', function (message) {
|
||||
match(expected.shift(), message.data, { assert: plan })
|
||||
})
|
||||
|
||||
stream.emit('message', { code: 'PINO_CONFIG', config: pinoConfig })
|
||||
stream.write(lines)
|
||||
stream.end()
|
||||
|
||||
await plan
|
||||
})
|
||||
@@ -0,0 +1,14 @@
|
||||
export { default as MAX } from './max.js';
|
||||
export { default as NIL } from './nil.js';
|
||||
export { default as parse } from './parse.js';
|
||||
export { default as stringify } from './stringify.js';
|
||||
export { default as v1 } from './v1.js';
|
||||
export { default as v1ToV6 } from './v1ToV6.js';
|
||||
export { default as v3 } from './v3.js';
|
||||
export { default as v4 } from './v4.js';
|
||||
export { default as v5 } from './v5.js';
|
||||
export { default as v6 } from './v6.js';
|
||||
export { default as v6ToV1 } from './v6ToV1.js';
|
||||
export { default as v7 } from './v7.js';
|
||||
export { default as validate } from './validate.js';
|
||||
export { default as version } from './version.js';
|
||||
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"name": "tsx",
|
||||
"version": "4.23.12",
|
||||
"description": "TypeScript Execute (tsx): Node.js enhanced with esbuild to run TypeScript & ESM files",
|
||||
"keywords": [
|
||||
"cli",
|
||||
"runtime",
|
||||
"node",
|
||||
"cjs",
|
||||
"commonjs",
|
||||
"esm",
|
||||
"typescript",
|
||||
"typescript runner"
|
||||
],
|
||||
"license": "MIT",
|
||||
"repository": "privatenumber/tsx",
|
||||
"author": {
|
||||
"name": "Hiroki Osame",
|
||||
"email": "hiroki.osame@gmail.com"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"type": "module",
|
||||
"bin": "./dist/cli.mjs",
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": "./dist/loader.mjs",
|
||||
"./patch-repl": "./dist/patch-repl.cjs",
|
||||
"./cjs": "./dist/cjs/index.cjs",
|
||||
"./cjs/api": {
|
||||
"import": {
|
||||
"types": "./dist/cjs/api/index.d.mts",
|
||||
"default": "./dist/cjs/api/index.mjs"
|
||||
},
|
||||
"require": {
|
||||
"types": "./dist/cjs/api/index.d.cts",
|
||||
"default": "./dist/cjs/api/index.cjs"
|
||||
}
|
||||
},
|
||||
"./esm": "./dist/esm/index.mjs",
|
||||
"./esm/api": {
|
||||
"import": {
|
||||
"types": "./dist/esm/api/index.d.mts",
|
||||
"default": "./dist/esm/api/index.mjs"
|
||||
},
|
||||
"require": {
|
||||
"types": "./dist/esm/api/index.d.cts",
|
||||
"default": "./dist/esm/api/index.cjs"
|
||||
}
|
||||
},
|
||||
"./cli": "./dist/cli.mjs",
|
||||
"./suppress-warnings": "./dist/suppress-warnings.cjs",
|
||||
"./preflight": "./dist/preflight.cjs",
|
||||
"./repl": "./dist/repl.mjs"
|
||||
},
|
||||
"homepage": "https://tsx.hirok.io",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"esbuild": "~0.28.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.3"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"languageVariant.js","sourceRoot":"","sources":["../../src/enums/languageVariant.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,IAAI,eAAoB,CAAC;AAChC,CAAC,UAAU,eAAe;IACtB,eAAe,CAAC,eAAe,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC;IAC9D,eAAe,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;AACxD,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC,CAAC,CAAC"}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,4 @@
|
||||
function _classStaticPrivateMethodSet() {
|
||||
throw new TypeError("attempted to set read only static private field");
|
||||
}
|
||||
module.exports = _classStaticPrivateMethodSet, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
||||
@@ -0,0 +1,83 @@
|
||||
declare namespace locatePath {
|
||||
interface Options {
|
||||
/**
|
||||
Current working directory.
|
||||
|
||||
@default process.cwd()
|
||||
*/
|
||||
readonly cwd?: string;
|
||||
|
||||
/**
|
||||
Type of path to match.
|
||||
|
||||
@default 'file'
|
||||
*/
|
||||
readonly type?: 'file' | 'directory';
|
||||
|
||||
/**
|
||||
Allow symbolic links to match if they point to the requested path type.
|
||||
|
||||
@default true
|
||||
*/
|
||||
readonly allowSymlinks?: boolean;
|
||||
}
|
||||
|
||||
interface AsyncOptions extends Options {
|
||||
/**
|
||||
Number of concurrently pending promises. Minimum: `1`.
|
||||
|
||||
@default Infinity
|
||||
*/
|
||||
readonly concurrency?: number;
|
||||
|
||||
/**
|
||||
Preserve `paths` order when searching.
|
||||
|
||||
Disable this to improve performance if you don't care about the order.
|
||||
|
||||
@default true
|
||||
*/
|
||||
readonly preserveOrder?: boolean;
|
||||
}
|
||||
}
|
||||
|
||||
declare const locatePath: {
|
||||
/**
|
||||
Synchronously get the first path that exists on disk of multiple paths.
|
||||
|
||||
@param paths - Paths to check.
|
||||
@returns The first path that exists or `undefined` if none exists.
|
||||
*/
|
||||
sync: (
|
||||
paths: Iterable<string>,
|
||||
options?: locatePath.Options
|
||||
) => string | undefined;
|
||||
|
||||
/**
|
||||
Get the first path that exists on disk of multiple paths.
|
||||
|
||||
@param paths - Paths to check.
|
||||
@returns The first path that exists or `undefined` if none exists.
|
||||
|
||||
@example
|
||||
```
|
||||
import locatePath = require('locate-path');
|
||||
|
||||
const files = [
|
||||
'unicorn.png',
|
||||
'rainbow.png', // Only this one actually exists on disk
|
||||
'pony.png'
|
||||
];
|
||||
|
||||
(async () => {
|
||||
console(await locatePath(files));
|
||||
//=> 'rainbow'
|
||||
})();
|
||||
```
|
||||
*/
|
||||
(paths: Iterable<string>, options?: locatePath.AsyncOptions): Promise<
|
||||
string | undefined
|
||||
>;
|
||||
};
|
||||
|
||||
export = locatePath;
|
||||
@@ -0,0 +1,8 @@
|
||||
import type { NodeWithParent, TSESTree } from '@typescript-eslint/types';
|
||||
import { DefinitionBase } from './DefinitionBase';
|
||||
import { DefinitionType } from './DefinitionType';
|
||||
export declare class ImplicitGlobalVariableDefinition extends DefinitionBase<DefinitionType.ImplicitGlobalVariable, NodeWithParent, null, TSESTree.BindingName> {
|
||||
readonly isTypeDefinition = false;
|
||||
readonly isVariableDefinition = true;
|
||||
constructor(name: TSESTree.BindingName, node: ImplicitGlobalVariableDefinition['node']);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Removes options that prompt the parser to parse the project with type
|
||||
* information. In other words, you can use this if you are invoking the parser
|
||||
* directly, to ensure that one file will be parsed in isolation, which is much,
|
||||
* much faster.
|
||||
*
|
||||
* @see https://github.com/typescript-eslint/typescript-eslint/issues/8428
|
||||
*/
|
||||
export declare function withoutProjectParserOptions<Options extends object>(opts: Options): Omit<Options, 'EXPERIMENTAL_useProjectService' | 'project' | 'projectService'>;
|
||||
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env node
|
||||
"use strict";
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __commonJS = function(cb, mod) {
|
||||
return function __require() {
|
||||
try {
|
||||
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
||||
} catch (e) {
|
||||
throw mod = 0, e;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// node_modules/semver-compare/index.js
|
||||
var require_semver_compare = __commonJS({
|
||||
"node_modules/semver-compare/index.js": function(exports2, module2) {
|
||||
module2.exports = function cmp(a, b) {
|
||||
var pa = a.split(".");
|
||||
var pb = b.split(".");
|
||||
for (var i = 0; i < 3; i++) {
|
||||
var na = Number(pa[i]);
|
||||
var nb = Number(pb[i]);
|
||||
if (na > nb) return 1;
|
||||
if (nb > na) return -1;
|
||||
if (!isNaN(na) && isNaN(nb)) return 1;
|
||||
if (isNaN(na) && !isNaN(nb)) return -1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// node_modules/please-upgrade-node/index.js
|
||||
var require_please_upgrade_node = __commonJS({
|
||||
"node_modules/please-upgrade-node/index.js": function(exports2, module2) {
|
||||
var semverCompare = require_semver_compare();
|
||||
module2.exports = function pleaseUpgradeNode2(pkg, opts) {
|
||||
var opts = opts || {};
|
||||
var requiredVersion = pkg.engines.node.replace(">=", "");
|
||||
var currentVersion = process.version.replace("v", "");
|
||||
if (semverCompare(currentVersion, requiredVersion) === -1) {
|
||||
if (opts.message) {
|
||||
console.error(opts.message(requiredVersion));
|
||||
} else {
|
||||
console.error(
|
||||
pkg.name + " requires at least version " + requiredVersion + " of Node, please upgrade"
|
||||
);
|
||||
}
|
||||
if (opts.hasOwnProperty("exitCode")) {
|
||||
process.exit(opts.exitCode);
|
||||
} else {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// bin/prettier.cjs
|
||||
var nodeModule = require("module");
|
||||
if (typeof nodeModule.enableCompileCache === "function") {
|
||||
nodeModule.enableCompileCache();
|
||||
}
|
||||
var pleaseUpgradeNode = require_please_upgrade_node();
|
||||
var packageJson = require("../package.json");
|
||||
pleaseUpgradeNode(packageJson);
|
||||
var dynamicImport = new Function("module", "return import(module)");
|
||||
var promise;
|
||||
var index = process.argv.indexOf("--experimental-cli");
|
||||
if (process.env.PRETTIER_EXPERIMENTAL_CLI || index !== -1) {
|
||||
if (index !== -1) {
|
||||
process.argv.splice(index, 1);
|
||||
}
|
||||
promise = dynamicImport("../internal/experimental-cli.mjs").then(
|
||||
function(cli) {
|
||||
return cli.__promise;
|
||||
}
|
||||
);
|
||||
} else {
|
||||
promise = dynamicImport("../internal/legacy-cli.mjs").then(function runCli(cli) {
|
||||
return cli.run();
|
||||
});
|
||||
}
|
||||
module.exports.__promise = promise;
|
||||
@@ -0,0 +1,207 @@
|
||||
import { test } from "vitest";
|
||||
// import path from "path";
|
||||
// import { Node, Project, SyntaxKind } from "ts-morph";
|
||||
|
||||
// import { filePath } from "./language-server.source";
|
||||
|
||||
// The following tool is helpful for understanding the TypeScript AST associated with these tests:
|
||||
// https://ts-ast-viewer.com/ (just copy the contents of language-server.source into the viewer)
|
||||
|
||||
test("", () => {});
|
||||
// describe("Executing Go To Definition (and therefore Find Usages and Rename Refactoring) using an IDE works on inferred object properties", () => {
|
||||
// // Compile file developmentEnvironment.source
|
||||
// const project = new Project({
|
||||
// tsConfigFilePath: path.join(__dirname, "..", "..", "tsconfig.json"),
|
||||
// skipAddingFilesFromTsConfig: true,
|
||||
// });
|
||||
// const sourceFile = project.addSourceFileAtPath(filePath);
|
||||
|
||||
// test("works for object properties inferred from z.object()", () => {
|
||||
// // Find usage of Test.f1 property
|
||||
// const instanceVariable =
|
||||
// sourceFile.getVariableDeclarationOrThrow("instanceOfTest");
|
||||
// const propertyBeingAssigned = getPropertyBeingAssigned(
|
||||
// instanceVariable,
|
||||
// "f1"
|
||||
// );
|
||||
|
||||
// // Find definition of Test.f1 property
|
||||
// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
|
||||
// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
|
||||
// SyntaxKind.VariableDeclaration
|
||||
// );
|
||||
|
||||
// // Assert that find definition returned the Zod definition of Test
|
||||
// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
|
||||
// expect(parentOfProperty?.getName()).toEqual("Test");
|
||||
// });
|
||||
|
||||
// // test("works for first object properties inferred from z.object().merge()", () => {
|
||||
// // // Find usage of TestMerge.f1 property
|
||||
// // const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
|
||||
// // "instanceOfTestMerge"
|
||||
// // );
|
||||
// // const propertyBeingAssigned = getPropertyBeingAssigned(
|
||||
// // instanceVariable,
|
||||
// // "f1"
|
||||
// // );
|
||||
|
||||
// // // Find definition of TestMerge.f1 property
|
||||
// // const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
|
||||
// // const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
|
||||
// // SyntaxKind.VariableDeclaration
|
||||
// // );
|
||||
|
||||
// // // Assert that find definition returned the Zod definition of Test
|
||||
// // expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
|
||||
// // expect(parentOfProperty?.getName()).toEqual("Test");
|
||||
// // });
|
||||
|
||||
// // test("works for second object properties inferred from z.object().merge()", () => {
|
||||
// // // Find usage of TestMerge.f2 property
|
||||
// // const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
|
||||
// // "instanceOfTestMerge"
|
||||
// // );
|
||||
// // const propertyBeingAssigned = getPropertyBeingAssigned(
|
||||
// // instanceVariable,
|
||||
// // "f2"
|
||||
// // );
|
||||
|
||||
// // // Find definition of TestMerge.f2 property
|
||||
// // const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
|
||||
// // const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
|
||||
// // SyntaxKind.VariableDeclaration
|
||||
// // );
|
||||
|
||||
// // // Assert that find definition returned the Zod definition of TestMerge
|
||||
// // expect(definitionOfProperty?.getText()).toEqual(
|
||||
// // "f2: z.string().optional()"
|
||||
// // );
|
||||
// // expect(parentOfProperty?.getName()).toEqual("TestMerge");
|
||||
// // });
|
||||
|
||||
// test("works for first object properties inferred from z.union()", () => {
|
||||
// // Find usage of TestUnion.f1 property
|
||||
// const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
|
||||
// "instanceOfTestUnion"
|
||||
// );
|
||||
// const propertyBeingAssigned = getPropertyBeingAssigned(
|
||||
// instanceVariable,
|
||||
// "f1"
|
||||
// );
|
||||
|
||||
// // Find definition of TestUnion.f1 property
|
||||
// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
|
||||
// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
|
||||
// SyntaxKind.VariableDeclaration
|
||||
// );
|
||||
|
||||
// // Assert that find definition returned the Zod definition of Test
|
||||
// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
|
||||
// expect(parentOfProperty?.getName()).toEqual("Test");
|
||||
// });
|
||||
|
||||
// test("works for second object properties inferred from z.union()", () => {
|
||||
// // Find usage of TestUnion.f2 property
|
||||
// const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
|
||||
// "instanceOfTestUnion"
|
||||
// );
|
||||
// const propertyBeingAssigned = getPropertyBeingAssigned(
|
||||
// instanceVariable,
|
||||
// "f2"
|
||||
// );
|
||||
|
||||
// // Find definition of TestUnion.f2 property
|
||||
// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
|
||||
// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
|
||||
// SyntaxKind.VariableDeclaration
|
||||
// );
|
||||
|
||||
// // Assert that find definition returned the Zod definition of TestUnion
|
||||
// expect(definitionOfProperty?.getText()).toEqual(
|
||||
// "f2: z.string().optional()"
|
||||
// );
|
||||
// expect(parentOfProperty?.getName()).toEqual("TestUnion");
|
||||
// });
|
||||
|
||||
// test("works for object properties inferred from z.object().partial()", () => {
|
||||
// // Find usage of TestPartial.f1 property
|
||||
// const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
|
||||
// "instanceOfTestPartial"
|
||||
// );
|
||||
// const propertyBeingAssigned = getPropertyBeingAssigned(
|
||||
// instanceVariable,
|
||||
// "f1"
|
||||
// );
|
||||
|
||||
// // Find definition of TestPartial.f1 property
|
||||
// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
|
||||
// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
|
||||
// SyntaxKind.VariableDeclaration
|
||||
// );
|
||||
|
||||
// // Assert that find definition returned the Zod definition of Test
|
||||
// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
|
||||
// expect(parentOfProperty?.getName()).toEqual("Test");
|
||||
// });
|
||||
|
||||
// test("works for object properties inferred from z.object().pick()", () => {
|
||||
// // Find usage of TestPick.f1 property
|
||||
// const instanceVariable =
|
||||
// sourceFile.getVariableDeclarationOrThrow("instanceOfTestPick");
|
||||
// const propertyBeingAssigned = getPropertyBeingAssigned(
|
||||
// instanceVariable,
|
||||
// "f1"
|
||||
// );
|
||||
|
||||
// // Find definition of TestPick.f1 property
|
||||
// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
|
||||
// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
|
||||
// SyntaxKind.VariableDeclaration
|
||||
// );
|
||||
|
||||
// // Assert that find definition returned the Zod definition of Test
|
||||
// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
|
||||
// expect(parentOfProperty?.getName()).toEqual("Test");
|
||||
// });
|
||||
|
||||
// test("works for object properties inferred from z.object().omit()", () => {
|
||||
// // Find usage of TestOmit.f1 property
|
||||
// const instanceVariable =
|
||||
// sourceFile.getVariableDeclarationOrThrow("instanceOfTestOmit");
|
||||
// const propertyBeingAssigned = getPropertyBeingAssigned(
|
||||
// instanceVariable,
|
||||
// "f1"
|
||||
// );
|
||||
|
||||
// // Find definition of TestOmit.f1 property
|
||||
// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
|
||||
// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
|
||||
// SyntaxKind.VariableDeclaration
|
||||
// );
|
||||
|
||||
// // Assert that find definition returned the Zod definition of Test
|
||||
// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
|
||||
// expect(parentOfProperty?.getName()).toEqual("Test");
|
||||
// });
|
||||
// });
|
||||
|
||||
// const getPropertyBeingAssigned = (node: Node, name: string) => {
|
||||
// const propertyAssignment = node.forEachDescendant((descendent) =>
|
||||
// Node.isPropertyAssignment(descendent) && descendent.getName() == name
|
||||
// ? descendent
|
||||
// : undefined
|
||||
// );
|
||||
|
||||
// if (propertyAssignment == null)
|
||||
// fail(`Could not find property assignment with name ${name}`);
|
||||
|
||||
// const propertyLiteral = propertyAssignment.getFirstDescendantByKind(
|
||||
// SyntaxKind.Identifier
|
||||
// );
|
||||
|
||||
// if (propertyLiteral == null)
|
||||
// fail(`Could not find property literal with name ${name}`);
|
||||
|
||||
// return propertyLiteral;
|
||||
// };
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"name": "@vitest/runner",
|
||||
"type": "module",
|
||||
"version": "4.1.10",
|
||||
"description": "Vitest test runner",
|
||||
"license": "MIT",
|
||||
"funding": "https://opencollective.com/vitest",
|
||||
"homepage": "https://vitest.dev/api/advanced/runner",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/vitest-dev/vitest.git",
|
||||
"directory": "packages/runner"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/vitest-dev/vitest/issues"
|
||||
},
|
||||
"keywords": [
|
||||
"vitest",
|
||||
"test",
|
||||
"test-runner"
|
||||
],
|
||||
"sideEffects": true,
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.js"
|
||||
},
|
||||
"./utils": {
|
||||
"types": "./dist/utils.d.ts",
|
||||
"default": "./dist/utils.js"
|
||||
},
|
||||
"./types": {
|
||||
"types": "./dist/types.d.ts",
|
||||
"default": "./dist/types.js"
|
||||
},
|
||||
"./*": "./*"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"*.d.ts",
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"pathe": "^2.0.3",
|
||||
"@vitest/utils": "4.1.10"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "premove dist && rollup -c",
|
||||
"dev": "rollup -c --watch"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* @fileoverview The rule should warn against code that tries to compare against -0.
|
||||
* @author Aladdin-ADD <hh_2013@foxmail.com>
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const { getVariableByName } = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
|
||||
docs: {
|
||||
description: "Disallow comparing against `-0`",
|
||||
recommended: true,
|
||||
url: "https://eslint.org/docs/latest/rules/no-compare-neg-zero",
|
||||
},
|
||||
|
||||
fixable: null,
|
||||
hasSuggestions: true,
|
||||
schema: [],
|
||||
|
||||
messages: {
|
||||
unexpected:
|
||||
"Do not use the '{{operator}}' operator to compare against -0.",
|
||||
suggestRemoveMinus:
|
||||
"Replace '-0' with '0' (keeps the current comparison behavior).",
|
||||
suggestObjectIs:
|
||||
"Replace with 'Object.is()' (changes the comparison to distinguish -0 from +0).",
|
||||
suggestNotObjectIs:
|
||||
"Replace with '!Object.is()' (changes the comparison to distinguish -0 from +0).",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks a given node is -0
|
||||
* @param {ASTNode} node A node to check.
|
||||
* @returns {boolean} `true` if the node is -0.
|
||||
*/
|
||||
function isNegZero(node) {
|
||||
return (
|
||||
node.type === "UnaryExpression" &&
|
||||
node.operator === "-" &&
|
||||
node.argument.type === "Literal" &&
|
||||
node.argument.value === 0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source text of an operand, keeping parentheses where required.
|
||||
* @param {ASTNode} operand A comparison operand node.
|
||||
* @returns {string} The source text of the operand.
|
||||
*/
|
||||
function getOperandText(operand) {
|
||||
const text = sourceCode.getText(operand);
|
||||
|
||||
return operand.type === "SequenceExpression" ? `(${text})` : text;
|
||||
}
|
||||
|
||||
const OPERATORS_TO_CHECK = new Set([
|
||||
">",
|
||||
">=",
|
||||
"<",
|
||||
"<=",
|
||||
"==",
|
||||
"===",
|
||||
"!=",
|
||||
"!==",
|
||||
]);
|
||||
|
||||
return {
|
||||
BinaryExpression(node) {
|
||||
if (!OPERATORS_TO_CHECK.has(node.operator)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const leftIsNegZero = isNegZero(node.left);
|
||||
const rightIsNegZero = isNegZero(node.right);
|
||||
|
||||
if (!leftIsNegZero && !rightIsNegZero) {
|
||||
return;
|
||||
}
|
||||
|
||||
context.report({
|
||||
node,
|
||||
messageId: "unexpected",
|
||||
data: { operator: node.operator },
|
||||
suggest: [
|
||||
{
|
||||
messageId: "suggestRemoveMinus",
|
||||
*fix(fixer) {
|
||||
if (leftIsNegZero) {
|
||||
yield fixer.replaceText(node.left, "0");
|
||||
}
|
||||
if (rightIsNegZero) {
|
||||
yield fixer.replaceText(node.right, "0");
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
messageId:
|
||||
node.operator === "==="
|
||||
? "suggestObjectIs"
|
||||
: "suggestNotObjectIs",
|
||||
fix(fixer) {
|
||||
if (
|
||||
(node.operator !== "===" &&
|
||||
node.operator !== "!==") ||
|
||||
sourceCode.getCommentsInside(node).length >
|
||||
0
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const objectVariable = getVariableByName(
|
||||
sourceCode.getScope(node),
|
||||
"Object",
|
||||
);
|
||||
|
||||
if (
|
||||
!objectVariable ||
|
||||
objectVariable.identifiers.length > 0
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const negation =
|
||||
node.operator === "===" ? "" : "!";
|
||||
|
||||
return fixer.replaceText(
|
||||
node,
|
||||
`${negation}Object.is(${getOperandText(node.left)}, ${getOperandText(node.right)})`,
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user