update
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -0,0 +1,108 @@
|
||||
/*! simple-get. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||||
module.exports = simpleGet
|
||||
|
||||
const concat = require('simple-concat')
|
||||
const decompressResponse = require('decompress-response') // excluded from browser build
|
||||
const http = require('http')
|
||||
const https = require('https')
|
||||
const once = require('once')
|
||||
const querystring = require('querystring')
|
||||
const url = require('url')
|
||||
|
||||
const isStream = o => o !== null && typeof o === 'object' && typeof o.pipe === 'function'
|
||||
|
||||
function simpleGet (opts, cb) {
|
||||
opts = Object.assign({ maxRedirects: 10 }, typeof opts === 'string' ? { url: opts } : opts)
|
||||
cb = once(cb)
|
||||
|
||||
if (opts.url) {
|
||||
const { hostname, port, protocol, auth, path } = url.parse(opts.url) // eslint-disable-line node/no-deprecated-api
|
||||
delete opts.url
|
||||
if (!hostname && !port && !protocol && !auth) opts.path = path // Relative redirect
|
||||
else Object.assign(opts, { hostname, port, protocol, auth, path }) // Absolute redirect
|
||||
}
|
||||
|
||||
const headers = { 'accept-encoding': 'gzip, deflate' }
|
||||
if (opts.headers) Object.keys(opts.headers).forEach(k => (headers[k.toLowerCase()] = opts.headers[k]))
|
||||
opts.headers = headers
|
||||
|
||||
let body
|
||||
if (opts.body) {
|
||||
body = opts.json && !isStream(opts.body) ? JSON.stringify(opts.body) : opts.body
|
||||
} else if (opts.form) {
|
||||
body = typeof opts.form === 'string' ? opts.form : querystring.stringify(opts.form)
|
||||
opts.headers['content-type'] = 'application/x-www-form-urlencoded'
|
||||
}
|
||||
|
||||
if (body) {
|
||||
if (!opts.method) opts.method = 'POST'
|
||||
if (!isStream(body)) opts.headers['content-length'] = Buffer.byteLength(body)
|
||||
if (opts.json && !opts.form) opts.headers['content-type'] = 'application/json'
|
||||
}
|
||||
delete opts.body; delete opts.form
|
||||
|
||||
if (opts.json) opts.headers.accept = 'application/json'
|
||||
if (opts.method) opts.method = opts.method.toUpperCase()
|
||||
|
||||
const originalHost = opts.hostname // hostname before potential redirect
|
||||
const protocol = opts.protocol === 'https:' ? https : http // Support http/https urls
|
||||
const req = protocol.request(opts, res => {
|
||||
if (opts.followRedirects !== false && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||
opts.url = res.headers.location // Follow 3xx redirects
|
||||
delete opts.headers.host // Discard `host` header on redirect (see #32)
|
||||
res.resume() // Discard response
|
||||
|
||||
const redirectHost = url.parse(opts.url).hostname // eslint-disable-line node/no-deprecated-api
|
||||
// If redirected host is different than original host, drop headers to prevent cookie leak (#73)
|
||||
if (redirectHost !== null && redirectHost !== originalHost) {
|
||||
delete opts.headers.cookie
|
||||
delete opts.headers.authorization
|
||||
}
|
||||
|
||||
if (opts.method === 'POST' && [301, 302].includes(res.statusCode)) {
|
||||
opts.method = 'GET' // On 301/302 redirect, change POST to GET (see #35)
|
||||
delete opts.headers['content-length']; delete opts.headers['content-type']
|
||||
}
|
||||
|
||||
if (opts.maxRedirects-- === 0) return cb(new Error('too many redirects'))
|
||||
else return simpleGet(opts, cb)
|
||||
}
|
||||
|
||||
const tryUnzip = typeof decompressResponse === 'function' && opts.method !== 'HEAD'
|
||||
cb(null, tryUnzip ? decompressResponse(res) : res)
|
||||
})
|
||||
req.on('timeout', () => {
|
||||
req.abort()
|
||||
cb(new Error('Request timed out'))
|
||||
})
|
||||
req.on('error', cb)
|
||||
|
||||
if (isStream(body)) body.on('error', cb).pipe(req)
|
||||
else req.end(body)
|
||||
|
||||
return req
|
||||
}
|
||||
|
||||
simpleGet.concat = (opts, cb) => {
|
||||
return simpleGet(opts, (err, res) => {
|
||||
if (err) return cb(err)
|
||||
concat(res, (err, data) => {
|
||||
if (err) return cb(err)
|
||||
if (opts.json) {
|
||||
try {
|
||||
data = JSON.parse(data.toString())
|
||||
} catch (err) {
|
||||
return cb(err, res, data)
|
||||
}
|
||||
}
|
||||
cb(null, res, data)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
;['get', 'post', 'put', 'patch', 'head', 'delete'].forEach(method => {
|
||||
simpleGet[method] = (opts, cb) => {
|
||||
if (typeof opts === 'string') opts = { url: opts }
|
||||
return simpleGet(Object.assign({ method: method.toUpperCase() }, opts), cb)
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1 @@
|
||||
module.exports={A:{A:{"1":"A B","2":"K D mC","132":"E F"},B:{"1":"0 9 C L M G N O P Q H R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I"},C:{"1":"0 1 2 3 4 5 6 7 8 9 J PB K D E F A B C L M G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB MC wB NC xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R OC S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I PC EC QC RC oC pC","2":"nC LC qC rC"},D:{"1":"0 1 2 3 4 5 6 7 8 9 J PB K D E F A B C L M G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB MC wB NC xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I PC EC QC RC"},E:{"1":"J PB K D E F A B C L M G sC SC tC uC vC wC TC FC GC xC yC zC UC VC HC 0C IC WC XC YC ZC aC 1C JC bC cC dC eC fC 2C KC gC hC iC jC 3C"},F:{"1":"0 1 2 3 4 5 6 7 8 B C G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB wB xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R OC S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z FC kC 8C GC","2":"F 4C 5C 6C 7C"},G:{"1":"SC 9C lC AD","513":"E BD CD DD ED FD GD HD ID JD KD LD MD ND OD PD QD RD SD UC VC HC TD IC WC XC YC ZC aC UD JC bC cC dC eC fC VD KC gC hC iC jC"},H:{"4097":"WD"},I:{"1025":"LC J I XD YD ZD aD lC bD cD"},J:{"258":"D A"},K:{"2":"A","258":"B C FC kC GC","1025":"H"},L:{"1025":"I"},M:{"2049":"EC"},N:{"258":"A B"},O:{"258":"HC"},P:{"1025":"1 2 3 4 5 6 7 8 J dD eD fD gD hD TC iD jD kD lD mD IC JC KC nD"},Q:{"1":"oD"},R:{"1025":"pD"},S:{"1":"qD rD"}},B:1,C:"Basic console logging functions",D:true};
|
||||
@@ -0,0 +1,223 @@
|
||||
/**
|
||||
* @fileoverview Helpers to debug for code path analysis.
|
||||
* @author Toru Nagashima
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const debug = require("debug")("eslint:code-path");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Gets id of a given segment.
|
||||
* @param {CodePathSegment} segment A segment to get.
|
||||
* @returns {string} Id of the segment.
|
||||
*/
|
||||
/* c8 ignore next */
|
||||
// eslint-disable-next-line jsdoc/require-jsdoc -- Ignoring
|
||||
function getId(segment) {
|
||||
return segment.id + (segment.reachable ? "" : "!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string for the given node and operation.
|
||||
* @param {ASTNode} node The node to convert.
|
||||
* @param {"enter" | "exit" | undefined} label The operation label.
|
||||
* @returns {string} The string representation.
|
||||
*/
|
||||
function nodeToString(node, label) {
|
||||
const suffix = label ? `:${label}` : "";
|
||||
|
||||
switch (node.type) {
|
||||
case "Identifier":
|
||||
return `${node.type}${suffix} (${node.name})`;
|
||||
case "Literal":
|
||||
return `${node.type}${suffix} (${node.value})`;
|
||||
default:
|
||||
return `${node.type}${suffix}`;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* A flag that debug dumping is enabled or not.
|
||||
* @type {boolean}
|
||||
*/
|
||||
enabled: debug.enabled,
|
||||
|
||||
/**
|
||||
* Dumps given objects.
|
||||
* @param {...any} args objects to dump.
|
||||
* @returns {void}
|
||||
*/
|
||||
dump: debug,
|
||||
|
||||
/**
|
||||
* Dumps the current analyzing state.
|
||||
* @param {ASTNode} node A node to dump.
|
||||
* @param {CodePathState} state A state to dump.
|
||||
* @param {boolean} leaving A flag whether or not it's leaving
|
||||
* @returns {void}
|
||||
*/
|
||||
dumpState: !debug.enabled
|
||||
? debug
|
||||
: /* c8 ignore next */ function (node, state, leaving) {
|
||||
for (let i = 0; i < state.currentSegments.length; ++i) {
|
||||
const segInternal = state.currentSegments[i].internal;
|
||||
|
||||
if (leaving) {
|
||||
const last = segInternal.nodes.length - 1;
|
||||
|
||||
if (
|
||||
last >= 0 &&
|
||||
segInternal.nodes[last] ===
|
||||
nodeToString(node, "enter")
|
||||
) {
|
||||
segInternal.nodes[last] = nodeToString(
|
||||
node,
|
||||
void 0,
|
||||
);
|
||||
} else {
|
||||
segInternal.nodes.push(nodeToString(node, "exit"));
|
||||
}
|
||||
} else {
|
||||
segInternal.nodes.push(nodeToString(node, "enter"));
|
||||
}
|
||||
}
|
||||
|
||||
debug(
|
||||
[
|
||||
`${state.currentSegments.map(getId).join(",")})`,
|
||||
`${node.type}${leaving ? ":exit" : ""}`,
|
||||
].join(" "),
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Dumps a DOT code of a given code path.
|
||||
* The DOT code can be visualized with Graphvis.
|
||||
* @param {CodePath} codePath A code path to dump.
|
||||
* @returns {void}
|
||||
* @see http://www.graphviz.org
|
||||
* @see http://www.webgraphviz.com
|
||||
*/
|
||||
dumpDot: !debug.enabled
|
||||
? debug
|
||||
: /* c8 ignore next */ function (codePath) {
|
||||
let text =
|
||||
"\n" +
|
||||
"digraph {\n" +
|
||||
'node[shape=box,style="rounded,filled",fillcolor=white];\n' +
|
||||
'initial[label="",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25];\n';
|
||||
|
||||
if (codePath.returnedSegments.length > 0) {
|
||||
text +=
|
||||
'final[label="",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25];\n';
|
||||
}
|
||||
if (codePath.thrownSegments.length > 0) {
|
||||
text +=
|
||||
'thrown[label="✘",shape=circle,width=0.3,height=0.3,fixedsize=true];\n';
|
||||
}
|
||||
|
||||
const traceMap = Object.create(null);
|
||||
const arrows = this.makeDotArrows(codePath, traceMap);
|
||||
|
||||
// eslint-disable-next-line guard-for-in -- Want ability to traverse prototype
|
||||
for (const id in traceMap) {
|
||||
const segment = traceMap[id];
|
||||
|
||||
text += `${id}[`;
|
||||
|
||||
if (segment.reachable) {
|
||||
text += 'label="';
|
||||
} else {
|
||||
text +=
|
||||
'style="rounded,dashed,filled",fillcolor="#FF9800",label="<<unreachable>>\\n';
|
||||
}
|
||||
|
||||
if (segment.internal.nodes.length > 0) {
|
||||
text += segment.internal.nodes.join("\\n");
|
||||
} else {
|
||||
text += "????";
|
||||
}
|
||||
|
||||
text += '"];\n';
|
||||
}
|
||||
|
||||
text += `${arrows}\n`;
|
||||
text += "}";
|
||||
debug("DOT", text);
|
||||
},
|
||||
|
||||
/**
|
||||
* Makes a DOT code of a given code path.
|
||||
* The DOT code can be visualized with Graphvis.
|
||||
* @param {CodePath} codePath A code path to make DOT.
|
||||
* @param {Object} traceMap Optional. A map to check whether or not segments had been done.
|
||||
* @returns {string} A DOT code of the code path.
|
||||
*/
|
||||
makeDotArrows(codePath, traceMap) {
|
||||
const stack = [[codePath.initialSegment, 0]];
|
||||
const done = traceMap || Object.create(null);
|
||||
let lastId = codePath.initialSegment.id;
|
||||
let text = `initial->${codePath.initialSegment.id}`;
|
||||
|
||||
while (stack.length > 0) {
|
||||
const item = stack.pop();
|
||||
const segment = item[0];
|
||||
const index = item[1];
|
||||
|
||||
if (done[segment.id] && index === 0) {
|
||||
continue;
|
||||
}
|
||||
done[segment.id] = segment;
|
||||
|
||||
const nextSegment = segment.allNextSegments[index];
|
||||
|
||||
if (!nextSegment) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lastId === segment.id) {
|
||||
text += `->${nextSegment.id}`;
|
||||
} else {
|
||||
text += `;\n${segment.id}->${nextSegment.id}`;
|
||||
}
|
||||
lastId = nextSegment.id;
|
||||
|
||||
stack.unshift([segment, 1 + index]);
|
||||
stack.push([nextSegment, 0]);
|
||||
}
|
||||
|
||||
codePath.returnedSegments.forEach(finalSegment => {
|
||||
if (lastId === finalSegment.id) {
|
||||
text += "->final";
|
||||
} else {
|
||||
text += `;\n${finalSegment.id}->final`;
|
||||
}
|
||||
lastId = null;
|
||||
});
|
||||
|
||||
codePath.thrownSegments.forEach(finalSegment => {
|
||||
if (lastId === finalSegment.id) {
|
||||
text += "->thrown";
|
||||
} else {
|
||||
text += `;\n${finalSegment.id}->thrown`;
|
||||
}
|
||||
lastId = null;
|
||||
});
|
||||
|
||||
return `${text};`;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
module.exports={A:{A:{"2":"F A B mC","8":"K D E"},B:{"2":"0 9 C L M G N O P Q H R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I"},C:{"2":"0 1 2 3 4 5 6 7 8 9 nC LC J PB K D E F A B C L M G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB MC wB NC xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R OC S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I PC EC QC RC oC pC qC rC"},D:{"1":"1 2 3 4 5 6 7 8 J PB K D E F A B C L M G N O P QB RB SB TB UB VB WB XB YB ZB aB","2":"0 9 oB pB qB rB sB tB uB vB MC wB NC xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I PC EC QC RC","130":"bB cB dB eB fB gB hB iB jB kB lB mB nB"},E:{"1":"J PB K D E F A B C L M G SC tC uC vC wC TC FC GC xC yC zC UC VC HC 0C IC WC XC YC ZC aC 1C JC bC cC dC eC fC 2C KC gC hC iC jC 3C","2":"sC"},F:{"1":"1 2 3 4 5 F B C G N O P QB 4C 5C 6C 7C FC kC 8C GC","2":"0 aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB wB xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R OC S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z","130":"6 7 8 RB SB TB UB VB WB XB YB ZB"},G:{"1":"E SC 9C lC AD BD CD DD ED FD GD HD ID JD KD LD MD ND OD PD QD RD SD UC VC HC TD IC WC XC YC ZC aC UD JC bC cC dC eC fC VD KC gC hC iC jC"},H:{"258":"WD"},I:{"1":"LC J aD lC bD cD","2":"I XD YD ZD"},J:{"1":"D A"},K:{"1":"A B C FC kC GC","2":"H"},L:{"130":"I"},M:{"2":"EC"},N:{"2":"A B"},O:{"2":"HC"},P:{"1":"J","130":"1 2 3 4 5 6 7 8 dD eD fD gD hD TC iD jD kD lD mD IC JC KC nD"},Q:{"2":"oD"},R:{"130":"pD"},S:{"2":"qD rD"}},B:2,C:"SVG fonts",D:true};
|
||||
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"name": "enhanced-resolve",
|
||||
"version": "5.18.1",
|
||||
"author": "Tobias Koppers @sokra",
|
||||
"description": "Offers a async require.resolve function. It's highly configurable.",
|
||||
"files": [
|
||||
"lib",
|
||||
"types.d.ts",
|
||||
"LICENSE"
|
||||
],
|
||||
"browser": {
|
||||
"process": "./lib/util/process-browser.js",
|
||||
"module": "./lib/util/module-browser.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.4",
|
||||
"tapable": "^2.2.0"
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/graceful-fs": "^4.1.6",
|
||||
"@types/jest": "^27.5.1",
|
||||
"@types/node": "20.9.5",
|
||||
"cspell": "4.2.8",
|
||||
"eslint": "^7.9.0",
|
||||
"eslint-config-prettier": "^6.11.0",
|
||||
"eslint-plugin-jsdoc": "^30.5.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^3.1.4",
|
||||
"husky": "^6.0.0",
|
||||
"jest": "^27.5.1",
|
||||
"lint-staged": "^10.4.0",
|
||||
"memfs": "^3.2.0",
|
||||
"prettier": "^2.1.2",
|
||||
"tooling": "webpack/tooling#v1.23.1",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"types": "types.d.ts",
|
||||
"homepage": "http://github.com/webpack/enhanced-resolve",
|
||||
"scripts": {
|
||||
"lint": "yarn run code-lint && yarn run type-lint && yarn typings-test && yarn run special-lint && yarn run spelling",
|
||||
"fix": "yarn run code-lint-fix && yarn run special-lint-fix",
|
||||
"code-lint": "eslint --cache lib test",
|
||||
"code-lint-fix": "eslint --cache lib test --fix",
|
||||
"type-lint": "tsc",
|
||||
"typings-test": "tsc -p tsconfig.types.test.json",
|
||||
"type-report": "rimraf coverage && yarn cover:types && yarn cover:report && open-cli coverage/lcov-report/index.html",
|
||||
"special-lint": "node node_modules/tooling/lockfile-lint && node node_modules/tooling/inherit-types && node node_modules/tooling/format-file-header && node node_modules/tooling/generate-types",
|
||||
"special-lint-fix": "node node_modules/tooling/inherit-types --write && node node_modules/tooling/format-file-header --write && node node_modules/tooling/generate-types --write",
|
||||
"pretty": "prettier --loglevel warn --write \"lib/**/*.{js,json}\" \"test/*.js\"",
|
||||
"pretest": "yarn lint",
|
||||
"spelling": "cspell \"**\"",
|
||||
"test:only": "node_modules/.bin/jest",
|
||||
"test:watch": "yarn test:only -- --watch",
|
||||
"test:coverage": "yarn test:only -- --collectCoverageFrom=\"lib/**/*.js\" --coverage",
|
||||
"test": "yarn test:coverage",
|
||||
"precover": "yarn lint",
|
||||
"prepare": "husky install"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*": "cspell --no-must-find-files",
|
||||
"*.js": "eslint --cache"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/webpack/enhanced-resolve.git"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import type { StateCreator, StoreMutatorIdentifier } from 'zustand/vanilla';
|
||||
type SubscribeWithSelector = <T, Mps extends [StoreMutatorIdentifier, unknown][] = [], Mcs extends [StoreMutatorIdentifier, unknown][] = []>(initializer: StateCreator<T, [
|
||||
...Mps,
|
||||
['zustand/subscribeWithSelector', never]
|
||||
], Mcs>) => StateCreator<T, Mps, [['zustand/subscribeWithSelector', never], ...Mcs]>;
|
||||
type Write<T, U> = Omit<T, keyof U> & U;
|
||||
type WithSelectorSubscribe<S> = S extends {
|
||||
getState: () => infer T;
|
||||
} ? Write<S, StoreSubscribeWithSelector<T>> : never;
|
||||
declare module '../vanilla.mjs' {
|
||||
interface StoreMutators<S, A> {
|
||||
['zustand/subscribeWithSelector']: WithSelectorSubscribe<S>;
|
||||
}
|
||||
}
|
||||
type StoreSubscribeWithSelector<T> = {
|
||||
subscribe: {
|
||||
(listener: (selectedState: T, previousSelectedState: T) => void): () => void;
|
||||
<U>(selector: (state: T) => U, listener: (selectedState: U, previousSelectedState: U) => void, options?: {
|
||||
equalityFn?: (a: U, b: U) => boolean;
|
||||
fireImmediately?: boolean;
|
||||
}): () => void;
|
||||
};
|
||||
};
|
||||
export declare const subscribeWithSelector: SubscribeWithSelector;
|
||||
export {};
|
||||
@@ -0,0 +1,40 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = traverseFast;
|
||||
var _index = require("../definitions/index.js");
|
||||
const _skip = Symbol();
|
||||
const _stop = Symbol();
|
||||
function traverseFast(node, enter, opts) {
|
||||
if (!node) return false;
|
||||
const keys = _index.VISITOR_KEYS[node.type];
|
||||
if (!keys) return false;
|
||||
opts = opts || {};
|
||||
const ret = enter(node, opts);
|
||||
if (ret !== undefined) {
|
||||
switch (ret) {
|
||||
case _skip:
|
||||
return false;
|
||||
case _stop:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (const key of keys) {
|
||||
const subNode = node[key];
|
||||
if (!subNode) continue;
|
||||
if (Array.isArray(subNode)) {
|
||||
for (const node of subNode) {
|
||||
if (traverseFast(node, enter, opts)) return true;
|
||||
}
|
||||
} else {
|
||||
if (traverseFast(subNode, enter, opts)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
traverseFast.skip = _skip;
|
||||
traverseFast.stop = _stop;
|
||||
|
||||
//# sourceMappingURL=traverseFast.js.map
|
||||
@@ -0,0 +1 @@
|
||||
module.exports={A:{A:{"1":"F A B","2":"K D E mC"},B:{"1":"0 9 C L M G N O P Q H R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I"},C:{"1":"0 1 2 3 4 5 6 7 8 9 nC LC J PB K D E F A B C L M G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB MC wB NC xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R OC S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I PC EC QC RC oC pC qC rC"},D:{"1":"0 1 2 3 4 5 6 7 8 9 J PB K D E F A B C L M G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB MC wB NC xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I PC EC QC RC"},E:{"1":"J PB K D E F A B C L M G sC SC tC uC vC wC TC FC GC xC yC zC UC VC HC 0C IC WC XC YC ZC aC 1C JC bC cC dC eC fC 2C KC gC hC iC jC 3C"},F:{"1":"0 1 2 3 4 5 6 7 8 F B C G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB wB xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R OC S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z 4C 5C 6C 7C FC kC 8C GC"},G:{"1":"E SC 9C lC AD BD CD DD ED FD GD HD ID JD KD LD MD ND OD PD QD RD SD UC VC HC TD IC WC XC YC ZC aC UD JC bC cC dC eC fC VD KC gC hC iC jC"},H:{"1":"WD"},I:{"1":"LC J I XD YD ZD aD lC bD cD"},J:{"1":"D A"},K:{"1":"A B C H FC kC GC"},L:{"1":"I"},M:{"1":"EC"},N:{"1":"A B"},O:{"1":"HC"},P:{"1":"1 2 3 4 5 6 7 8 J dD eD fD gD hD TC iD jD kD lD mD IC JC KC nD"},Q:{"1":"oD"},R:{"1":"pD"},S:{"1":"qD rD"}},B:1,C:"XHTML served as application/xhtml+xml",D:true};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,169 @@
|
||||
import { beforeAll, describe, expect, it } from 'vitest';
|
||||
import { createRef } from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
|
||||
import { pdfjs } from './index.test.js';
|
||||
|
||||
import Outline from './Outline.js';
|
||||
|
||||
import failingPdf from '../../../__mocks__/_failing_pdf.js';
|
||||
import { loadPDF, makeAsyncCallback, muteConsole, restoreConsole } from '../../../test-utils.js';
|
||||
|
||||
import DocumentContext from './DocumentContext.js';
|
||||
|
||||
import type { PDFDocumentProxy } from 'pdfjs-dist';
|
||||
import type { DocumentContextType } from './shared/types.js';
|
||||
|
||||
type PDFOutline = Awaited<ReturnType<PDFDocumentProxy['getOutline']>>;
|
||||
|
||||
const pdfFile = loadPDF('./../../__mocks__/_pdf.pdf');
|
||||
const pdfFile2 = loadPDF('./../../__mocks__/_pdf2.pdf');
|
||||
|
||||
function renderWithContext(children: React.ReactNode, context: Partial<DocumentContextType>) {
|
||||
const { rerender, ...otherResult } = render(
|
||||
<DocumentContext.Provider value={context as DocumentContextType}>
|
||||
{children}
|
||||
</DocumentContext.Provider>,
|
||||
);
|
||||
|
||||
return {
|
||||
...otherResult,
|
||||
rerender: (
|
||||
nextChildren: React.ReactNode,
|
||||
nextContext: Partial<DocumentContextType> = context,
|
||||
) =>
|
||||
rerender(
|
||||
<DocumentContext.Provider value={nextContext as DocumentContextType}>
|
||||
{nextChildren}
|
||||
</DocumentContext.Provider>,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
describe('Outline', () => {
|
||||
// Loaded PDF file
|
||||
let pdf: PDFDocumentProxy;
|
||||
let pdf2: PDFDocumentProxy;
|
||||
|
||||
// Object with basic loaded outline information that shall match after successful loading
|
||||
let desiredLoadedOutline: PDFOutline;
|
||||
let desiredLoadedOutline2: PDFOutline;
|
||||
|
||||
beforeAll(async () => {
|
||||
pdf = await pdfjs.getDocument({ data: pdfFile.arrayBuffer }).promise;
|
||||
pdf2 = await pdfjs.getDocument({ data: pdfFile2.arrayBuffer }).promise;
|
||||
|
||||
desiredLoadedOutline = await pdf.getOutline();
|
||||
desiredLoadedOutline2 = await pdf2.getOutline();
|
||||
});
|
||||
|
||||
describe('loading', () => {
|
||||
it('loads an outline and calls onLoadSuccess callback properly when placed inside Document', async () => {
|
||||
const { func: onLoadSuccess, promise: onLoadSuccessPromise } = makeAsyncCallback();
|
||||
|
||||
renderWithContext(<Outline onLoadSuccess={onLoadSuccess} />, { pdf });
|
||||
|
||||
expect.assertions(1);
|
||||
|
||||
await expect(onLoadSuccessPromise).resolves.toMatchObject([desiredLoadedOutline]);
|
||||
});
|
||||
|
||||
it('loads an outline and calls onLoadSuccess callback properly when pdf prop is passed', async () => {
|
||||
const { func: onLoadSuccess, promise: onLoadSuccessPromise } = makeAsyncCallback();
|
||||
|
||||
render(<Outline onLoadSuccess={onLoadSuccess} pdf={pdf} />);
|
||||
|
||||
expect.assertions(1);
|
||||
|
||||
await expect(onLoadSuccessPromise).resolves.toMatchObject([desiredLoadedOutline]);
|
||||
});
|
||||
|
||||
it('calls onLoadError when failed to load an outline', async () => {
|
||||
const { func: onLoadError, promise: onLoadErrorPromise } = makeAsyncCallback();
|
||||
|
||||
muteConsole();
|
||||
|
||||
renderWithContext(<Outline onLoadError={onLoadError} />, { pdf: failingPdf });
|
||||
|
||||
expect.assertions(1);
|
||||
|
||||
await expect(onLoadErrorPromise).resolves.toMatchObject([expect.any(Error)]);
|
||||
|
||||
restoreConsole();
|
||||
});
|
||||
|
||||
it('replaces an outline properly when pdf is changed', async () => {
|
||||
const { func: onLoadSuccess, promise: onLoadSuccessPromise } = makeAsyncCallback();
|
||||
|
||||
const { rerender } = renderWithContext(<Outline onLoadSuccess={onLoadSuccess} />, { pdf });
|
||||
|
||||
expect.assertions(2);
|
||||
|
||||
await expect(onLoadSuccessPromise).resolves.toMatchObject([desiredLoadedOutline]);
|
||||
|
||||
const { func: onLoadSuccess2, promise: onLoadSuccessPromise2 } = makeAsyncCallback();
|
||||
|
||||
rerender(<Outline onLoadSuccess={onLoadSuccess2} />, { pdf: pdf2 });
|
||||
|
||||
// It would have been .toMatchObject if not for the fact _pdf2.pdf has no outline
|
||||
await expect(onLoadSuccessPromise2).resolves.toMatchObject([desiredLoadedOutline2]);
|
||||
});
|
||||
|
||||
it('throws an error when placed outside Document without pdf prop passed', () => {
|
||||
muteConsole();
|
||||
|
||||
expect(() => render(<Outline />)).toThrow();
|
||||
|
||||
restoreConsole();
|
||||
});
|
||||
});
|
||||
|
||||
describe('rendering', () => {
|
||||
it('applies className to its wrapper when given a string', async () => {
|
||||
const { func: onLoadSuccess, promise: onLoadSuccessPromise } = makeAsyncCallback();
|
||||
|
||||
const className = 'testClassName';
|
||||
|
||||
const { container } = renderWithContext(
|
||||
<Outline className={className} onLoadSuccess={onLoadSuccess} />,
|
||||
{ pdf },
|
||||
);
|
||||
|
||||
expect.assertions(1);
|
||||
|
||||
await onLoadSuccessPromise;
|
||||
|
||||
const wrapper = container.querySelector('.react-pdf__Outline');
|
||||
|
||||
expect(wrapper).toHaveClass(className);
|
||||
});
|
||||
|
||||
it('passes container element to inputRef properly', async () => {
|
||||
const { func: onLoadSuccess, promise: onLoadSuccessPromise } = makeAsyncCallback();
|
||||
|
||||
const inputRef = createRef<HTMLDivElement>();
|
||||
|
||||
renderWithContext(<Outline inputRef={inputRef} onLoadSuccess={onLoadSuccess} />, { pdf });
|
||||
|
||||
expect.assertions(1);
|
||||
|
||||
await onLoadSuccessPromise;
|
||||
|
||||
expect(inputRef.current).toBeInstanceOf(HTMLDivElement);
|
||||
});
|
||||
|
||||
it('renders OutlineItem components properly', async () => {
|
||||
const { func: onLoadSuccess, promise: onLoadSuccessPromise } = makeAsyncCallback();
|
||||
|
||||
renderWithContext(<Outline onLoadSuccess={onLoadSuccess} />, { pdf });
|
||||
|
||||
expect.assertions(1);
|
||||
|
||||
await onLoadSuccessPromise;
|
||||
|
||||
const items = screen.getAllByRole('listitem');
|
||||
|
||||
expect(items).toHaveLength(5);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,221 @@
|
||||
/**
|
||||
* @fileoverview Rule to flag use of console object
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
defaultOptions: [{}],
|
||||
|
||||
docs: {
|
||||
description: "Disallow the use of `console`",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/no-console",
|
||||
},
|
||||
|
||||
schema: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
allow: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "string",
|
||||
},
|
||||
minItems: 1,
|
||||
uniqueItems: true,
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
|
||||
hasSuggestions: true,
|
||||
|
||||
messages: {
|
||||
unexpected: "Unexpected console statement.",
|
||||
limited:
|
||||
"Unexpected console statement. Only these console methods are allowed: {{ allowed }}.",
|
||||
removeConsole: "Remove the console.{{ propertyName }}().",
|
||||
removeMethodCall: "Remove the console method call.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const [{ allow: allowed = [] }] = context.options;
|
||||
const sourceCode = context.sourceCode;
|
||||
|
||||
/**
|
||||
* Checks whether the given reference is 'console' or not.
|
||||
* @param {eslint-scope.Reference} reference The reference to check.
|
||||
* @returns {boolean} `true` if the reference is 'console'.
|
||||
*/
|
||||
function isConsole(reference) {
|
||||
const id = reference.identifier;
|
||||
|
||||
return id && id.name === "console";
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the property name of the given MemberExpression node
|
||||
* is allowed by options or not.
|
||||
* @param {ASTNode} node The MemberExpression node to check.
|
||||
* @returns {boolean} `true` if the property name of the node is allowed.
|
||||
*/
|
||||
function isAllowed(node) {
|
||||
const propertyName = astUtils.getStaticPropertyName(node);
|
||||
|
||||
return propertyName && allowed.includes(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given reference is a member access which is not
|
||||
* allowed by options or not.
|
||||
* @param {eslint-scope.Reference} reference The reference to check.
|
||||
* @returns {boolean} `true` if the reference is a member access which
|
||||
* is not allowed by options.
|
||||
*/
|
||||
function isMemberAccessExceptAllowed(reference) {
|
||||
const node = reference.identifier;
|
||||
const parent = node.parent;
|
||||
|
||||
return (
|
||||
parent.type === "MemberExpression" &&
|
||||
parent.object === node &&
|
||||
!isAllowed(parent)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if removing the ExpressionStatement node will cause ASI to
|
||||
* break.
|
||||
* eg.
|
||||
* foo()
|
||||
* console.log();
|
||||
* [1, 2, 3].forEach(a => doSomething(a))
|
||||
*
|
||||
* Removing the console.log(); statement should leave two statements, but
|
||||
* here the two statements will become one because [ causes continuation after
|
||||
* foo().
|
||||
* @param {ASTNode} node The ExpressionStatement node to check.
|
||||
* @returns {boolean} `true` if ASI will break after removing the ExpressionStatement
|
||||
* node.
|
||||
*/
|
||||
function maybeAsiHazard(node) {
|
||||
const SAFE_TOKENS_BEFORE = /^[:;{]$/u; // One of :;{
|
||||
const UNSAFE_CHARS_AFTER = /^[-[(/+`]/u; // One of [(/+-`
|
||||
|
||||
const tokenBefore = sourceCode.getTokenBefore(node);
|
||||
const tokenAfter = sourceCode.getTokenAfter(node);
|
||||
|
||||
return (
|
||||
Boolean(tokenAfter) &&
|
||||
UNSAFE_CHARS_AFTER.test(tokenAfter.value) &&
|
||||
tokenAfter.value !== "++" &&
|
||||
tokenAfter.value !== "--" &&
|
||||
Boolean(tokenBefore) &&
|
||||
!SAFE_TOKENS_BEFORE.test(tokenBefore.value)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the MemberExpression node's parent.parent.parent is a
|
||||
* Program, BlockStatement, StaticBlock, or SwitchCase node. This check
|
||||
* is necessary to avoid providing a suggestion that might cause a syntax error.
|
||||
*
|
||||
* eg. if (a) console.log(b), removing console.log() here will lead to a
|
||||
* syntax error.
|
||||
* if (a) { console.log(b) }, removing console.log() here is acceptable.
|
||||
*
|
||||
* Additionally, it checks if the callee of the CallExpression node is
|
||||
* the node itself.
|
||||
*
|
||||
* eg. foo(console.log), cannot provide a suggestion here.
|
||||
* @param {ASTNode} node The MemberExpression node to check.
|
||||
* @returns {boolean} `true` if a suggestion can be provided for a node.
|
||||
*/
|
||||
function canProvideSuggestions(node) {
|
||||
return (
|
||||
node.parent.type === "CallExpression" &&
|
||||
node.parent.callee === node &&
|
||||
node.parent.parent.type === "ExpressionStatement" &&
|
||||
astUtils.STATEMENT_LIST_PARENTS.has(
|
||||
node.parent.parent.parent.type,
|
||||
) &&
|
||||
!maybeAsiHazard(node.parent.parent)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports the given reference as a violation.
|
||||
* @param {eslint-scope.Reference} reference The reference to report.
|
||||
* @returns {void}
|
||||
*/
|
||||
function report(reference) {
|
||||
const node = reference.identifier.parent;
|
||||
|
||||
const suggest = [];
|
||||
|
||||
if (canProvideSuggestions(node)) {
|
||||
const suggestion = {
|
||||
fix(fixer) {
|
||||
return fixer.remove(node.parent.parent);
|
||||
},
|
||||
};
|
||||
|
||||
if (node.computed) {
|
||||
suggestion.messageId = "removeMethodCall";
|
||||
} else {
|
||||
suggestion.messageId = "removeConsole";
|
||||
suggestion.data = { propertyName: node.property.name };
|
||||
}
|
||||
suggest.push(suggestion);
|
||||
}
|
||||
context.report({
|
||||
node,
|
||||
loc: node.loc,
|
||||
messageId: allowed.length ? "limited" : "unexpected",
|
||||
data: { allowed: allowed.join(", ") },
|
||||
suggest,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
"Program:exit"(node) {
|
||||
const scope = sourceCode.getScope(node);
|
||||
const consoleVar = astUtils.getVariableByName(scope, "console");
|
||||
const shadowed = consoleVar && consoleVar.defs.length > 0;
|
||||
|
||||
/*
|
||||
* 'scope.through' includes all references to undefined
|
||||
* variables. If the variable 'console' is not defined, it uses
|
||||
* 'scope.through'.
|
||||
*/
|
||||
const references = consoleVar
|
||||
? consoleVar.references
|
||||
: scope.through.filter(isConsole);
|
||||
|
||||
if (!shadowed) {
|
||||
references
|
||||
.filter(isMemberAccessExceptAllowed)
|
||||
.forEach(report);
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* @fileoverview Rule to disallow assignments where both sides are exactly the same
|
||||
* @author Toru Nagashima
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const SPACES = /\s+/gu;
|
||||
|
||||
/**
|
||||
* Traverses 2 Pattern nodes in parallel, then reports self-assignments.
|
||||
* @param {ASTNode|null} left A left node to traverse. This is a Pattern or
|
||||
* a Property.
|
||||
* @param {ASTNode|null} right A right node to traverse. This is a Pattern or
|
||||
* a Property.
|
||||
* @param {boolean} props The flag to check member expressions as well.
|
||||
* @param {Function} report A callback function to report.
|
||||
* @returns {void}
|
||||
*/
|
||||
function eachSelfAssignment(left, right, props, report) {
|
||||
if (!left || !right) {
|
||||
// do nothing
|
||||
} else if (
|
||||
left.type === "Identifier" &&
|
||||
right.type === "Identifier" &&
|
||||
left.name === right.name
|
||||
) {
|
||||
report(right);
|
||||
} else if (
|
||||
left.type === "ArrayPattern" &&
|
||||
right.type === "ArrayExpression"
|
||||
) {
|
||||
const end = Math.min(left.elements.length, right.elements.length);
|
||||
|
||||
for (let i = 0; i < end; ++i) {
|
||||
const leftElement = left.elements[i];
|
||||
const rightElement = right.elements[i];
|
||||
|
||||
// Avoid cases such as [...a] = [...a, 1]
|
||||
if (
|
||||
leftElement &&
|
||||
leftElement.type === "RestElement" &&
|
||||
i < right.elements.length - 1
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
eachSelfAssignment(leftElement, rightElement, props, report);
|
||||
|
||||
// After a spread element, those indices are unknown.
|
||||
if (rightElement && rightElement.type === "SpreadElement") {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (left.type === "RestElement" && right.type === "SpreadElement") {
|
||||
eachSelfAssignment(left.argument, right.argument, props, report);
|
||||
} else if (
|
||||
left.type === "ObjectPattern" &&
|
||||
right.type === "ObjectExpression" &&
|
||||
right.properties.length >= 1
|
||||
) {
|
||||
/*
|
||||
* Gets the index of the last spread property.
|
||||
* It's possible to overwrite properties followed by it.
|
||||
*/
|
||||
let startJ = 0;
|
||||
|
||||
for (let i = right.properties.length - 1; i >= 0; --i) {
|
||||
const propType = right.properties[i].type;
|
||||
|
||||
if (
|
||||
propType === "SpreadElement" ||
|
||||
propType === "ExperimentalSpreadProperty"
|
||||
) {
|
||||
startJ = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < left.properties.length; ++i) {
|
||||
for (let j = startJ; j < right.properties.length; ++j) {
|
||||
eachSelfAssignment(
|
||||
left.properties[i],
|
||||
right.properties[j],
|
||||
props,
|
||||
report,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
left.type === "Property" &&
|
||||
right.type === "Property" &&
|
||||
right.kind === "init" &&
|
||||
!right.method
|
||||
) {
|
||||
const leftName = astUtils.getStaticPropertyName(left);
|
||||
|
||||
if (
|
||||
leftName !== null &&
|
||||
leftName === astUtils.getStaticPropertyName(right)
|
||||
) {
|
||||
eachSelfAssignment(left.value, right.value, props, report);
|
||||
}
|
||||
} else if (
|
||||
props &&
|
||||
astUtils.skipChainExpression(left).type === "MemberExpression" &&
|
||||
astUtils.skipChainExpression(right).type === "MemberExpression" &&
|
||||
astUtils.isSameReference(left, right)
|
||||
) {
|
||||
report(right);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
|
||||
defaultOptions: [{ props: true }],
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Disallow assignments where both sides are exactly the same",
|
||||
recommended: true,
|
||||
url: "https://eslint.org/docs/latest/rules/no-self-assign",
|
||||
},
|
||||
|
||||
schema: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
props: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
|
||||
messages: {
|
||||
selfAssignment: "'{{name}}' is assigned to itself.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
const [{ props }] = context.options;
|
||||
|
||||
/**
|
||||
* Reports a given node as self assignments.
|
||||
* @param {ASTNode} node A node to report. This is an Identifier node.
|
||||
* @returns {void}
|
||||
*/
|
||||
function report(node) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "selfAssignment",
|
||||
data: {
|
||||
name: sourceCode.getText(node).replace(SPACES, ""),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
AssignmentExpression(node) {
|
||||
if (["=", "&&=", "||=", "??="].includes(node.operator)) {
|
||||
eachSelfAssignment(node.left, node.right, props, report);
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user