WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
import { _ as _class_apply_descriptor_get } from "./_class_apply_descriptor_get.js";
|
||||
import { _ as _class_extract_field_descriptor } from "./_class_extract_field_descriptor.js";
|
||||
|
||||
function _class_private_field_get(receiver, privateMap) {
|
||||
var descriptor = _class_extract_field_descriptor(receiver, privateMap, "get");
|
||||
return _class_apply_descriptor_get(receiver, descriptor);
|
||||
}
|
||||
export { _class_private_field_get as _ };
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"short-u16.d.ts","sourceRoot":"","sources":["../../src/short-u16.ts"],"names":[],"mappings":"AAAA,OAAO,EAMH,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACtB,MAAM,qBAAqB,CAAC;AAI7B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,kBAAkB,QAAO,mBAAmB,CAAC,MAAM,GAAG,MAAM,CA6BnE,CAAC;AAEP;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,kBAAkB,QAAO,mBAAmB,CAAC,MAAM,CAmB1D,CAAC;AAEP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,eAAO,MAAM,gBAAgB,QAAO,iBAAiB,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,CACjB,CAAC"}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
import v35 from './v35.js';
|
||||
import md5 from './md5.js';
|
||||
const v3 = v35('v3', 0x30, md5);
|
||||
export default v3;
|
||||
@@ -0,0 +1,743 @@
|
||||
'use strict';
|
||||
|
||||
const { Writable } = require('stream');
|
||||
|
||||
const PerMessageDeflate = require('./permessage-deflate');
|
||||
const {
|
||||
BINARY_TYPES,
|
||||
EMPTY_BUFFER,
|
||||
kStatusCode,
|
||||
kWebSocket
|
||||
} = require('./constants');
|
||||
const { concat, toArrayBuffer, unmask } = require('./buffer-util');
|
||||
const { isValidStatusCode, isValidUTF8 } = require('./validation');
|
||||
|
||||
const FastBuffer = Buffer[Symbol.species];
|
||||
|
||||
const GET_INFO = 0;
|
||||
const GET_PAYLOAD_LENGTH_16 = 1;
|
||||
const GET_PAYLOAD_LENGTH_64 = 2;
|
||||
const GET_MASK = 3;
|
||||
const GET_DATA = 4;
|
||||
const INFLATING = 5;
|
||||
const DEFER_EVENT = 6;
|
||||
|
||||
/**
|
||||
* HyBi Receiver implementation.
|
||||
*
|
||||
* @extends Writable
|
||||
*/
|
||||
class Receiver extends Writable {
|
||||
/**
|
||||
* Creates a Receiver instance.
|
||||
*
|
||||
* @param {Object} [options] Options object
|
||||
* @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether
|
||||
* any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
|
||||
* multiple times in the same tick
|
||||
* @param {String} [options.binaryType=nodebuffer] The type for binary data
|
||||
* @param {Object} [options.extensions] An object containing the negotiated
|
||||
* extensions
|
||||
* @param {Boolean} [options.isServer=false] Specifies whether to operate in
|
||||
* client or server mode
|
||||
* @param {Number} [options.maxBufferedChunks=0] The maximum number of
|
||||
* buffered data chunks
|
||||
* @param {Number} [options.maxFragments=0] The maximum number of message
|
||||
* fragments
|
||||
* @param {Number} [options.maxPayload=0] The maximum allowed message length
|
||||
* @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
|
||||
* not to skip UTF-8 validation for text and close messages
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
super();
|
||||
|
||||
this._allowSynchronousEvents =
|
||||
options.allowSynchronousEvents !== undefined
|
||||
? options.allowSynchronousEvents
|
||||
: true;
|
||||
this._binaryType = options.binaryType || BINARY_TYPES[0];
|
||||
this._extensions = options.extensions || {};
|
||||
this._isServer = !!options.isServer;
|
||||
this._maxBufferedChunks = options.maxBufferedChunks | 0;
|
||||
this._maxFragments = options.maxFragments | 0;
|
||||
this._maxPayload = options.maxPayload | 0;
|
||||
this._skipUTF8Validation = !!options.skipUTF8Validation;
|
||||
this[kWebSocket] = undefined;
|
||||
|
||||
this._bufferedBytes = 0;
|
||||
this._buffers = [];
|
||||
|
||||
this._compressed = false;
|
||||
this._payloadLength = 0;
|
||||
this._mask = undefined;
|
||||
this._fragmented = 0;
|
||||
this._masked = false;
|
||||
this._fin = false;
|
||||
this._opcode = 0;
|
||||
|
||||
this._totalPayloadLength = 0;
|
||||
this._messageLength = 0;
|
||||
this._numFragments = 0;
|
||||
this._fragments = [];
|
||||
|
||||
this._errored = false;
|
||||
this._loop = false;
|
||||
this._state = GET_INFO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements `Writable.prototype._write()`.
|
||||
*
|
||||
* @param {Buffer} chunk The chunk of data to write
|
||||
* @param {String} encoding The character encoding of `chunk`
|
||||
* @param {Function} cb Callback
|
||||
* @private
|
||||
*/
|
||||
_write(chunk, encoding, cb) {
|
||||
if (this._opcode === 0x08 && this._state == GET_INFO) return cb();
|
||||
|
||||
if (
|
||||
this._maxBufferedChunks > 0 &&
|
||||
this._buffers.length >= this._maxBufferedChunks
|
||||
) {
|
||||
cb(
|
||||
this.createError(
|
||||
RangeError,
|
||||
'Too many buffered chunks',
|
||||
false,
|
||||
1008,
|
||||
'WS_ERR_TOO_MANY_BUFFERED_PARTS'
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this._bufferedBytes += chunk.length;
|
||||
this._buffers.push(chunk);
|
||||
this.startLoop(cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumes `n` bytes from the buffered data.
|
||||
*
|
||||
* @param {Number} n The number of bytes to consume
|
||||
* @return {Buffer} The consumed bytes
|
||||
* @private
|
||||
*/
|
||||
consume(n) {
|
||||
this._bufferedBytes -= n;
|
||||
|
||||
if (n === this._buffers[0].length) return this._buffers.shift();
|
||||
|
||||
if (n < this._buffers[0].length) {
|
||||
const buf = this._buffers[0];
|
||||
this._buffers[0] = new FastBuffer(
|
||||
buf.buffer,
|
||||
buf.byteOffset + n,
|
||||
buf.length - n
|
||||
);
|
||||
|
||||
return new FastBuffer(buf.buffer, buf.byteOffset, n);
|
||||
}
|
||||
|
||||
const dst = Buffer.allocUnsafe(n);
|
||||
|
||||
do {
|
||||
const buf = this._buffers[0];
|
||||
const offset = dst.length - n;
|
||||
|
||||
if (n >= buf.length) {
|
||||
dst.set(this._buffers.shift(), offset);
|
||||
} else {
|
||||
dst.set(new Uint8Array(buf.buffer, buf.byteOffset, n), offset);
|
||||
this._buffers[0] = new FastBuffer(
|
||||
buf.buffer,
|
||||
buf.byteOffset + n,
|
||||
buf.length - n
|
||||
);
|
||||
}
|
||||
|
||||
n -= buf.length;
|
||||
} while (n > 0);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the parsing loop.
|
||||
*
|
||||
* @param {Function} cb Callback
|
||||
* @private
|
||||
*/
|
||||
startLoop(cb) {
|
||||
this._loop = true;
|
||||
|
||||
do {
|
||||
switch (this._state) {
|
||||
case GET_INFO:
|
||||
this.getInfo(cb);
|
||||
break;
|
||||
case GET_PAYLOAD_LENGTH_16:
|
||||
this.getPayloadLength16(cb);
|
||||
break;
|
||||
case GET_PAYLOAD_LENGTH_64:
|
||||
this.getPayloadLength64(cb);
|
||||
break;
|
||||
case GET_MASK:
|
||||
this.getMask();
|
||||
break;
|
||||
case GET_DATA:
|
||||
this.getData(cb);
|
||||
break;
|
||||
case INFLATING:
|
||||
case DEFER_EVENT:
|
||||
this._loop = false;
|
||||
return;
|
||||
}
|
||||
} while (this._loop);
|
||||
|
||||
if (!this._errored) cb();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the first two bytes of a frame.
|
||||
*
|
||||
* @param {Function} cb Callback
|
||||
* @private
|
||||
*/
|
||||
getInfo(cb) {
|
||||
if (this._bufferedBytes < 2) {
|
||||
this._loop = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const buf = this.consume(2);
|
||||
|
||||
if ((buf[0] & 0x30) !== 0x00) {
|
||||
const error = this.createError(
|
||||
RangeError,
|
||||
'RSV2 and RSV3 must be clear',
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_UNEXPECTED_RSV_2_3'
|
||||
);
|
||||
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
const compressed = (buf[0] & 0x40) === 0x40;
|
||||
|
||||
if (compressed && !this._extensions[PerMessageDeflate.extensionName]) {
|
||||
const error = this.createError(
|
||||
RangeError,
|
||||
'RSV1 must be clear',
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_UNEXPECTED_RSV_1'
|
||||
);
|
||||
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
this._fin = (buf[0] & 0x80) === 0x80;
|
||||
this._opcode = buf[0] & 0x0f;
|
||||
this._payloadLength = buf[1] & 0x7f;
|
||||
|
||||
if (this._opcode === 0x00) {
|
||||
if (compressed) {
|
||||
const error = this.createError(
|
||||
RangeError,
|
||||
'RSV1 must be clear',
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_UNEXPECTED_RSV_1'
|
||||
);
|
||||
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._fragmented) {
|
||||
const error = this.createError(
|
||||
RangeError,
|
||||
'invalid opcode 0',
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_INVALID_OPCODE'
|
||||
);
|
||||
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
this._opcode = this._fragmented;
|
||||
} else if (this._opcode === 0x01 || this._opcode === 0x02) {
|
||||
if (this._fragmented) {
|
||||
const error = this.createError(
|
||||
RangeError,
|
||||
`invalid opcode ${this._opcode}`,
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_INVALID_OPCODE'
|
||||
);
|
||||
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
this._compressed = compressed;
|
||||
} else if (this._opcode > 0x07 && this._opcode < 0x0b) {
|
||||
if (!this._fin) {
|
||||
const error = this.createError(
|
||||
RangeError,
|
||||
'FIN must be set',
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_EXPECTED_FIN'
|
||||
);
|
||||
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (compressed) {
|
||||
const error = this.createError(
|
||||
RangeError,
|
||||
'RSV1 must be clear',
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_UNEXPECTED_RSV_1'
|
||||
);
|
||||
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
this._payloadLength > 0x7d ||
|
||||
(this._opcode === 0x08 && this._payloadLength === 1)
|
||||
) {
|
||||
const error = this.createError(
|
||||
RangeError,
|
||||
`invalid payload length ${this._payloadLength}`,
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH'
|
||||
);
|
||||
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
const error = this.createError(
|
||||
RangeError,
|
||||
`invalid opcode ${this._opcode}`,
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_INVALID_OPCODE'
|
||||
);
|
||||
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._fin && !this._fragmented) this._fragmented = this._opcode;
|
||||
this._masked = (buf[1] & 0x80) === 0x80;
|
||||
|
||||
if (this._isServer) {
|
||||
if (!this._masked) {
|
||||
const error = this.createError(
|
||||
RangeError,
|
||||
'MASK must be set',
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_EXPECTED_MASK'
|
||||
);
|
||||
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
} else if (this._masked) {
|
||||
const error = this.createError(
|
||||
RangeError,
|
||||
'MASK must be clear',
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_UNEXPECTED_MASK'
|
||||
);
|
||||
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16;
|
||||
else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64;
|
||||
else this.haveLength(cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets extended payload length (7+16).
|
||||
*
|
||||
* @param {Function} cb Callback
|
||||
* @private
|
||||
*/
|
||||
getPayloadLength16(cb) {
|
||||
if (this._bufferedBytes < 2) {
|
||||
this._loop = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this._payloadLength = this.consume(2).readUInt16BE(0);
|
||||
this.haveLength(cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets extended payload length (7+64).
|
||||
*
|
||||
* @param {Function} cb Callback
|
||||
* @private
|
||||
*/
|
||||
getPayloadLength64(cb) {
|
||||
if (this._bufferedBytes < 8) {
|
||||
this._loop = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const buf = this.consume(8);
|
||||
const num = buf.readUInt32BE(0);
|
||||
|
||||
//
|
||||
// The maximum safe integer in JavaScript is 2^53 - 1. An error is returned
|
||||
// if payload length is greater than this number.
|
||||
//
|
||||
if (num > Math.pow(2, 53 - 32) - 1) {
|
||||
const error = this.createError(
|
||||
RangeError,
|
||||
'Unsupported WebSocket frame: payload length > 2^53 - 1',
|
||||
false,
|
||||
1009,
|
||||
'WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH'
|
||||
);
|
||||
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4);
|
||||
this.haveLength(cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Payload length has been read.
|
||||
*
|
||||
* @param {Function} cb Callback
|
||||
* @private
|
||||
*/
|
||||
haveLength(cb) {
|
||||
if (this._payloadLength && this._opcode < 0x08) {
|
||||
this._totalPayloadLength += this._payloadLength;
|
||||
if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) {
|
||||
const error = this.createError(
|
||||
RangeError,
|
||||
'Max payload size exceeded',
|
||||
false,
|
||||
1009,
|
||||
'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'
|
||||
);
|
||||
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._masked) this._state = GET_MASK;
|
||||
else this._state = GET_DATA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads mask bytes.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
getMask() {
|
||||
if (this._bufferedBytes < 4) {
|
||||
this._loop = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this._mask = this.consume(4);
|
||||
this._state = GET_DATA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads data bytes.
|
||||
*
|
||||
* @param {Function} cb Callback
|
||||
* @private
|
||||
*/
|
||||
getData(cb) {
|
||||
let data = EMPTY_BUFFER;
|
||||
|
||||
if (this._payloadLength) {
|
||||
if (this._bufferedBytes < this._payloadLength) {
|
||||
this._loop = false;
|
||||
return;
|
||||
}
|
||||
|
||||
data = this.consume(this._payloadLength);
|
||||
|
||||
if (
|
||||
this._masked &&
|
||||
(this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0
|
||||
) {
|
||||
unmask(data, this._mask);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._opcode > 0x07) {
|
||||
this.controlMessage(data, cb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._maxFragments > 0 && ++this._numFragments > this._maxFragments) {
|
||||
const error = this.createError(
|
||||
RangeError,
|
||||
'Too many message fragments',
|
||||
false,
|
||||
1008,
|
||||
'WS_ERR_TOO_MANY_BUFFERED_PARTS'
|
||||
);
|
||||
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._compressed) {
|
||||
this._state = INFLATING;
|
||||
this.decompress(data, cb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.length) {
|
||||
//
|
||||
// This message is not compressed so its length is the sum of the payload
|
||||
// length of all fragments.
|
||||
//
|
||||
this._messageLength = this._totalPayloadLength;
|
||||
this._fragments.push(data);
|
||||
}
|
||||
|
||||
this.dataMessage(cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompresses data.
|
||||
*
|
||||
* @param {Buffer} data Compressed data
|
||||
* @param {Function} cb Callback
|
||||
* @private
|
||||
*/
|
||||
decompress(data, cb) {
|
||||
const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
|
||||
|
||||
perMessageDeflate.decompress(data, this._fin, (err, buf) => {
|
||||
if (err) return cb(err);
|
||||
|
||||
if (buf.length) {
|
||||
this._messageLength += buf.length;
|
||||
if (this._messageLength > this._maxPayload && this._maxPayload > 0) {
|
||||
const error = this.createError(
|
||||
RangeError,
|
||||
'Max payload size exceeded',
|
||||
false,
|
||||
1009,
|
||||
'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'
|
||||
);
|
||||
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
this._fragments.push(buf);
|
||||
}
|
||||
|
||||
this.dataMessage(cb);
|
||||
if (this._state === GET_INFO) this.startLoop(cb);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a data message.
|
||||
*
|
||||
* @param {Function} cb Callback
|
||||
* @private
|
||||
*/
|
||||
dataMessage(cb) {
|
||||
if (!this._fin) {
|
||||
this._state = GET_INFO;
|
||||
return;
|
||||
}
|
||||
|
||||
const messageLength = this._messageLength;
|
||||
const fragments = this._fragments;
|
||||
|
||||
this._totalPayloadLength = 0;
|
||||
this._messageLength = 0;
|
||||
this._fragmented = 0;
|
||||
this._numFragments = 0;
|
||||
this._fragments = [];
|
||||
|
||||
if (this._opcode === 2) {
|
||||
let data;
|
||||
|
||||
if (this._binaryType === 'nodebuffer') {
|
||||
data = concat(fragments, messageLength);
|
||||
} else if (this._binaryType === 'arraybuffer') {
|
||||
data = toArrayBuffer(concat(fragments, messageLength));
|
||||
} else if (this._binaryType === 'blob') {
|
||||
data = new Blob(fragments);
|
||||
} else {
|
||||
data = fragments;
|
||||
}
|
||||
|
||||
if (this._allowSynchronousEvents) {
|
||||
this.emit('message', data, true);
|
||||
this._state = GET_INFO;
|
||||
} else {
|
||||
this._state = DEFER_EVENT;
|
||||
setImmediate(() => {
|
||||
this.emit('message', data, true);
|
||||
this._state = GET_INFO;
|
||||
this.startLoop(cb);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const buf = concat(fragments, messageLength);
|
||||
|
||||
if (!this._skipUTF8Validation && !isValidUTF8(buf)) {
|
||||
const error = this.createError(
|
||||
Error,
|
||||
'invalid UTF-8 sequence',
|
||||
true,
|
||||
1007,
|
||||
'WS_ERR_INVALID_UTF8'
|
||||
);
|
||||
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._state === INFLATING || this._allowSynchronousEvents) {
|
||||
this.emit('message', buf, false);
|
||||
this._state = GET_INFO;
|
||||
} else {
|
||||
this._state = DEFER_EVENT;
|
||||
setImmediate(() => {
|
||||
this.emit('message', buf, false);
|
||||
this._state = GET_INFO;
|
||||
this.startLoop(cb);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a control message.
|
||||
*
|
||||
* @param {Buffer} data Data to handle
|
||||
* @return {(Error|RangeError|undefined)} A possible error
|
||||
* @private
|
||||
*/
|
||||
controlMessage(data, cb) {
|
||||
if (this._opcode === 0x08) {
|
||||
if (data.length === 0) {
|
||||
this._loop = false;
|
||||
this.emit('conclude', 1005, EMPTY_BUFFER);
|
||||
this.end();
|
||||
} else {
|
||||
const code = data.readUInt16BE(0);
|
||||
|
||||
if (!isValidStatusCode(code)) {
|
||||
const error = this.createError(
|
||||
RangeError,
|
||||
`invalid status code ${code}`,
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_INVALID_CLOSE_CODE'
|
||||
);
|
||||
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
const buf = new FastBuffer(
|
||||
data.buffer,
|
||||
data.byteOffset + 2,
|
||||
data.length - 2
|
||||
);
|
||||
|
||||
if (!this._skipUTF8Validation && !isValidUTF8(buf)) {
|
||||
const error = this.createError(
|
||||
Error,
|
||||
'invalid UTF-8 sequence',
|
||||
true,
|
||||
1007,
|
||||
'WS_ERR_INVALID_UTF8'
|
||||
);
|
||||
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
this._loop = false;
|
||||
this.emit('conclude', code, buf);
|
||||
this.end();
|
||||
}
|
||||
|
||||
this._state = GET_INFO;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._allowSynchronousEvents) {
|
||||
this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data);
|
||||
this._state = GET_INFO;
|
||||
} else {
|
||||
this._state = DEFER_EVENT;
|
||||
setImmediate(() => {
|
||||
this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data);
|
||||
this._state = GET_INFO;
|
||||
this.startLoop(cb);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an error object.
|
||||
*
|
||||
* @param {function(new:Error|RangeError)} ErrorCtor The error constructor
|
||||
* @param {String} message The error message
|
||||
* @param {Boolean} prefix Specifies whether or not to add a default prefix to
|
||||
* `message`
|
||||
* @param {Number} statusCode The status code
|
||||
* @param {String} errorCode The exposed error code
|
||||
* @return {(Error|RangeError)} The error
|
||||
* @private
|
||||
*/
|
||||
createError(ErrorCtor, message, prefix, statusCode, errorCode) {
|
||||
this._loop = false;
|
||||
this._errored = true;
|
||||
|
||||
const err = new ErrorCtor(
|
||||
prefix ? `Invalid WebSocket frame: ${message}` : message
|
||||
);
|
||||
|
||||
Error.captureStackTrace(err, this.createError);
|
||||
err.code = errorCode;
|
||||
err[kStatusCode] = statusCode;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Receiver;
|
||||
@@ -0,0 +1,5 @@
|
||||
HELP-ME by Matteo
|
||||
|
||||
* start starts a script
|
||||
* help shows help
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
"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 () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isNullableType = isNullableType;
|
||||
exports.isTypeArrayTypeOrUnionOfArrayTypes = isTypeArrayTypeOrUnionOfArrayTypes;
|
||||
exports.isTypeNeverType = isTypeNeverType;
|
||||
exports.isTypeUnknownType = isTypeUnknownType;
|
||||
exports.isTypeReferenceType = isTypeReferenceType;
|
||||
exports.isTypeAnyType = isTypeAnyType;
|
||||
exports.isTypeAnyArrayType = isTypeAnyArrayType;
|
||||
exports.isTypeUnknownArrayType = isTypeUnknownArrayType;
|
||||
exports.typeIsOrHasBaseType = typeIsOrHasBaseType;
|
||||
exports.isTypeBigIntLiteralType = isTypeBigIntLiteralType;
|
||||
exports.isTypeTemplateLiteralType = isTypeTemplateLiteralType;
|
||||
const debug_1 = __importDefault(require("debug"));
|
||||
const tsutils = __importStar(require("ts-api-utils"));
|
||||
const ts = __importStar(require("typescript"));
|
||||
const typeFlagUtils_1 = require("./typeFlagUtils");
|
||||
const log = (0, debug_1.default)('typescript-eslint:type-utils:predicates');
|
||||
/**
|
||||
* Checks if the given type is (or accepts) nullable
|
||||
*/
|
||||
function isNullableType(type) {
|
||||
return (0, typeFlagUtils_1.isTypeFlagSet)(type, ts.TypeFlags.Any |
|
||||
ts.TypeFlags.Unknown |
|
||||
ts.TypeFlags.Null |
|
||||
ts.TypeFlags.Undefined |
|
||||
ts.TypeFlags.Void);
|
||||
}
|
||||
/**
|
||||
* Checks if the given type is either an array type,
|
||||
* or a union made up solely of array types.
|
||||
*/
|
||||
function isTypeArrayTypeOrUnionOfArrayTypes(type, checker) {
|
||||
for (const t of tsutils.unionConstituents(type)) {
|
||||
if (!checker.isArrayType(t)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @returns true if the type is `never`
|
||||
*/
|
||||
function isTypeNeverType(type) {
|
||||
return (0, typeFlagUtils_1.isTypeFlagSet)(type, ts.TypeFlags.Never);
|
||||
}
|
||||
/**
|
||||
* @returns true if the type is `unknown`
|
||||
*/
|
||||
function isTypeUnknownType(type) {
|
||||
return (0, typeFlagUtils_1.isTypeFlagSet)(type, ts.TypeFlags.Unknown);
|
||||
}
|
||||
// https://github.com/microsoft/TypeScript/blob/42aa18bf442c4df147e30deaf27261a41cbdc617/src/compiler/types.ts#L5157
|
||||
const Nullable = ts.TypeFlags.Undefined | ts.TypeFlags.Null;
|
||||
// https://github.com/microsoft/TypeScript/blob/42aa18bf442c4df147e30deaf27261a41cbdc617/src/compiler/types.ts#L5187
|
||||
const ObjectFlagsType = ts.TypeFlags.Any |
|
||||
Nullable |
|
||||
ts.TypeFlags.Never |
|
||||
ts.TypeFlags.Object |
|
||||
ts.TypeFlags.Union |
|
||||
ts.TypeFlags.Intersection;
|
||||
function isTypeReferenceType(type) {
|
||||
if ((type.flags & ObjectFlagsType) === 0) {
|
||||
return false;
|
||||
}
|
||||
const objectTypeFlags = type.objectFlags;
|
||||
return (objectTypeFlags & ts.ObjectFlags.Reference) !== 0;
|
||||
}
|
||||
/**
|
||||
* @returns true if the type is `any`
|
||||
*/
|
||||
function isTypeAnyType(type) {
|
||||
if ((0, typeFlagUtils_1.isTypeFlagSet)(type, ts.TypeFlags.Any)) {
|
||||
if (type.intrinsicName === 'error') {
|
||||
log('Found an "error" any type');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* @returns true if the type is `any[]`
|
||||
*/
|
||||
function isTypeAnyArrayType(type, checker) {
|
||||
return (checker.isArrayType(type) &&
|
||||
isTypeAnyType(checker.getTypeArguments(type)[0]));
|
||||
}
|
||||
/**
|
||||
* @returns true if the type is `unknown[]`
|
||||
*/
|
||||
function isTypeUnknownArrayType(type, checker) {
|
||||
return (checker.isArrayType(type) &&
|
||||
isTypeUnknownType(checker.getTypeArguments(type)[0]));
|
||||
}
|
||||
/**
|
||||
* @returns Whether a type is an instance of the parent type, including for the parent's base types.
|
||||
*/
|
||||
function typeIsOrHasBaseType(type, parentType) {
|
||||
const parentSymbol = parentType.getSymbol();
|
||||
if (!type.getSymbol() || !parentSymbol) {
|
||||
return false;
|
||||
}
|
||||
const typeAndBaseTypes = [type];
|
||||
const ancestorTypes = type.getBaseTypes();
|
||||
if (ancestorTypes) {
|
||||
typeAndBaseTypes.push(...ancestorTypes);
|
||||
}
|
||||
for (const baseType of typeAndBaseTypes) {
|
||||
const baseSymbol = baseType.getSymbol();
|
||||
if (baseSymbol?.name === parentSymbol.name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function isTypeBigIntLiteralType(type) {
|
||||
return (0, typeFlagUtils_1.isTypeFlagSet)(type, ts.TypeFlags.BigIntLiteral);
|
||||
}
|
||||
function isTypeTemplateLiteralType(type) {
|
||||
return (0, typeFlagUtils_1.isTypeFlagSet)(type, ts.TypeFlags.TemplateLiteral);
|
||||
}
|
||||
@@ -0,0 +1,493 @@
|
||||
/* eslint no-param-reassign: 0 -- stylistic choice */
|
||||
|
||||
import TokenTranslator from "./token-translator.js";
|
||||
import { normalizeOptions } from "./options.js";
|
||||
|
||||
/**
|
||||
* @import {
|
||||
* CommentType,
|
||||
* EspreeParserCtor,
|
||||
* EsprimaNode,
|
||||
* AcornJsxParserCtorEnhanced,
|
||||
* TokTypes
|
||||
* } from "./types.js";
|
||||
* @import {
|
||||
* Options,
|
||||
* EspreeToken as EsprimaToken,
|
||||
* EspreeTokens as EsprimaTokens,
|
||||
* EspreeComment as EsprimaComment
|
||||
* } from "../espree.js";
|
||||
* @import { NormalizedEcmaVersion } from "./options.js";
|
||||
* @import * as acorn from "acorn";
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* originalSourceType: "script" | "module" | "commonjs" | undefined
|
||||
* tokens: EsprimaToken[] | null,
|
||||
* comments: EsprimaComment[] | null,
|
||||
* impliedStrict: boolean,
|
||||
* ecmaVersion: NormalizedEcmaVersion,
|
||||
* jsxAttrValueToken: boolean,
|
||||
* lastToken: acorn.Token | null,
|
||||
* templateElements: acorn.TemplateElement[]
|
||||
* }} State
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* sourceType?: "script"|"module"|"commonjs";
|
||||
* comments?: EsprimaComment[];
|
||||
* tokens?: EsprimaToken[];
|
||||
* body: acorn.Node[];
|
||||
* } & acorn.Program} EsprimaProgramNode
|
||||
*/
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Types exported from file
|
||||
// ----------------------------------------------------------------------------
|
||||
/**
|
||||
* @typedef {{
|
||||
* index?: number;
|
||||
* lineNumber?: number;
|
||||
* column?: number;
|
||||
* } & SyntaxError} EnhancedSyntaxError
|
||||
*/
|
||||
|
||||
// We add `jsxAttrValueToken` ourselves.
|
||||
/**
|
||||
* @typedef {{
|
||||
* jsxAttrValueToken?: acorn.TokenType;
|
||||
* } & TokTypes} EnhancedTokTypes
|
||||
*/
|
||||
|
||||
const STATE = Symbol("espree's internal state");
|
||||
const ESPRIMA_FINISH_NODE = Symbol("espree's esprimaFinishNode");
|
||||
|
||||
/**
|
||||
* Converts an Acorn comment to a Esprima comment.
|
||||
* @param {boolean} block True if it's a block comment, false if not.
|
||||
* @param {string} text The text of the comment.
|
||||
* @param {number} start The index at which the comment starts.
|
||||
* @param {number} end The index at which the comment ends.
|
||||
* @param {acorn.Position | undefined} startLoc The location at which the comment starts.
|
||||
* @param {acorn.Position | undefined} endLoc The location at which the comment ends.
|
||||
* @param {string} code The source code being parsed.
|
||||
* @returns {EsprimaComment} The comment object.
|
||||
* @private
|
||||
*/
|
||||
function convertAcornCommentToEsprimaComment(
|
||||
block,
|
||||
text,
|
||||
start,
|
||||
end,
|
||||
startLoc,
|
||||
endLoc,
|
||||
code,
|
||||
) {
|
||||
/** @type {CommentType} */
|
||||
let type;
|
||||
|
||||
if (block) {
|
||||
type = "Block";
|
||||
} else if (code.slice(start, start + 2) === "#!") {
|
||||
type = "Hashbang";
|
||||
} else {
|
||||
type = "Line";
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {{
|
||||
* type: CommentType,
|
||||
* value: string,
|
||||
* start?: number,
|
||||
* end?: number,
|
||||
* range?: [number, number],
|
||||
* loc?: {
|
||||
* start: acorn.Position | undefined,
|
||||
* end: acorn.Position | undefined
|
||||
* }
|
||||
* }}
|
||||
*/
|
||||
const comment = {
|
||||
type,
|
||||
value: text,
|
||||
};
|
||||
|
||||
if (typeof start === "number") {
|
||||
comment.start = start;
|
||||
comment.end = end;
|
||||
comment.range = [start, end];
|
||||
}
|
||||
|
||||
if (typeof startLoc === "object") {
|
||||
comment.loc = {
|
||||
start: startLoc,
|
||||
end: endLoc,
|
||||
};
|
||||
}
|
||||
|
||||
return comment;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line arrow-body-style -- For TS
|
||||
export default () => {
|
||||
/**
|
||||
* Returns the Espree parser.
|
||||
* @param {AcornJsxParserCtorEnhanced} Parser The Acorn parser. The `acorn` property is missing from acorn's
|
||||
* TypeScript but is present statically on the class.
|
||||
* @returns {EspreeParserCtor} The Espree Parser constructor.
|
||||
*/
|
||||
return Parser => {
|
||||
const tokTypes = /** @type {EnhancedTokTypes} */ (
|
||||
Object.assign({}, Parser.acorn.tokTypes)
|
||||
);
|
||||
|
||||
if (Parser.acornJsx) {
|
||||
Object.assign(tokTypes, Parser.acornJsx.tokTypes);
|
||||
}
|
||||
|
||||
return class Espree extends Parser {
|
||||
/**
|
||||
* @param {Options | null | undefined} opts The parser options
|
||||
* @param {string | object} code The code which will be converted to a string.
|
||||
*/
|
||||
constructor(opts, code) {
|
||||
if (typeof opts !== "object" || opts === null) {
|
||||
opts = {};
|
||||
}
|
||||
if (typeof code !== "string" && !(code instanceof String)) {
|
||||
code = String(code);
|
||||
}
|
||||
|
||||
// save original source type in case of commonjs
|
||||
const originalSourceType = opts.sourceType;
|
||||
const options = normalizeOptions(opts);
|
||||
const ecmaFeatures = options.ecmaFeatures || {};
|
||||
const tokenTranslator =
|
||||
options.tokens === true
|
||||
? new TokenTranslator(
|
||||
tokTypes,
|
||||
|
||||
// @ts-expect-error Appears to be a TS bug since the type is indeed string|String
|
||||
code,
|
||||
)
|
||||
: null;
|
||||
|
||||
/**
|
||||
* Data that is unique to Espree and is not represented internally
|
||||
* in Acorn.
|
||||
*
|
||||
* For ES2023 hashbangs, Espree will call `onComment()` during the
|
||||
* constructor, so we must define state before having access to
|
||||
* `this`.
|
||||
* @type {State}
|
||||
*/
|
||||
const state = {
|
||||
originalSourceType:
|
||||
originalSourceType || options.sourceType,
|
||||
tokens: tokenTranslator ? [] : null,
|
||||
comments: options.comment === true ? [] : null,
|
||||
impliedStrict:
|
||||
ecmaFeatures.impliedStrict === true &&
|
||||
options.ecmaVersion >= 5,
|
||||
ecmaVersion: options.ecmaVersion,
|
||||
jsxAttrValueToken: false,
|
||||
lastToken: null,
|
||||
templateElements: [],
|
||||
};
|
||||
|
||||
// Initialize acorn parser.
|
||||
super(
|
||||
{
|
||||
// do not use spread, because we don't want to pass any unknown options to acorn
|
||||
ecmaVersion: options.ecmaVersion,
|
||||
sourceType: options.sourceType,
|
||||
ranges: options.ranges,
|
||||
locations: options.locations,
|
||||
allowReserved: options.allowReserved,
|
||||
|
||||
// Truthy value is true for backward compatibility.
|
||||
allowReturnOutsideFunction:
|
||||
options.allowReturnOutsideFunction,
|
||||
|
||||
// Collect tokens
|
||||
onToken(token) {
|
||||
if (tokenTranslator) {
|
||||
// Use `tokens`, `ecmaVersion`, and `jsxAttrValueToken` in the state.
|
||||
tokenTranslator.onToken(
|
||||
token,
|
||||
|
||||
/**
|
||||
* @type {Omit<State, "tokens"> & {
|
||||
* tokens: EsprimaToken[]
|
||||
* }}
|
||||
*/
|
||||
(state),
|
||||
);
|
||||
}
|
||||
if (token.type !== tokTypes.eof) {
|
||||
state.lastToken = token;
|
||||
}
|
||||
},
|
||||
|
||||
// Collect comments
|
||||
onComment(block, text, start, end, startLoc, endLoc) {
|
||||
if (state.comments) {
|
||||
const comment =
|
||||
convertAcornCommentToEsprimaComment(
|
||||
block,
|
||||
text,
|
||||
start,
|
||||
end,
|
||||
startLoc,
|
||||
endLoc,
|
||||
|
||||
// @ts-expect-error Appears to be a TS bug
|
||||
// since the type is indeed string|String
|
||||
code,
|
||||
);
|
||||
|
||||
state.comments.push(comment);
|
||||
}
|
||||
},
|
||||
},
|
||||
// @ts-expect-error Appears to be a TS bug
|
||||
// since the type is indeed string|String
|
||||
code,
|
||||
);
|
||||
|
||||
/*
|
||||
* We put all of this data into a symbol property as a way to avoid
|
||||
* potential naming conflicts with future versions of Acorn.
|
||||
*/
|
||||
this[STATE] = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Espree tokens.
|
||||
* @returns {EsprimaTokens} The Esprima-compatible tokens
|
||||
*/
|
||||
tokenize() {
|
||||
do {
|
||||
this.next();
|
||||
} while (this.type !== tokTypes.eof);
|
||||
|
||||
// Consume the final eof token
|
||||
this.next();
|
||||
|
||||
const extra = this[STATE];
|
||||
const tokens = /** @type {EsprimaTokens} */ (extra.tokens);
|
||||
|
||||
if (extra.comments) {
|
||||
tokens.comments = extra.comments;
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls parent.
|
||||
* @param {acorn.Node} node The node
|
||||
* @param {string} type The type
|
||||
* @returns {acorn.Node} The altered Node
|
||||
*/
|
||||
finishNode(node, type) {
|
||||
const result = super.finishNode(node, type);
|
||||
|
||||
return this[ESPRIMA_FINISH_NODE](result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls parent.
|
||||
* @param {acorn.Node} node The node
|
||||
* @param {string} type The type
|
||||
* @param {number} pos The position
|
||||
* @param {acorn.Position} loc The location
|
||||
* @returns {acorn.Node} The altered Node
|
||||
*/
|
||||
finishNodeAt(node, type, pos, loc) {
|
||||
const result = super.finishNodeAt(node, type, pos, loc);
|
||||
|
||||
return this[ESPRIMA_FINISH_NODE](result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses.
|
||||
* @returns {EsprimaProgramNode} The program Node
|
||||
*/
|
||||
parse() {
|
||||
const extra = this[STATE];
|
||||
const prog = super.parse();
|
||||
|
||||
const program = /** @type {EsprimaProgramNode} */ (prog);
|
||||
|
||||
// @ts-expect-error TS bug? We've already converted to `EsprimaProgramNode`
|
||||
program.sourceType = extra.originalSourceType;
|
||||
|
||||
if (extra.comments) {
|
||||
program.comments = extra.comments;
|
||||
}
|
||||
if (extra.tokens) {
|
||||
program.tokens = extra.tokens;
|
||||
}
|
||||
|
||||
/*
|
||||
* https://github.com/eslint/espree/issues/349
|
||||
* Ensure that template elements have correct range information.
|
||||
* This is one location where Acorn produces a different value
|
||||
* for its start and end properties vs. the values present in the
|
||||
* range property. In order to avoid confusion, we set the start
|
||||
* and end properties to the values that are present in range.
|
||||
* This is done here, instead of in finishNode(), because Acorn
|
||||
* uses the values of start and end internally while parsing, making
|
||||
* it dangerous to change those values while parsing is ongoing.
|
||||
* By waiting until the end of parsing, we can safely change these
|
||||
* values without affect any other part of the process.
|
||||
*/
|
||||
this[STATE].templateElements.forEach(templateElement => {
|
||||
const startOffset = -1;
|
||||
const endOffset = templateElement.tail ? 1 : 2;
|
||||
|
||||
templateElement.start += startOffset;
|
||||
templateElement.end += endOffset;
|
||||
|
||||
if (templateElement.range) {
|
||||
templateElement.range[0] += startOffset;
|
||||
templateElement.range[1] += endOffset;
|
||||
}
|
||||
|
||||
if (templateElement.loc) {
|
||||
templateElement.loc.start.column += startOffset;
|
||||
templateElement.loc.end.column += endOffset;
|
||||
}
|
||||
});
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses top level.
|
||||
* @param {acorn.Node} node AST Node
|
||||
* @returns {acorn.Node} The changed node
|
||||
*/
|
||||
parseTopLevel(node) {
|
||||
if (this[STATE].impliedStrict) {
|
||||
this.strict = true;
|
||||
}
|
||||
return super.parseTopLevel(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the default raise method to throw Esprima-style errors.
|
||||
* @param {number} pos The position of the error.
|
||||
* @param {string} message The error message.
|
||||
* @throws {EnhancedSyntaxError} A syntax error.
|
||||
* @returns {void}
|
||||
*/
|
||||
raise(pos, message) {
|
||||
const loc = Parser.acorn.getLineInfo(this.input, pos);
|
||||
const err = /** @type {EnhancedSyntaxError} */ (
|
||||
new SyntaxError(message)
|
||||
);
|
||||
|
||||
err.index = pos;
|
||||
err.lineNumber = loc.line;
|
||||
err.column = loc.column + 1; // acorn uses 0-based columns
|
||||
throw err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the default raise method to throw Esprima-style errors.
|
||||
* @param {number} pos The position of the error.
|
||||
* @param {string} message The error message.
|
||||
* @throws {SyntaxError} A syntax error.
|
||||
* @returns {void}
|
||||
*/
|
||||
raiseRecoverable(pos, message) {
|
||||
this.raise(pos, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the default unexpected method to throw Esprima-style errors.
|
||||
* @param {number} pos The position of the error.
|
||||
* @throws {SyntaxError} A syntax error.
|
||||
* @returns {void}
|
||||
*/
|
||||
unexpected(pos) {
|
||||
let message = "Unexpected token";
|
||||
|
||||
if (pos !== null && pos !== void 0) {
|
||||
this.pos = pos;
|
||||
|
||||
if (this.options.locations) {
|
||||
while (this.pos < this.lineStart) {
|
||||
this.lineStart =
|
||||
this.input.lastIndexOf(
|
||||
"\n",
|
||||
this.lineStart - 2,
|
||||
) + 1;
|
||||
--this.curLine;
|
||||
}
|
||||
}
|
||||
|
||||
this.nextToken();
|
||||
}
|
||||
|
||||
if (this.end > this.start) {
|
||||
message += ` ${this.input.slice(this.start, this.end)}`;
|
||||
}
|
||||
|
||||
this.raise(this.start, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Esprima-FB represents JSX strings as tokens called "JSXText", but Acorn-JSX
|
||||
* uses regular tt.string without any distinction between this and regular JS
|
||||
* strings. As such, we intercept an attempt to read a JSX string and set a flag
|
||||
* on extra so that when tokens are converted, the next token will be switched
|
||||
* to JSXText via onToken.
|
||||
* @param {number} quote A character code
|
||||
* @returns {void}
|
||||
*/ // eslint-disable-next-line camelcase -- required by API
|
||||
jsx_readString(quote) {
|
||||
const result = super.jsx_readString(quote);
|
||||
|
||||
if (this.type === tokTypes.string) {
|
||||
this[STATE].jsxAttrValueToken = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs last-minute Esprima-specific compatibility checks and fixes.
|
||||
* @param {acorn.Node} result The node to check.
|
||||
* @returns {EsprimaNode} The finished node.
|
||||
*/
|
||||
[ESPRIMA_FINISH_NODE](result) {
|
||||
// Acorn doesn't count the opening and closing backticks as part of templates
|
||||
// so we have to adjust ranges/locations appropriately.
|
||||
if (result.type === "TemplateElement") {
|
||||
// save template element references to fix start/end later
|
||||
this[STATE].templateElements.push(
|
||||
/** @type {acorn.TemplateElement} */
|
||||
(result),
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
result.type.includes("Function") &&
|
||||
!("generator" in result)
|
||||
) {
|
||||
/**
|
||||
* @type {acorn.FunctionDeclaration|acorn.FunctionExpression|
|
||||
* acorn.ArrowFunctionExpression}
|
||||
*/
|
||||
(result).generator = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
function tsRewriteRelativeImportExtensions(t, e) {
|
||||
return "string" == typeof t && /^\.\.?\//.test(t) ? t.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+)?)\.([cm]?)ts$/i, function (t, s, r, n, o) {
|
||||
return s ? e ? ".jsx" : ".js" : !r || n && o ? r + n + "." + o.toLowerCase() + "js" : t;
|
||||
}) : t;
|
||||
}
|
||||
module.exports = tsRewriteRelativeImportExtensions, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
||||
@@ -0,0 +1,5 @@
|
||||
'use strict'
|
||||
|
||||
const SemVer = require('../classes/semver')
|
||||
const major = (a, loose) => new SemVer(a, loose).major
|
||||
module.exports = major
|
||||
@@ -0,0 +1,78 @@
|
||||
import type { IssueData, ZodErrorMap, ZodIssue } from "../ZodError.cjs";
|
||||
import type { ZodParsedType } from "./util.cjs";
|
||||
export declare const makeIssue: (params: {
|
||||
data: any;
|
||||
path: (string | number)[];
|
||||
errorMaps: ZodErrorMap[];
|
||||
issueData: IssueData;
|
||||
}) => ZodIssue;
|
||||
export type ParseParams = {
|
||||
path: (string | number)[];
|
||||
errorMap: ZodErrorMap;
|
||||
async: boolean;
|
||||
};
|
||||
export type ParsePathComponent = string | number;
|
||||
export type ParsePath = ParsePathComponent[];
|
||||
export declare const EMPTY_PATH: ParsePath;
|
||||
export interface ParseContext {
|
||||
readonly common: {
|
||||
readonly issues: ZodIssue[];
|
||||
readonly contextualErrorMap?: ZodErrorMap | undefined;
|
||||
readonly async: boolean;
|
||||
};
|
||||
readonly path: ParsePath;
|
||||
readonly schemaErrorMap?: ZodErrorMap | undefined;
|
||||
readonly parent: ParseContext | null;
|
||||
readonly data: any;
|
||||
readonly parsedType: ZodParsedType;
|
||||
}
|
||||
export type ParseInput = {
|
||||
data: any;
|
||||
path: (string | number)[];
|
||||
parent: ParseContext;
|
||||
};
|
||||
export declare function addIssueToContext(ctx: ParseContext, issueData: IssueData): void;
|
||||
export type ObjectPair = {
|
||||
key: SyncParseReturnType<any>;
|
||||
value: SyncParseReturnType<any>;
|
||||
};
|
||||
export declare class ParseStatus {
|
||||
value: "aborted" | "dirty" | "valid";
|
||||
dirty(): void;
|
||||
abort(): void;
|
||||
static mergeArray(status: ParseStatus, results: SyncParseReturnType<any>[]): SyncParseReturnType;
|
||||
static mergeObjectAsync(status: ParseStatus, pairs: {
|
||||
key: ParseReturnType<any>;
|
||||
value: ParseReturnType<any>;
|
||||
}[]): Promise<SyncParseReturnType<any>>;
|
||||
static mergeObjectSync(status: ParseStatus, pairs: {
|
||||
key: SyncParseReturnType<any>;
|
||||
value: SyncParseReturnType<any>;
|
||||
alwaysSet?: boolean;
|
||||
}[]): SyncParseReturnType;
|
||||
}
|
||||
export interface ParseResult {
|
||||
status: "aborted" | "dirty" | "valid";
|
||||
data: any;
|
||||
}
|
||||
export type INVALID = {
|
||||
status: "aborted";
|
||||
};
|
||||
export declare const INVALID: INVALID;
|
||||
export type DIRTY<T> = {
|
||||
status: "dirty";
|
||||
value: T;
|
||||
};
|
||||
export declare const DIRTY: <T>(value: T) => DIRTY<T>;
|
||||
export type OK<T> = {
|
||||
status: "valid";
|
||||
value: T;
|
||||
};
|
||||
export declare const OK: <T>(value: T) => OK<T>;
|
||||
export type SyncParseReturnType<T = any> = OK<T> | DIRTY<T> | INVALID;
|
||||
export type AsyncParseReturnType<T> = Promise<SyncParseReturnType<T>>;
|
||||
export type ParseReturnType<T> = SyncParseReturnType<T> | AsyncParseReturnType<T>;
|
||||
export declare const isAborted: (x: ParseReturnType<any>) => x is INVALID;
|
||||
export declare const isDirty: <T>(x: ParseReturnType<T>) => x is OK<T> | DIRTY<T>;
|
||||
export declare const isValid: <T>(x: ParseReturnType<T>) => x is OK<T>;
|
||||
export declare const isAsync: <T>(x: ParseReturnType<T>) => x is AsyncParseReturnType<T>;
|
||||
@@ -0,0 +1,12 @@
|
||||
import crypto from 'crypto';
|
||||
const rnds8Pool = new Uint8Array(256); // # of random values to pre-allocate
|
||||
|
||||
let poolPtr = rnds8Pool.length;
|
||||
export default function rng() {
|
||||
if (poolPtr > rnds8Pool.length - 16) {
|
||||
crypto.randomFillSync(rnds8Pool);
|
||||
poolPtr = 0;
|
||||
}
|
||||
|
||||
return rnds8Pool.slice(poolPtr, poolPtr += 16);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
function _iterable_to_array(iter) {
|
||||
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) {
|
||||
return Array.from(iter);
|
||||
}
|
||||
}
|
||||
exports._ = _iterable_to_array;
|
||||
@@ -0,0 +1,237 @@
|
||||
'use strict'
|
||||
|
||||
//Parse method copied from https://github.com/brianc/node-postgres
|
||||
//Copyright (c) 2010-2014 Brian Carlson (brian.m.carlson@gmail.com)
|
||||
//MIT License
|
||||
|
||||
//parses a connection string
|
||||
function parse(str, options = {}) {
|
||||
//unix socket
|
||||
if (str.charAt(0) === '/') {
|
||||
const config = str.split(' ')
|
||||
return { host: config[0], database: config[1] }
|
||||
}
|
||||
|
||||
// Check for empty host in URL
|
||||
|
||||
const config = Object.create(null)
|
||||
let result
|
||||
let dummyHost = false
|
||||
if (/ |%[^a-f0-9]|%[a-f0-9][^a-f0-9]/i.test(str)) {
|
||||
// Ensure spaces are encoded as %20
|
||||
str = encodeURI(str).replace(/%25(\d\d)/g, '%$1')
|
||||
}
|
||||
|
||||
try {
|
||||
try {
|
||||
result = new URL(str, 'postgres://base')
|
||||
} catch (e) {
|
||||
// The URL is invalid so try again with a dummy host
|
||||
result = new URL(str.replace('@/', '@___DUMMY___/'), 'postgres://base')
|
||||
dummyHost = true
|
||||
}
|
||||
} catch (err) {
|
||||
// Remove the input from the error message to avoid leaking sensitive information
|
||||
err.input && (err.input = '*****REDACTED*****')
|
||||
throw err
|
||||
}
|
||||
|
||||
// We'd like to use Object.fromEntries() here but Node.js 10 does not support it
|
||||
for (const entry of result.searchParams.entries()) {
|
||||
config[entry[0]] = entry[1]
|
||||
}
|
||||
|
||||
config.user = config.user || decodeURIComponent(result.username)
|
||||
config.password = config.password || decodeURIComponent(result.password)
|
||||
|
||||
if (result.protocol == 'socket:') {
|
||||
config.host = decodeURI(result.pathname)
|
||||
config.database = result.searchParams.get('db')
|
||||
config.client_encoding = result.searchParams.get('encoding')
|
||||
return config
|
||||
}
|
||||
const hostname = dummyHost ? '' : result.hostname
|
||||
if (!config.host) {
|
||||
// Only set the host if there is no equivalent query param.
|
||||
config.host = decodeURIComponent(hostname)
|
||||
} else if (hostname && /^%2f/i.test(hostname)) {
|
||||
// Only prepend the hostname to the pathname if it is not a URL encoded Unix socket host.
|
||||
result.pathname = hostname + result.pathname
|
||||
}
|
||||
if (!config.port) {
|
||||
// Only set the port if there is no equivalent query param.
|
||||
config.port = result.port
|
||||
}
|
||||
|
||||
const pathname = result.pathname.slice(1) || null
|
||||
config.database = pathname ? decodeURI(pathname) : null
|
||||
|
||||
if (config.ssl === 'true' || config.ssl === '1') {
|
||||
config.ssl = true
|
||||
}
|
||||
|
||||
if (config.ssl === '0') {
|
||||
config.ssl = false
|
||||
}
|
||||
|
||||
if (config.sslcert || config.sslkey || config.sslrootcert || config.sslmode) {
|
||||
config.ssl = {}
|
||||
}
|
||||
|
||||
// sslnegotiation=direct implies SSL is in use (libpq requires sslmode>=require),
|
||||
// so enable SSL if the connection string did not otherwise configure it.
|
||||
if (config.sslnegotiation === 'direct' && config.ssl === undefined) {
|
||||
config.ssl = true
|
||||
}
|
||||
|
||||
// Only try to load fs if we expect to read from the disk
|
||||
const fs = config.sslcert || config.sslkey || config.sslrootcert ? require('fs') : null
|
||||
|
||||
if (config.sslcert) {
|
||||
config.ssl.cert = fs.readFileSync(config.sslcert).toString()
|
||||
}
|
||||
|
||||
if (config.sslkey) {
|
||||
config.ssl.key = fs.readFileSync(config.sslkey).toString()
|
||||
}
|
||||
|
||||
if (config.sslrootcert) {
|
||||
config.ssl.ca = fs.readFileSync(config.sslrootcert).toString()
|
||||
}
|
||||
|
||||
if (options.useLibpqCompat && config.uselibpqcompat) {
|
||||
throw new Error('Both useLibpqCompat and uselibpqcompat are set. Please use only one of them.')
|
||||
}
|
||||
|
||||
if (config.uselibpqcompat === 'true' || options.useLibpqCompat) {
|
||||
switch (config.sslmode) {
|
||||
case 'disable': {
|
||||
config.ssl = false
|
||||
break
|
||||
}
|
||||
case 'prefer': {
|
||||
config.ssl.rejectUnauthorized = false
|
||||
break
|
||||
}
|
||||
case 'require': {
|
||||
if (config.sslrootcert) {
|
||||
// If a root CA is specified, behavior of `sslmode=require` will be the same as that of `verify-ca`
|
||||
config.ssl.checkServerIdentity = function () {}
|
||||
} else {
|
||||
config.ssl.rejectUnauthorized = false
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'verify-ca': {
|
||||
if (!config.ssl.ca) {
|
||||
throw new Error(
|
||||
'SECURITY WARNING: Using sslmode=verify-ca requires specifying a CA with sslrootcert. If a public CA is used, verify-ca allows connections to a server that somebody else may have registered with the CA, making you vulnerable to Man-in-the-Middle attacks. Either specify a custom CA certificate with sslrootcert parameter or use sslmode=verify-full for proper security.'
|
||||
)
|
||||
}
|
||||
config.ssl.checkServerIdentity = function () {}
|
||||
break
|
||||
}
|
||||
case 'verify-full': {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (config.sslmode) {
|
||||
case 'disable': {
|
||||
config.ssl = false
|
||||
break
|
||||
}
|
||||
case 'prefer':
|
||||
case 'require':
|
||||
case 'verify-ca':
|
||||
case 'verify-full': {
|
||||
if (config.sslmode !== 'verify-full') {
|
||||
deprecatedSslModeWarning(config.sslmode)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'no-verify': {
|
||||
config.ssl.rejectUnauthorized = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
// convert pg-connection-string ssl config to a ClientConfig.ConnectionOptions
|
||||
function toConnectionOptions(sslConfig) {
|
||||
const connectionOptions = Object.entries(sslConfig).reduce((c, [key, value]) => {
|
||||
// we explicitly check for undefined and null instead of `if (value)` because some
|
||||
// options accept falsy values. Example: `ssl.rejectUnauthorized = false`
|
||||
if (value !== undefined && value !== null) {
|
||||
c[key] = value
|
||||
}
|
||||
|
||||
return c
|
||||
}, Object.create(null))
|
||||
|
||||
return connectionOptions
|
||||
}
|
||||
|
||||
// convert pg-connection-string config to a ClientConfig
|
||||
function toClientConfig(config) {
|
||||
const poolConfig = Object.entries(config).reduce((c, [key, value]) => {
|
||||
if (key === 'ssl') {
|
||||
const sslConfig = value
|
||||
|
||||
if (typeof sslConfig === 'boolean') {
|
||||
c[key] = sslConfig
|
||||
}
|
||||
|
||||
if (typeof sslConfig === 'object') {
|
||||
c[key] = toConnectionOptions(sslConfig)
|
||||
}
|
||||
} else if (value !== undefined && value !== null) {
|
||||
if (key === 'port') {
|
||||
// when port is not specified, it is converted into an empty string
|
||||
// we want to avoid NaN or empty string as a values in ClientConfig
|
||||
if (value !== '') {
|
||||
const v = parseInt(value, 10)
|
||||
if (isNaN(v)) {
|
||||
throw new Error(`Invalid ${key}: ${value}`)
|
||||
}
|
||||
|
||||
c[key] = v
|
||||
}
|
||||
} else {
|
||||
c[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
return c
|
||||
}, Object.create(null))
|
||||
|
||||
return poolConfig
|
||||
}
|
||||
|
||||
// parses a connection string into ClientConfig
|
||||
function parseIntoClientConfig(str) {
|
||||
return toClientConfig(parse(str))
|
||||
}
|
||||
|
||||
function deprecatedSslModeWarning(sslmode) {
|
||||
if (!deprecatedSslModeWarning.warned && typeof process !== 'undefined' && process.emitWarning) {
|
||||
deprecatedSslModeWarning.warned = true
|
||||
process.emitWarning(`SECURITY WARNING: The SSL modes 'prefer', 'require', and 'verify-ca' are treated as aliases for 'verify-full'.
|
||||
In the next major version (pg-connection-string v3.0.0 and pg v9.0.0), these modes will adopt standard libpq semantics, which have weaker security guarantees.
|
||||
|
||||
To prepare for this change:
|
||||
- If you want the current behavior, explicitly use 'sslmode=verify-full'
|
||||
- If you want libpq compatibility now, use 'uselibpqcompat=true&sslmode=${sslmode}'
|
||||
|
||||
See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode definitions.`)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = parse
|
||||
|
||||
parse.parse = parse
|
||||
parse.toClientConfig = toClientConfig
|
||||
parse.parseIntoClientConfig = parseIntoClientConfig
|
||||
@@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
// THIS CODE WAS AUTOMATICALLY GENERATED
|
||||
// DO NOT EDIT THIS CODE BY HAND
|
||||
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
|
||||
// npx nx generate-lib repo
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.es2019_string = void 0;
|
||||
const base_config_1 = require("./base-config");
|
||||
exports.es2019_string = {
|
||||
libs: [],
|
||||
variables: [['String', base_config_1.TYPE]],
|
||||
};
|
||||
@@ -0,0 +1,241 @@
|
||||
"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"));
|
||||
const error = () => {
|
||||
// Hebrew labels + grammatical gender
|
||||
const TypeNames = {
|
||||
string: { label: "מחרוזת", gender: "f" },
|
||||
number: { label: "מספר", gender: "m" },
|
||||
boolean: { label: "ערך בוליאני", gender: "m" },
|
||||
bigint: { label: "BigInt", gender: "m" },
|
||||
date: { label: "תאריך", gender: "m" },
|
||||
array: { label: "מערך", gender: "m" },
|
||||
object: { label: "אובייקט", gender: "m" },
|
||||
null: { label: "ערך ריק (null)", gender: "m" },
|
||||
undefined: { label: "ערך לא מוגדר (undefined)", gender: "m" },
|
||||
symbol: { label: "סימבול (Symbol)", gender: "m" },
|
||||
function: { label: "פונקציה", gender: "f" },
|
||||
map: { label: "מפה (Map)", gender: "f" },
|
||||
set: { label: "קבוצה (Set)", gender: "f" },
|
||||
file: { label: "קובץ", gender: "m" },
|
||||
promise: { label: "Promise", gender: "m" },
|
||||
NaN: { label: "NaN", gender: "m" },
|
||||
unknown: { label: "ערך לא ידוע", gender: "m" },
|
||||
value: { label: "ערך", gender: "m" },
|
||||
};
|
||||
// Sizing units for size-related messages + localized origin labels
|
||||
const Sizable = {
|
||||
string: { unit: "תווים", shortLabel: "קצר", longLabel: "ארוך" },
|
||||
file: { unit: "בייטים", shortLabel: "קטן", longLabel: "גדול" },
|
||||
array: { unit: "פריטים", shortLabel: "קטן", longLabel: "גדול" },
|
||||
set: { unit: "פריטים", shortLabel: "קטן", longLabel: "גדול" },
|
||||
number: { unit: "", shortLabel: "קטן", longLabel: "גדול" }, // no unit
|
||||
};
|
||||
// Helpers — labels, articles, and verbs
|
||||
const typeEntry = (t) => (t ? TypeNames[t] : undefined);
|
||||
const typeLabel = (t) => {
|
||||
const e = typeEntry(t);
|
||||
if (e)
|
||||
return e.label;
|
||||
// fallback: show raw string if unknown
|
||||
return t ?? TypeNames.unknown.label;
|
||||
};
|
||||
const withDefinite = (t) => `ה${typeLabel(t)}`;
|
||||
const verbFor = (t) => {
|
||||
const e = typeEntry(t);
|
||||
const gender = e?.gender ?? "m";
|
||||
return gender === "f" ? "צריכה להיות" : "צריך להיות";
|
||||
};
|
||||
const getSizing = (origin) => {
|
||||
if (!origin)
|
||||
return null;
|
||||
return Sizable[origin] ?? null;
|
||||
};
|
||||
const FormatDictionary = {
|
||||
regex: { label: "קלט", gender: "m" },
|
||||
email: { label: "כתובת אימייל", gender: "f" },
|
||||
url: { label: "כתובת רשת", gender: "f" },
|
||||
emoji: { label: "אימוג'י", gender: "m" },
|
||||
uuid: { label: "UUID", gender: "m" },
|
||||
nanoid: { label: "nanoid", gender: "m" },
|
||||
guid: { label: "GUID", gender: "m" },
|
||||
cuid: { label: "cuid", gender: "m" },
|
||||
cuid2: { label: "cuid2", gender: "m" },
|
||||
ulid: { label: "ULID", gender: "m" },
|
||||
xid: { label: "XID", gender: "m" },
|
||||
ksuid: { label: "KSUID", gender: "m" },
|
||||
datetime: { label: "תאריך וזמן ISO", gender: "m" },
|
||||
date: { label: "תאריך ISO", gender: "m" },
|
||||
time: { label: "זמן ISO", gender: "m" },
|
||||
duration: { label: "משך זמן ISO", gender: "m" },
|
||||
ipv4: { label: "כתובת IPv4", gender: "f" },
|
||||
ipv6: { label: "כתובת IPv6", gender: "f" },
|
||||
cidrv4: { label: "טווח IPv4", gender: "m" },
|
||||
cidrv6: { label: "טווח IPv6", gender: "m" },
|
||||
base64: { label: "מחרוזת בבסיס 64", gender: "f" },
|
||||
base64url: { label: "מחרוזת בבסיס 64 לכתובות רשת", gender: "f" },
|
||||
json_string: { label: "מחרוזת JSON", gender: "f" },
|
||||
e164: { label: "מספר E.164", gender: "m" },
|
||||
jwt: { label: "JWT", gender: "m" },
|
||||
ends_with: { label: "קלט", gender: "m" },
|
||||
includes: { label: "קלט", gender: "m" },
|
||||
lowercase: { label: "קלט", gender: "m" },
|
||||
starts_with: { label: "קלט", gender: "m" },
|
||||
uppercase: { label: "קלט", gender: "m" },
|
||||
};
|
||||
const TypeDictionary = {
|
||||
nan: "NaN",
|
||||
};
|
||||
return (issue) => {
|
||||
switch (issue.code) {
|
||||
case "invalid_type": {
|
||||
// Expected type: show without definite article for clearer Hebrew
|
||||
const expectedKey = issue.expected;
|
||||
const expected = TypeDictionary[expectedKey ?? ""] ?? typeLabel(expectedKey);
|
||||
// Received: show localized label if known, otherwise constructor/raw
|
||||
const receivedType = util.parsedType(issue.input);
|
||||
const received = TypeDictionary[receivedType] ?? TypeNames[receivedType]?.label ?? 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])}`;
|
||||
}
|
||||
// Join values with proper Hebrew formatting
|
||||
const stringified = issue.values.map((v) => util.stringifyPrimitive(v));
|
||||
if (issue.values.length === 2) {
|
||||
return `ערך לא תקין: האפשרויות המתאימות הן ${stringified[0]} או ${stringified[1]}`;
|
||||
}
|
||||
// For 3+ values: "a", "b" או "c"
|
||||
const lastValue = stringified[stringified.length - 1];
|
||||
const restValues = stringified.slice(0, -1).join(", ");
|
||||
return `ערך לא תקין: האפשרויות המתאימות הן ${restValues} או ${lastValue}`;
|
||||
}
|
||||
case "too_big": {
|
||||
const sizing = getSizing(issue.origin);
|
||||
const subject = withDefinite(issue.origin ?? "value");
|
||||
if (issue.origin === "string") {
|
||||
// Special handling for strings - more natural Hebrew
|
||||
return `${sizing?.longLabel ?? "ארוך"} מדי: ${subject} צריכה להכיל ${issue.maximum.toString()} ${sizing?.unit ?? ""} ${issue.inclusive ? "או פחות" : "לכל היותר"}`.trim();
|
||||
}
|
||||
if (issue.origin === "number") {
|
||||
// Natural Hebrew for numbers
|
||||
const comparison = issue.inclusive ? `קטן או שווה ל-${issue.maximum}` : `קטן מ-${issue.maximum}`;
|
||||
return `גדול מדי: ${subject} צריך להיות ${comparison}`;
|
||||
}
|
||||
if (issue.origin === "array" || issue.origin === "set") {
|
||||
// Natural Hebrew for arrays and sets
|
||||
const verb = issue.origin === "set" ? "צריכה" : "צריך";
|
||||
const comparison = issue.inclusive
|
||||
? `${issue.maximum} ${sizing?.unit ?? ""} או פחות`
|
||||
: `פחות מ-${issue.maximum} ${sizing?.unit ?? ""}`;
|
||||
return `גדול מדי: ${subject} ${verb} להכיל ${comparison}`.trim();
|
||||
}
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const be = verbFor(issue.origin ?? "value");
|
||||
if (sizing?.unit) {
|
||||
return `${sizing.longLabel} מדי: ${subject} ${be} ${adj}${issue.maximum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
return `${sizing?.longLabel ?? "גדול"} מדי: ${subject} ${be} ${adj}${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const sizing = getSizing(issue.origin);
|
||||
const subject = withDefinite(issue.origin ?? "value");
|
||||
if (issue.origin === "string") {
|
||||
// Special handling for strings - more natural Hebrew
|
||||
return `${sizing?.shortLabel ?? "קצר"} מדי: ${subject} צריכה להכיל ${issue.minimum.toString()} ${sizing?.unit ?? ""} ${issue.inclusive ? "או יותר" : "לפחות"}`.trim();
|
||||
}
|
||||
if (issue.origin === "number") {
|
||||
// Natural Hebrew for numbers
|
||||
const comparison = issue.inclusive ? `גדול או שווה ל-${issue.minimum}` : `גדול מ-${issue.minimum}`;
|
||||
return `קטן מדי: ${subject} צריך להיות ${comparison}`;
|
||||
}
|
||||
if (issue.origin === "array" || issue.origin === "set") {
|
||||
// Natural Hebrew for arrays and sets
|
||||
const verb = issue.origin === "set" ? "צריכה" : "צריך";
|
||||
// Special case for singular (minimum === 1)
|
||||
if (issue.minimum === 1 && issue.inclusive) {
|
||||
const singularPhrase = issue.origin === "set" ? "לפחות פריט אחד" : "לפחות פריט אחד";
|
||||
return `קטן מדי: ${subject} ${verb} להכיל ${singularPhrase}`;
|
||||
}
|
||||
const comparison = issue.inclusive
|
||||
? `${issue.minimum} ${sizing?.unit ?? ""} או יותר`
|
||||
: `יותר מ-${issue.minimum} ${sizing?.unit ?? ""}`;
|
||||
return `קטן מדי: ${subject} ${verb} להכיל ${comparison}`.trim();
|
||||
}
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const be = verbFor(issue.origin ?? "value");
|
||||
if (sizing?.unit) {
|
||||
return `${sizing.shortLabel} מדי: ${subject} ${be} ${adj}${issue.minimum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
return `${sizing?.shortLabel ?? "קטן"} מדי: ${subject} ${be} ${adj}${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue;
|
||||
// These apply to strings — use feminine grammar + ה׳ הידיעה
|
||||
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}`;
|
||||
// Handle gender agreement for formats
|
||||
const nounEntry = FormatDictionary[_issue.format];
|
||||
const noun = nounEntry?.label ?? _issue.format;
|
||||
const gender = nounEntry?.gender ?? "m";
|
||||
const adjective = gender === "f" ? "תקינה" : "תקין";
|
||||
return `${noun} לא ${adjective}`;
|
||||
}
|
||||
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 `שדה לא תקין באובייקט`;
|
||||
}
|
||||
case "invalid_union":
|
||||
return "קלט לא תקין";
|
||||
case "invalid_element": {
|
||||
const place = withDefinite(issue.origin ?? "array");
|
||||
return `ערך לא תקין ב${place}`;
|
||||
}
|
||||
default:
|
||||
return `קלט לא תקין`;
|
||||
}
|
||||
};
|
||||
};
|
||||
function default_1() {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
module.exports = exports.default;
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../src/api/node/protocol.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,eAAO,MAAM,sBAAsB,IAAI,CAAC;AACxC,eAAO,MAAM,sBAAsB,IAAI,CAAC;AACxC,eAAO,MAAM,sBAAsB,IAAI,CAAC;AACxC,eAAO,MAAM,sBAAsB,KAAK,CAAC;AACzC,eAAO,MAAM,sBAAsB,KAAK,CAAC;AACzC,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAC9C,eAAO,MAAM,kCAAkC,KAAK,CAAC;AACrD,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAC7C,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAC9C,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAChD,eAAO,MAAM,mBAAmB,KAAK,CAAC;AACtC,eAAO,MAAM,WAAW,KAAK,CAAC;AAE9B,eAAO,MAAM,QAAQ,KAAK,CAAC;AAE3B,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,eAAO,MAAM,gBAAgB,KAAK,CAAC;AACnC,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,gBAAgB,KAAK,CAAC;AACnC,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,eAAO,MAAM,cAAc,aAAa,CAAC;AAEzC,eAAO,MAAM,uBAAuB,IAAa,CAAC;AAClD,eAAO,MAAM,qBAAqB,aAAa,CAAC;AAChD,eAAO,MAAM,uBAAuB,aAAa,CAAC;AAElD,eAAO,MAAM,sBAAsB,WAAa,CAAC;AACjD,eAAO,MAAM,uBAAuB,WAAa,CAAC;AAGlD,OAAO,EAAE,eAAe,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC"}
|
||||
@@ -0,0 +1,4 @@
|
||||
function _readOnlyError(r) {
|
||||
throw new TypeError('"' + r + '" is read-only');
|
||||
}
|
||||
module.exports = _readOnlyError, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
||||
@@ -0,0 +1,483 @@
|
||||
function isMockFunction(fn) {
|
||||
return typeof fn === "function" && "_isMockFunction" in fn && fn._isMockFunction === true;
|
||||
}
|
||||
const MOCK_RESTORE = new Set();
|
||||
// Jest keeps the state in a separate WeakMap which is good for memory,
|
||||
// but it makes the state slower to access and return different values
|
||||
// if you stored it before calling `mockClear` where it will be recreated
|
||||
const REGISTERED_MOCKS = new Set();
|
||||
const MOCK_CONFIGS = new WeakMap();
|
||||
function createMockInstance(options = {}) {
|
||||
const { originalImplementation, restore, mockImplementation, resetToMockImplementation, resetToMockName } = options;
|
||||
if (restore) {
|
||||
MOCK_RESTORE.add(restore);
|
||||
}
|
||||
const config = getDefaultConfig(originalImplementation);
|
||||
const state = getDefaultState();
|
||||
const mock = createMock({
|
||||
config,
|
||||
state,
|
||||
...options
|
||||
});
|
||||
const mockLength = (mockImplementation || originalImplementation)?.length ?? 0;
|
||||
Object.defineProperty(mock, "length", {
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
value: mockLength,
|
||||
configurable: true
|
||||
});
|
||||
// inherit the default name so it appears in snapshots and logs
|
||||
// this is used by `vi.spyOn()` for better debugging.
|
||||
// when `vi.fn()` is called, we just use the default string
|
||||
if (resetToMockName) {
|
||||
config.mockName = mock.name || "vi.fn()";
|
||||
}
|
||||
MOCK_CONFIGS.set(mock, config);
|
||||
REGISTERED_MOCKS.add(mock);
|
||||
mock._isMockFunction = true;
|
||||
mock.getMockImplementation = () => {
|
||||
// Jest only returns `config.mockImplementation` here,
|
||||
// but we think it makes sense to return what the next function will be called
|
||||
return config.onceMockImplementations[0] || config.mockImplementation;
|
||||
};
|
||||
Object.defineProperty(mock, "mock", {
|
||||
configurable: false,
|
||||
enumerable: true,
|
||||
writable: false,
|
||||
value: state
|
||||
});
|
||||
mock.mockImplementation = function mockImplementation(implementation) {
|
||||
config.mockImplementation = implementation;
|
||||
return mock;
|
||||
};
|
||||
mock.mockImplementationOnce = function mockImplementationOnce(implementation) {
|
||||
config.onceMockImplementations.push(implementation);
|
||||
return mock;
|
||||
};
|
||||
mock.withImplementation = function withImplementation(implementation, callback) {
|
||||
const previousImplementation = config.mockImplementation;
|
||||
const previousOnceImplementations = config.onceMockImplementations;
|
||||
const reset = () => {
|
||||
config.mockImplementation = previousImplementation;
|
||||
config.onceMockImplementations = previousOnceImplementations;
|
||||
};
|
||||
config.mockImplementation = implementation;
|
||||
config.onceMockImplementations = [];
|
||||
const returnValue = callback();
|
||||
if (typeof returnValue === "object" && typeof returnValue?.then === "function") {
|
||||
return returnValue.then(() => {
|
||||
reset();
|
||||
return mock;
|
||||
});
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
return mock;
|
||||
};
|
||||
mock.mockReturnThis = function mockReturnThis() {
|
||||
return mock.mockImplementation(function() {
|
||||
return this;
|
||||
});
|
||||
};
|
||||
mock.mockReturnValue = function mockReturnValue(value) {
|
||||
return mock.mockImplementation(function() {
|
||||
if (new.target) {
|
||||
throwConstructorError("mockReturnValue");
|
||||
}
|
||||
return value;
|
||||
});
|
||||
};
|
||||
mock.mockReturnValueOnce = function mockReturnValueOnce(value) {
|
||||
return mock.mockImplementationOnce(function() {
|
||||
if (new.target) {
|
||||
throwConstructorError("mockReturnValueOnce");
|
||||
}
|
||||
return value;
|
||||
});
|
||||
};
|
||||
mock.mockThrow = function mockThrow(value) {
|
||||
// eslint-disable-next-line prefer-arrow-callback
|
||||
return mock.mockImplementation(function() {
|
||||
throw value;
|
||||
});
|
||||
};
|
||||
mock.mockThrowOnce = function mockThrowOnce(value) {
|
||||
// eslint-disable-next-line prefer-arrow-callback
|
||||
return mock.mockImplementationOnce(function() {
|
||||
throw value;
|
||||
});
|
||||
};
|
||||
mock.mockResolvedValue = function mockResolvedValue(value) {
|
||||
return mock.mockImplementation(function() {
|
||||
if (new.target) {
|
||||
throwConstructorError("mockResolvedValue");
|
||||
}
|
||||
return Promise.resolve(value);
|
||||
});
|
||||
};
|
||||
mock.mockResolvedValueOnce = function mockResolvedValueOnce(value) {
|
||||
return mock.mockImplementationOnce(function() {
|
||||
if (new.target) {
|
||||
throwConstructorError("mockResolvedValueOnce");
|
||||
}
|
||||
return Promise.resolve(value);
|
||||
});
|
||||
};
|
||||
mock.mockRejectedValue = function mockRejectedValue(value) {
|
||||
return mock.mockImplementation(function() {
|
||||
if (new.target) {
|
||||
throwConstructorError("mockRejectedValue");
|
||||
}
|
||||
return Promise.reject(value);
|
||||
});
|
||||
};
|
||||
mock.mockRejectedValueOnce = function mockRejectedValueOnce(value) {
|
||||
return mock.mockImplementationOnce(function() {
|
||||
if (new.target) {
|
||||
throwConstructorError("mockRejectedValueOnce");
|
||||
}
|
||||
return Promise.reject(value);
|
||||
});
|
||||
};
|
||||
mock.mockClear = function mockClear() {
|
||||
state.calls = [];
|
||||
state.contexts = [];
|
||||
state.instances = [];
|
||||
state.invocationCallOrder = [];
|
||||
state.results = [];
|
||||
state.settledResults = [];
|
||||
return mock;
|
||||
};
|
||||
mock.mockReset = function mockReset() {
|
||||
mock.mockClear();
|
||||
config.mockImplementation = resetToMockImplementation ? mockImplementation : undefined;
|
||||
config.mockName = resetToMockName ? mock.name || "vi.fn()" : "vi.fn()";
|
||||
config.onceMockImplementations = [];
|
||||
return mock;
|
||||
};
|
||||
mock.mockRestore = function mockRestore() {
|
||||
mock.mockReset();
|
||||
return restore?.();
|
||||
};
|
||||
mock.mockName = function mockName(name) {
|
||||
if (typeof name === "string") {
|
||||
config.mockName = name;
|
||||
}
|
||||
return mock;
|
||||
};
|
||||
mock.getMockName = function getMockName() {
|
||||
return config.mockName || "vi.fn()";
|
||||
};
|
||||
if (Symbol.dispose) {
|
||||
mock[Symbol.dispose] = () => mock.mockRestore();
|
||||
}
|
||||
if (mockImplementation) {
|
||||
mock.mockImplementation(mockImplementation);
|
||||
}
|
||||
return mock;
|
||||
}
|
||||
function fn(originalImplementation) {
|
||||
// if the function is already a mock, just return the same function,
|
||||
// similarly to how vi.spyOn() works
|
||||
if (originalImplementation != null && isMockFunction(originalImplementation)) {
|
||||
return originalImplementation;
|
||||
}
|
||||
return createMockInstance({
|
||||
mockImplementation: originalImplementation,
|
||||
resetToMockImplementation: true
|
||||
});
|
||||
}
|
||||
function spyOn(object, key, accessor) {
|
||||
assert(object != null, "The vi.spyOn() function could not find an object to spy upon. The first argument must be defined.");
|
||||
assert(typeof object === "object" || typeof object === "function", "Vitest cannot spy on a primitive value.");
|
||||
const [originalDescriptorObject, originalDescriptor] = getDescriptor(object, key) || [];
|
||||
assert(originalDescriptor || key in object, `The property "${String(key)}" is not defined on the ${typeof object}.`);
|
||||
let accessType = accessor || "value";
|
||||
let ssr = false;
|
||||
// vite ssr support - actual function is stored inside a getter
|
||||
if (accessType === "value" && originalDescriptor && originalDescriptor.value == null && originalDescriptor.get) {
|
||||
accessType = "get";
|
||||
ssr = true;
|
||||
}
|
||||
let original;
|
||||
if (originalDescriptor) {
|
||||
original = originalDescriptor[accessType];
|
||||
// weird Proxy edge case where descriptor's value is undefined,
|
||||
// but there's still a value on the object when called
|
||||
// https://github.com/vitest-dev/vitest/issues/9439
|
||||
if (original == null && accessType === "value") {
|
||||
original = object[key];
|
||||
}
|
||||
} else if (accessType !== "value") {
|
||||
original = () => object[key];
|
||||
} else {
|
||||
original = object[key];
|
||||
}
|
||||
const originalImplementation = ssr && original ? original() : original;
|
||||
const originalType = typeof originalImplementation;
|
||||
assert(
|
||||
// allow only functions
|
||||
originalType === "function" || accessType !== "value" && original == null,
|
||||
`vi.spyOn() can only spy on a function. Received ${originalType}.`
|
||||
);
|
||||
if (isMockFunction(originalImplementation)) {
|
||||
return originalImplementation;
|
||||
}
|
||||
const reassign = (cb) => {
|
||||
const { value, ...desc } = originalDescriptor || {
|
||||
configurable: true,
|
||||
writable: true
|
||||
};
|
||||
if (accessType !== "value") {
|
||||
delete desc.writable;
|
||||
}
|
||||
desc[accessType] = cb;
|
||||
Object.defineProperty(object, key, desc);
|
||||
};
|
||||
const restore = () => {
|
||||
// if method is defined on the prototype, we can just remove it from
|
||||
// the current object instead of redefining a copy of it
|
||||
if (originalDescriptorObject !== object) {
|
||||
Reflect.deleteProperty(object, key);
|
||||
} else if (originalDescriptor && !original) {
|
||||
Object.defineProperty(object, key, originalDescriptor);
|
||||
} else {
|
||||
reassign(original);
|
||||
}
|
||||
};
|
||||
const mock = createMockInstance({
|
||||
restore,
|
||||
originalImplementation,
|
||||
resetToMockName: true
|
||||
});
|
||||
try {
|
||||
reassign(ssr ? () => mock : mock);
|
||||
} catch (error) {
|
||||
if (error instanceof TypeError && Symbol.toStringTag && object[Symbol.toStringTag] === "Module" && (error.message.includes("Cannot redefine property") || error.message.includes("Cannot replace module namespace") || error.message.includes("can't redefine non-configurable property"))) {
|
||||
throw new TypeError(`Cannot spy on export "${String(key)}". Module namespace is not configurable in ESM. See: https://vitest.dev/guide/browser/#limitations`, { cause: error });
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
return mock;
|
||||
}
|
||||
function getDescriptor(obj, method) {
|
||||
const objDescriptor = Object.getOwnPropertyDescriptor(obj, method);
|
||||
if (objDescriptor) {
|
||||
return [obj, objDescriptor];
|
||||
}
|
||||
let currentProto = Object.getPrototypeOf(obj);
|
||||
while (currentProto !== null) {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(currentProto, method);
|
||||
if (descriptor) {
|
||||
return [currentProto, descriptor];
|
||||
}
|
||||
currentProto = Object.getPrototypeOf(currentProto);
|
||||
}
|
||||
}
|
||||
function assert(condition, message) {
|
||||
if (!condition) {
|
||||
throw new Error(message);
|
||||
}
|
||||
}
|
||||
let invocationCallCounter = 1;
|
||||
function createMock({ state, config, name: mockName, prototypeState, prototypeConfig, keepMembersImplementation, mockImplementation, prototypeMembers = [] }) {
|
||||
const original = config.mockOriginal;
|
||||
const pseudoOriginal = mockImplementation;
|
||||
const name = mockName || original?.name || "Mock";
|
||||
const namedObject = { [name]: (function(...args) {
|
||||
registerCalls(args, state, prototypeState);
|
||||
registerInvocationOrder(invocationCallCounter++, state, prototypeState);
|
||||
const result = {
|
||||
type: "incomplete",
|
||||
value: undefined
|
||||
};
|
||||
const settledResult = {
|
||||
type: "incomplete",
|
||||
value: undefined
|
||||
};
|
||||
registerResult(result, state, prototypeState);
|
||||
registerSettledResult(settledResult, state, prototypeState);
|
||||
const context = new.target ? undefined : this;
|
||||
const [instanceIndex, instancePrototypeIndex] = registerInstance(context, state, prototypeState);
|
||||
const [contextIndex, contextPrototypeIndex] = registerContext(context, state, prototypeState);
|
||||
const implementation = config.onceMockImplementations.shift() || config.mockImplementation || prototypeConfig?.onceMockImplementations.shift() || prototypeConfig?.mockImplementation || original || function() {};
|
||||
let returnValue;
|
||||
let thrownValue;
|
||||
let didThrow = false;
|
||||
try {
|
||||
if (new.target) {
|
||||
returnValue = Reflect.construct(implementation, args, new.target);
|
||||
// jest calls this before the implementation, but we have to resolve this _after_
|
||||
// because we cannot do it before the `Reflect.construct` called the custom implementation.
|
||||
// fortunately, the constructor is always an empty function because `prototypeMethods`
|
||||
// are only used by the automocker, so this doesn't matter
|
||||
for (const prop of prototypeMembers) {
|
||||
const prototypeMock = returnValue[prop];
|
||||
// the method was overridden because of inheritance, ignore it
|
||||
// eslint-disable-next-line ts/no-use-before-define
|
||||
if (prototypeMock !== mock.prototype[prop]) {
|
||||
continue;
|
||||
}
|
||||
const isMock = isMockFunction(prototypeMock);
|
||||
const prototypeState = isMock ? prototypeMock.mock : undefined;
|
||||
const prototypeConfig = isMock ? MOCK_CONFIGS.get(prototypeMock) : undefined;
|
||||
returnValue[prop] = createMockInstance({
|
||||
originalImplementation: keepMembersImplementation ? prototypeConfig?.mockOriginal : undefined,
|
||||
prototypeState,
|
||||
prototypeConfig,
|
||||
keepMembersImplementation
|
||||
});
|
||||
}
|
||||
} else {
|
||||
returnValue = implementation.apply(this, args);
|
||||
}
|
||||
} catch (error) {
|
||||
thrownValue = error;
|
||||
didThrow = true;
|
||||
if (error instanceof TypeError && error.message.includes("is not a constructor")) {
|
||||
console.warn(`[vitest] The ${namedObject[name].getMockName()} mock did not use 'function' or 'class' in its implementation, see https://vitest.dev/api/vi#vi-spyon for examples.`);
|
||||
}
|
||||
throw error;
|
||||
} finally {
|
||||
if (didThrow) {
|
||||
result.type = "throw";
|
||||
result.value = thrownValue;
|
||||
settledResult.type = "rejected";
|
||||
settledResult.value = thrownValue;
|
||||
} else {
|
||||
result.type = "return";
|
||||
result.value = returnValue;
|
||||
if (new.target) {
|
||||
state.contexts[contextIndex - 1] = returnValue;
|
||||
state.instances[instanceIndex - 1] = returnValue;
|
||||
if (contextPrototypeIndex != null && prototypeState) {
|
||||
prototypeState.contexts[contextPrototypeIndex - 1] = returnValue;
|
||||
}
|
||||
if (instancePrototypeIndex != null && prototypeState) {
|
||||
prototypeState.instances[instancePrototypeIndex - 1] = returnValue;
|
||||
}
|
||||
}
|
||||
if (returnValue instanceof Promise) {
|
||||
returnValue.then((settledValue) => {
|
||||
settledResult.type = "fulfilled";
|
||||
settledResult.value = settledValue;
|
||||
}, (rejectedValue) => {
|
||||
settledResult.type = "rejected";
|
||||
settledResult.value = rejectedValue;
|
||||
});
|
||||
} else {
|
||||
settledResult.type = "fulfilled";
|
||||
settledResult.value = returnValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}) };
|
||||
const mock = namedObject[name];
|
||||
const copyPropertiesFrom = original || pseudoOriginal;
|
||||
if (copyPropertiesFrom) {
|
||||
copyOriginalStaticProperties(mock, copyPropertiesFrom);
|
||||
}
|
||||
return mock;
|
||||
}
|
||||
function registerCalls(args, state, prototypeState) {
|
||||
state.calls.push(args);
|
||||
prototypeState?.calls.push(args);
|
||||
}
|
||||
function registerInvocationOrder(order, state, prototypeState) {
|
||||
state.invocationCallOrder.push(order);
|
||||
prototypeState?.invocationCallOrder.push(order);
|
||||
}
|
||||
function registerResult(result, state, prototypeState) {
|
||||
state.results.push(result);
|
||||
prototypeState?.results.push(result);
|
||||
}
|
||||
function registerSettledResult(result, state, prototypeState) {
|
||||
state.settledResults.push(result);
|
||||
prototypeState?.settledResults.push(result);
|
||||
}
|
||||
function registerInstance(instance, state, prototypeState) {
|
||||
const instanceIndex = state.instances.push(instance);
|
||||
const instancePrototypeIndex = prototypeState?.instances.push(instance);
|
||||
return [instanceIndex, instancePrototypeIndex];
|
||||
}
|
||||
function registerContext(context, state, prototypeState) {
|
||||
const contextIndex = state.contexts.push(context);
|
||||
const contextPrototypeIndex = prototypeState?.contexts.push(context);
|
||||
return [contextIndex, contextPrototypeIndex];
|
||||
}
|
||||
function copyOriginalStaticProperties(mock, original) {
|
||||
const { properties, descriptors } = getAllProperties(original);
|
||||
for (const key of properties) {
|
||||
const descriptor = descriptors[key];
|
||||
const mockDescriptor = getDescriptor(mock, key);
|
||||
if (mockDescriptor) {
|
||||
continue;
|
||||
}
|
||||
Object.defineProperty(mock, key, descriptor);
|
||||
}
|
||||
}
|
||||
const ignoreProperties = new Set([
|
||||
"length",
|
||||
"name",
|
||||
"prototype",
|
||||
Symbol.for("nodejs.util.promisify.custom")
|
||||
]);
|
||||
function getAllProperties(original) {
|
||||
const properties = new Set();
|
||||
const descriptors = {};
|
||||
while (original && original !== Object.prototype && original !== Function.prototype) {
|
||||
const ownProperties = [...Object.getOwnPropertyNames(original), ...Object.getOwnPropertySymbols(original)];
|
||||
for (const prop of ownProperties) {
|
||||
if (descriptors[prop] || ignoreProperties.has(prop)) {
|
||||
continue;
|
||||
}
|
||||
properties.add(prop);
|
||||
descriptors[prop] = Object.getOwnPropertyDescriptor(original, prop);
|
||||
}
|
||||
original = Object.getPrototypeOf(original);
|
||||
}
|
||||
return {
|
||||
properties,
|
||||
descriptors
|
||||
};
|
||||
}
|
||||
function getDefaultConfig(original) {
|
||||
return {
|
||||
mockImplementation: undefined,
|
||||
mockOriginal: original,
|
||||
mockName: "vi.fn()",
|
||||
onceMockImplementations: []
|
||||
};
|
||||
}
|
||||
function getDefaultState() {
|
||||
const state = {
|
||||
calls: [],
|
||||
contexts: [],
|
||||
instances: [],
|
||||
invocationCallOrder: [],
|
||||
settledResults: [],
|
||||
results: [],
|
||||
get lastCall() {
|
||||
return state.calls.at(-1);
|
||||
}
|
||||
};
|
||||
return state;
|
||||
}
|
||||
function restoreAllMocks() {
|
||||
for (const restore of MOCK_RESTORE) {
|
||||
restore();
|
||||
}
|
||||
MOCK_RESTORE.clear();
|
||||
}
|
||||
function clearAllMocks() {
|
||||
REGISTERED_MOCKS.forEach((mock) => mock.mockClear());
|
||||
}
|
||||
function resetAllMocks() {
|
||||
REGISTERED_MOCKS.forEach((mock) => mock.mockReset());
|
||||
}
|
||||
function throwConstructorError(shorthand) {
|
||||
throw new TypeError(`Cannot use \`${shorthand}\` when called with \`new\`. Use \`mockImplementation\` with a \`class\` keyword instead. See https://vitest.dev/api/mock#class-support for more information.`);
|
||||
}
|
||||
|
||||
export { clearAllMocks, createMockInstance, fn, isMockFunction, resetAllMocks, restoreAllMocks, spyOn };
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "stackback",
|
||||
"version": "0.0.2",
|
||||
"description": "return list of CallSite objects from a captured stacktrace",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "mocha --ui qunit"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/shtylman/node-stackback.git"
|
||||
},
|
||||
"keywords": [
|
||||
"stacktrace",
|
||||
"trace",
|
||||
"stack"
|
||||
],
|
||||
"devDependencies": {
|
||||
"mocha": "~1.6.0"
|
||||
},
|
||||
"author": "Roman Shtylman <shtylman@gmail.com>",
|
||||
"license": "MIT"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,IAAI,MAAM,gBAAgB,CAAC;AAClC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;AAE5B,OAAO,KAAK,MAAM,iBAAiB,CAAC;AACpC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC;AAE9B,OAAO,EAAE,MAAM,cAAc,CAAC;AAC9B,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;AAExB,OAAO,GAAG,MAAM,eAAe,CAAC;AAChC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC;AAE1B,OAAO,MAAM,MAAM,kBAAkB,CAAC;AACtC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;AAEhC,OAAO,GAAG,MAAM,eAAe,CAAC;AAChC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC;AAE1B,OAAO,IAAI,MAAM,oBAAoB,CAAC;AACtC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;AAE5B,cAAc,OAAO,CAAC"}
|
||||
Reference in New Issue
Block a user