dependency-cruiser 17.3.3-beta-3 → 17.3.3-beta-4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dependency-cruiser",
3
- "version": "17.3.3-beta-3",
3
+ "version": "17.3.3-beta-4",
4
4
  "description": "Validate and visualize dependencies. With your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.",
5
5
  "keywords": [
6
6
  "static analysis",
@@ -98,7 +98,10 @@ export default function findContentChanges(
98
98
  );
99
99
 
100
100
  bus.debug("cache: - get (new - cached)");
101
- lDiffCachedVsNew.forEach(({ name }) => lFileSet.delete(name));
101
+ // eslint-disable-next-line budapestian/local-variable-pattern
102
+ for (const { name } of lDiffCachedVsNew) {
103
+ lFileSet.delete(name);
104
+ }
102
105
 
103
106
  const lDiffNewVsCached = [];
104
107
  for (const lFileName of lFileSet) {
@@ -45,8 +45,8 @@ function buildNotToTestRule(pInitOptions) {
45
45
  }
46
46
  },`;
47
47
  return pInitOptions.hasTestsOutsideSource
48
- ? lNotToTestRule.replace(
49
- /{{testLocationRE}}/g,
48
+ ? lNotToTestRule.replaceAll(
49
+ "{{testLocationRE}}",
50
50
  folderNameArrayToRE(pInitOptions?.testLocation ?? []),
51
51
  )
52
52
  : "";
@@ -211,12 +211,12 @@ function buildBuiltInModulesAttribute(pInitOptions) {
211
211
  */
212
212
  export default function buildConfig(pInitOptions) {
213
213
  return configTemplate
214
- .replace(
215
- /{{sourceLocationRE}}/g,
214
+ .replaceAll(
215
+ "{{sourceLocationRE}}",
216
216
  folderNameArrayToRE(pInitOptions.sourceLocation),
217
217
  )
218
- .replace(
219
- /{{resolutionExtensionsAsString}}/g,
218
+ .replaceAll(
219
+ "{{resolutionExtensionsAsString}}",
220
220
  extensionsToString(pInitOptions.resolutionExtensions),
221
221
  )
222
222
  .replace("{{notToTestRule}}", buildNotToTestRule(pInitOptions))
@@ -5,7 +5,7 @@
5
5
  */
6
6
  export function folderNameArrayToRE(pArrayOfStrings) {
7
7
  const lFoldersInARE = pArrayOfStrings
8
- .map((pName) => pName.replace(/\\/g, "\\\\").replace(/\./g, "\\."))
8
+ .map((pName) => pName.replaceAll("\\", "\\\\").replaceAll(".", "\\."))
9
9
  .join("|");
10
10
 
11
11
  return `^(${lFoldersInARE})`;
@@ -1,11 +1,10 @@
1
- /* eslint-disable security/detect-non-literal-regexp */
2
1
  /* eslint-disable security/detect-object-injection, no-inline-comments */
3
2
  import {
4
3
  matchToModulePath,
5
4
  matchToModulePathNot,
6
5
  } from "#validate/matchers.mjs";
7
6
  import IndexedModuleGraph from "#graph-utl/indexed-module-graph.mjs";
8
- import { extractGroups } from "#utl/regex-util.mjs";
7
+ import { getCachedRegExp, extractGroups } from "#utl/regex-util.mjs";
9
8
 
10
9
  function isReachableRule(pRule) {
11
10
  return Object.hasOwn(pRule?.to ?? {}, "reachable");
@@ -19,16 +18,25 @@ function getReachableRules(pRuleSet) {
19
18
  }
20
19
 
21
20
  function isModuleInRuleFrom(pRule) {
21
+ const lRuleFrom = pRule.from ?? pRule.module;
22
+ if (!lRuleFrom) {
23
+ return () => false;
24
+ }
25
+ const lRuleFromPathRE = lRuleFrom.path
26
+ ? getCachedRegExp(lRuleFrom.path)
27
+ : null;
28
+ const lRuleFromPathNotRE = lRuleFrom.pathNot
29
+ ? getCachedRegExp(lRuleFrom.pathNot)
30
+ : null;
31
+
22
32
  return (pModule) => {
23
- const lRuleFrom = pRule.from ?? pRule.module;
24
- if (lRuleFrom) {
25
- return (
26
- (!lRuleFrom.path || new RegExp(lRuleFrom.path).test(pModule.source)) &&
27
- (!lRuleFrom.pathNot ||
28
- !new RegExp(lRuleFrom.pathNot).test(pModule.source))
29
- );
33
+ if (lRuleFromPathRE && !lRuleFromPathRE.test(pModule.source)) {
34
+ return false;
35
+ }
36
+ if (lRuleFromPathNotRE && lRuleFromPathNotRE.test(pModule.source)) {
37
+ return false;
30
38
  }
31
- return false;
39
+ return true;
32
40
  };
33
41
  }
34
42
 
@@ -146,7 +146,7 @@ function resolveWithRetry(
146
146
  lReturnValue.couldNotResolve &&
147
147
  canBeResolvedToTsVariant(lStrippedModuleName)
148
148
  ) {
149
- const lModuleWithoutExtension = lStrippedModuleName.replace(
149
+ const lModuleWithoutExtension = lStrippedModuleName.replaceAll(
150
150
  /\.(js|jsx|cjs|mjs)$/g,
151
151
  "",
152
152
  );
@@ -225,9 +225,8 @@ export default function resolve(
225
225
  // enhanced-resolve inserts a NULL character in front of any `#` character.
226
226
  // This wonky replace corrects that so the filename again corresponds
227
227
  // with a real file on disk
228
- const lResolvedEHRCorrected = lResolvedDependency.resolved.replace(
229
- // eslint-disable-next-line no-control-regex
230
- /\u0000#/g,
228
+ const lResolvedEHRCorrected = lResolvedDependency.resolved.replaceAll(
229
+ "\u0000#",
231
230
  "#",
232
231
  );
233
232
  const lResolvedYarnVirtual = resolveYarnVirtual(
@@ -3,9 +3,9 @@ import { isAbsolute, resolve as path_resolve } from "node:path";
3
3
  import { join as posix_join } from "node:path/posix";
4
4
  import picomatch from "picomatch";
5
5
  import getExtension from "#utl/get-extension.mjs";
6
+ import { getCachedRegExp } from "#utl/regex-util.mjs";
6
7
 
7
8
  /**
8
- * @import { IResolveOptions } from "../../../types/resolve-options.mjs"
9
9
  * @import { ITranspileOptions } from "../../../types/dependency-cruiser.mjs"
10
10
  */
11
11
 
@@ -108,10 +108,8 @@ function isSubpathImport(pModuleName, pManifest) {
108
108
  // replacement only.
109
109
  // Quoting https://nodejs.org/api/packages.html#subpath-imports :
110
110
  // > "* maps expose nested subpaths as it is a string replacement syntax only"
111
- const lMatchREasString = pImportLHS.replace(/\*/g, ".+");
112
- // eslint-disable-next-line security/detect-non-literal-regexp
113
- const lMatchRE = new RegExp(`^${lMatchREasString}$`);
114
- return lMatchRE.test(pModuleName);
111
+ const lMatchREasString = pImportLHS.replaceAll("*", ".+");
112
+ return getCachedRegExp(`^${lMatchREasString}$`).test(pModuleName);
115
113
  })
116
114
  );
117
115
  }
@@ -226,11 +224,9 @@ function matchesTSConfigPaths(pModuleName, pPaths) {
226
224
  //
227
225
  // TODO: 'any string' - does this include the empty string as well? Checks seem
228
226
  // to indicate it doesn't, so we use `.+` instead of `.*`
229
- return Object.keys(pPaths).some((pPathLHS) => {
230
- // eslint-disable-next-line security/detect-non-literal-regexp
231
- const lMatchRE = new RegExp(`^${pPathLHS.replace(/\*/g, ".+")}$`);
232
- return lMatchRE.test(pModuleName);
233
- });
227
+ return Object.keys(pPaths).some((pPathLHS) =>
228
+ getCachedRegExp(`^${pPathLHS.replaceAll("*", ".+")}$`).test(pModuleName),
229
+ );
234
230
  }
235
231
 
236
232
  function stripExtension(pModulePath) {
@@ -560,7 +560,6 @@ export default function extractTypeScriptDependencies(
560
560
  pDetectJSDocImports,
561
561
  pDetectProcessBuiltinModuleCalls,
562
562
  ) {
563
- // console.dir(pTypeScriptAST, { depth: 100 });
564
563
  return typescript
565
564
  ? extractImports(pTypeScriptAST)
566
565
  .concat(extractExports(pTypeScriptAST))
@@ -1,9 +1,12 @@
1
1
  import consolidateModules from "./consolidate-modules.mjs";
2
2
  import consolidateModuleDependencies from "./consolidate-module-dependencies.mjs";
3
+ import { getCachedRegExp } from "#utl/regex-util.mjs";
3
4
 
4
5
  function squashDependencyToPattern(pCollapsePattern) {
5
6
  return (pDependency) => {
6
- const lCollapseMatch = pDependency.resolved.match(pCollapsePattern);
7
+ const lCollapseMatch = getCachedRegExp(pCollapsePattern).exec(
8
+ pDependency.resolved,
9
+ );
7
10
 
8
11
  return {
9
12
  ...pDependency,
@@ -27,7 +30,9 @@ function determineConsolidatedness(pConsolidated, pCollapseMatch, pSource) {
27
30
 
28
31
  function squashModuleToPattern(pCollapsePattern) {
29
32
  return (pModule) => {
30
- const lCollapseMatch = pModule.source.match(pCollapsePattern);
33
+ const lCollapseMatch = getCachedRegExp(pCollapsePattern).exec(
34
+ pModule.source,
35
+ );
31
36
 
32
37
  return {
33
38
  ...pModule,
@@ -1,5 +1,7 @@
1
+ import { getCachedRegExp } from "#utl/regex-util.mjs";
2
+
1
3
  export function filenameMatchesPattern(pFullPathToFile, pPattern) {
2
- return RegExp(pPattern, "g").test(pFullPathToFile);
4
+ return getCachedRegExp(pPattern).test(pFullPathToFile);
3
5
  }
4
6
 
5
7
  export function moduleMatchesFilter(pModule, pFilter) {
@@ -3,6 +3,7 @@ import { assertCruiseOptionsValid } from "./options/assert-validity.mjs";
3
3
  import { normalizeCruiseOptions } from "./options/normalize.mjs";
4
4
  import reportWrap from "./report-wrap.mjs";
5
5
  import { bus } from "#utl/bus.mjs";
6
+ import { clearRegExpCache } from "#utl/regex-util.mjs";
6
7
 
7
8
  const TOTAL_STEPS = 10;
8
9
 
@@ -104,5 +105,10 @@ export default async function cruise(
104
105
  }
105
106
 
106
107
  bus.summary("report", c(9));
107
- return await reportWrap(lCruiseResult, lCruiseOptions);
108
+ const lResult = await reportWrap(lCruiseResult, lCruiseOptions);
109
+
110
+ bus.debug("clear regex cache");
111
+ clearRegExpCache();
112
+
113
+ return lResult;
108
114
  }
package/src/meta.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  /* generated - don't edit */
2
2
  module.exports = {
3
- version: "17.3.3-beta-3",
3
+ version: "17.3.3-beta-4",
4
4
  engines: {
5
5
  node: "^20.12||^22||>=24",
6
6
  },
@@ -1,3 +1,4 @@
1
+ import { clearCache } from "./anonymize-path-element.mjs";
1
2
  import { anonymizePath, WHITELIST_RE } from "./anonymize-path.mjs";
2
3
 
3
4
  const EOL = "\n";
@@ -148,7 +149,7 @@ function anonymize(pResults, pWordList) {
148
149
 
149
150
  function sanitizeWordList(pWordList) {
150
151
  return pWordList
151
- .map((pString) => pString.replace(/[^a-zA-Z-]/g, "_"))
152
+ .map((pString) => pString.replaceAll(/[^a-zA-Z-]/g, "_"))
152
153
  .filter(
153
154
  (pString) =>
154
155
  /^[a-zA-Z-_]+$/g.test(pString) && !WHITELIST_RE.test(pString),
@@ -184,7 +185,7 @@ export default function reportAnonymous(pResults, pAnonymousReporterOptions) {
184
185
  lAnonymousReporterOptions.wordlist =
185
186
  pResults?.summary?.optionsUsed?.reporterOptions?.anon?.wordlist ?? [];
186
187
  }
187
- return {
188
+ const lReturnValue = {
188
189
  output:
189
190
  JSON.stringify(
190
191
  anonymize(
@@ -196,4 +197,6 @@ export default function reportAnonymous(pResults, pAnonymousReporterOptions) {
196
197
  ) + EOL,
197
198
  exitCode: 0,
198
199
  };
200
+ clearCache();
201
+ return lReturnValue;
199
202
  }
@@ -270,7 +270,7 @@ function skewLineABit(lDrawingInstructions) {
270
270
  // Even this value is so small that it is not visible to the
271
271
  // human eye (tested with the two I have at my disposal).
272
272
  var lIncrement = 0.001;
273
- var lNewLastValue = parseFloat(lLastValue) + lIncrement;
273
+ var lNewLastValue = Number.parseFloat(lLastValue) + lIncrement;
274
274
 
275
275
  return lDrawingInstructions.replace(lLastValue, lNewLastValue);
276
276
  }
@@ -106,10 +106,10 @@ function focusHighlights(pModules, pNamesHashMap) {
106
106
 
107
107
  const hashToReadableNodeName = (pNode) =>
108
108
  pNode
109
- .replace(ACORN_DUMMY_VALUE, "__unknown__")
110
- .replace(/^\.$|^\.\//g, "__currentPath__")
111
- .replace(/^\.{2}$|^\.{2}\//g, "__prevPath__")
112
- .replace(/[[\]/.@~-]/g, "_");
109
+ .replaceAll(ACORN_DUMMY_VALUE, "__unknown__")
110
+ .replaceAll(/^\.$|^\.\//g, "__currentPath__")
111
+ .replaceAll(/^\.{2}$|^\.{2}\//g, "__prevPath__")
112
+ .replaceAll(/[[\]/.@~-]/g, "_");
113
113
 
114
114
  /**
115
115
  * @param {import("../../types/cruise-result").IModule[]} pModules
@@ -43,7 +43,7 @@ async function getPluginReporter(pOutputType) {
43
43
 
44
44
  export function getExternalPluginReporter(pOutputType) {
45
45
  const lPluginPatternRE = /^plugin:(?<pluginName>.+)$/;
46
- const lPluginMatch = (pOutputType || "").match(lPluginPatternRE);
46
+ const lPluginMatch = lPluginPatternRE.exec(pOutputType || "");
47
47
 
48
48
  if (lPluginMatch?.groups) {
49
49
  return getPluginReporter(lPluginMatch.groups.pluginName);
@@ -19,18 +19,18 @@ function escape(pMessageString) {
19
19
  return (
20
20
  pMessageString
21
21
  .toString()
22
- .replace(/\|/g, "||")
23
- .replace(/\n/g, "|n")
24
- .replace(/\r/g, "|r")
25
- .replace(/\[/g, "|[")
26
- .replace(/\]/g, "|]")
22
+ .replaceAll("|", "||")
23
+ .replaceAll("\n", "|n")
24
+ .replaceAll("\r", "|r")
25
+ .replaceAll("[", "|[")
26
+ .replaceAll("]", "|]")
27
27
  // next line
28
- .replace(/\u0085/g, "|x")
28
+ .replaceAll("\u0085", "|x")
29
29
  // line separator
30
- .replace(/\u2028/g, "|l")
30
+ .replaceAll("\u2028", "|l")
31
31
  // paragraph separator
32
- .replace(/\u2029/g, "|p")
33
- .replace(/'/g, "|'")
32
+ .replaceAll("\u2029", "|p")
33
+ .replaceAll("'", "|'")
34
34
  );
35
35
  }
36
36
 
@@ -48,7 +48,7 @@ function smartURIConcat(pPrefix, pSource) {
48
48
  function deriveExternalPackageName(pSource) {
49
49
  const lRE =
50
50
  /node_modules\/(?<packageName>[^@][^/]+)|(?<atPackageName>@[^/]+\/[^/]+)/;
51
- const lMatch = pSource.match(lRE);
51
+ const lMatch = lRE.exec(pSource);
52
52
  if (lMatch) {
53
53
  return lMatch.groups.packageName || lMatch.groups.atPackageName;
54
54
  }
@@ -72,7 +72,7 @@ function deriveCorePackageName(pSource) {
72
72
  */
73
73
  export function getURLForModule(pModule, pPrefix, pSuffix) {
74
74
  // TODO: derive the URLs from configuration
75
- if (pModule.dependencyTypes?.some((pType) => pType === "core")) {
75
+ if (pModule.dependencyTypes?.includes("core")) {
76
76
  const lPackageName = deriveCorePackageName(pModule.source);
77
77
  // Check if it's a Bun core module (starts with bun:)
78
78
  if (lPackageName.startsWith("bun:")) {
@@ -16,7 +16,7 @@ const EXTENSION_RE = /(?<extension>(?:(?:\.d\.(?:[cm])?ts)|\.coffee\.md)$)/;
16
16
  * @return {string} extension
17
17
  */
18
18
  export default function getExtension(pFileName) {
19
- const lMatchResult = pFileName.match(EXTENSION_RE);
19
+ const lMatchResult = EXTENSION_RE.exec(pFileName);
20
20
 
21
21
  return lMatchResult?.groups?.extension ?? extname(pFileName);
22
22
  }
@@ -1,3 +1,25 @@
1
+ /* eslint-disable security/detect-non-literal-regexp */
2
+ const REGEXP_CACHE = new Map();
3
+
4
+ /**
5
+ * Returns a cached RegExp instance for the given pattern.
6
+ *
7
+ * See ./regex-cache.md for design considerations
8
+ *
9
+ * @param {string} pPattern
10
+ * @returns {RegExp}
11
+ */
12
+ export function getCachedRegExp(pPattern) {
13
+ if (!REGEXP_CACHE.has(pPattern)) {
14
+ REGEXP_CACHE.set(pPattern, new RegExp(pPattern));
15
+ }
16
+ return REGEXP_CACHE.get(pPattern);
17
+ }
18
+
19
+ export function clearRegExpCache() {
20
+ REGEXP_CACHE.clear();
21
+ }
22
+
1
23
  /**
2
24
  * If there is at least one group expression in the given pRulePath
3
25
  * return the first matched one.
@@ -19,7 +41,7 @@ export function extractGroups(pFromRestriction, pActualPath) {
19
41
  // except before it enters here it has already been 'normalized' to a string
20
42
  // so it can be safely passed to match. The right solution here (TODO)
21
43
  // is to create a separate type for NormalizedFromRestriction
22
- let lMatchResult = pActualPath.match(pFromRestriction.path);
44
+ let lMatchResult = getCachedRegExp(pFromRestriction.path).exec(pActualPath);
23
45
 
24
46
  if (lMatchResult && lMatchResult.length > 1) {
25
47
  lReturnValue = lMatchResult.filter(
@@ -49,8 +71,7 @@ export function extractGroups(pFromRestriction, pActualPath) {
49
71
  export function replaceGroupPlaceholders(pString, pExtractedGroups) {
50
72
  return pExtractedGroups.reduce(
51
73
  (pAll, pThis, pIndex) =>
52
- // eslint-disable-next-line security/detect-non-literal-regexp
53
- pAll.replace(new RegExp(`\\$${pIndex}`, "g"), pThis),
74
+ pAll.replaceAll(new RegExp(`\\$${pIndex}`, "g"), pThis),
54
75
  pString,
55
76
  );
56
77
  }
@@ -1,9 +1,7 @@
1
1
  const DEFAULT_INDENT = 4;
2
2
 
3
3
  function indentString(pString, pCount) {
4
- const lRegex = /^(?!\s*$)/gm;
5
-
6
- return pString.replace(lRegex, " ".repeat(pCount));
4
+ return pString.replaceAll(/^(?!\s*$)/gm, " ".repeat(pCount));
7
5
  }
8
6
 
9
7
  /**
@@ -1,23 +1,28 @@
1
- /* eslint-disable security/detect-non-literal-regexp */
2
1
  import { isModuleOnlyRule, isFolderScope } from "./rule-classifiers.mjs";
3
2
  import { propertyEquals, matchesToIsMoreUnstable } from "./matchers.mjs";
4
- import { extractGroups, replaceGroupPlaceholders } from "#utl/regex-util.mjs";
3
+ import {
4
+ getCachedRegExp,
5
+ extractGroups,
6
+ replaceGroupPlaceholders,
7
+ } from "#utl/regex-util.mjs";
5
8
 
6
9
  function fromFolderPath(pRule, pFromFolder) {
7
- return !pRule.from.path || new RegExp(pRule.from.path).test(pFromFolder.name);
10
+ return (
11
+ !pRule.from.path || getCachedRegExp(pRule.from.path).test(pFromFolder.name)
12
+ );
8
13
  }
9
14
 
10
15
  function fromFolderPathNot(pRule, pFromFolder) {
11
16
  return (
12
17
  !pRule.from.pathNot ||
13
- !new RegExp(pRule.from.pathNot).test(pFromFolder.name)
18
+ !getCachedRegExp(pRule.from.pathNot).test(pFromFolder.name)
14
19
  );
15
20
  }
16
21
 
17
22
  function toFolderPath(pRule, pToFolder, pGroups) {
18
23
  return (
19
24
  !pRule.to.path ||
20
- new RegExp(replaceGroupPlaceholders(pRule.to.path, pGroups)).test(
25
+ getCachedRegExp(replaceGroupPlaceholders(pRule.to.path, pGroups)).test(
21
26
  pToFolder.name,
22
27
  )
23
28
  );
@@ -26,7 +31,7 @@ function toFolderPath(pRule, pToFolder, pGroups) {
26
31
  function toFolderPathNot(pRule, pToFolder, pGroups) {
27
32
  return (
28
33
  !pRule.to.pathNot ||
29
- !new RegExp(replaceGroupPlaceholders(pRule.to.pathNot, pGroups)).test(
34
+ !getCachedRegExp(replaceGroupPlaceholders(pRule.to.pathNot, pGroups)).test(
30
35
  pToFolder.name,
31
36
  )
32
37
  );
@@ -1,4 +1,3 @@
1
- /* eslint-disable security/detect-non-literal-regexp */
2
1
  import {
3
2
  matchToModulePath,
4
3
  matchToModulePathNot,
@@ -7,7 +6,7 @@ import {
7
6
  matchesModulePath,
8
7
  matchesModulePathNot,
9
8
  } from "./matchers.mjs";
10
- import { extractGroups } from "#utl/regex-util.mjs";
9
+ import { getCachedRegExp, extractGroups } from "#utl/regex-util.mjs";
11
10
 
12
11
  /**
13
12
  * @import { IModule } from "../../types/cruise-result.mjs";
@@ -99,8 +98,9 @@ export function matchesReachesRule(pRule, pModule) {
99
98
  function dependentsCountsMatch(pRule, pDependents) {
100
99
  const lMatchingDependentsCount = pDependents.filter(
101
100
  (pDependent) =>
102
- (!pRule.from.path || new RegExp(pRule.from.path).test(pDependent)) &&
103
- (!pRule.from.pathNot || !new RegExp(pRule.from.pathNot).test(pDependent)),
101
+ (!pRule.from.path || getCachedRegExp(pRule.from.path).test(pDependent)) &&
102
+ (!pRule.from.pathNot ||
103
+ !getCachedRegExp(pRule.from.pathNot).test(pDependent)),
104
104
  ).length;
105
105
  return (
106
106
  (!pRule.module.numberOfDependentsLessThan ||
@@ -1,7 +1,6 @@
1
- /* eslint-disable security/detect-non-literal-regexp */
2
1
  /* eslint-disable security/detect-object-injection */
3
2
  import { dirname, resolve, sep } from "node:path/posix";
4
- import { replaceGroupPlaceholders } from "#utl/regex-util.mjs";
3
+ import { getCachedRegExp, replaceGroupPlaceholders } from "#utl/regex-util.mjs";
5
4
  import { intersects } from "#utl/array-util.mjs";
6
5
 
7
6
  // by their nature some dependency types always occur alongside other
@@ -33,7 +32,7 @@ export function propertyMatches(pRule, pDependency, pRuleProperty, pProperty) {
33
32
  return (
34
33
  !pRule.to[pRuleProperty] ||
35
34
  (pDependency[pProperty] &&
36
- new RegExp(pRule.to[pRuleProperty]).test(pDependency[pProperty]))
35
+ getCachedRegExp(pRule.to[pRuleProperty]).test(pDependency[pProperty]))
37
36
  );
38
37
  }
39
38
 
@@ -46,37 +45,43 @@ export function propertyMatchesNot(
46
45
  return (
47
46
  !pRule.to[pRuleProperty] ||
48
47
  (pDependency[pProperty] &&
49
- !new RegExp(pRule.to[pRuleProperty]).test(pDependency[pProperty]))
48
+ !getCachedRegExp(pRule.to[pRuleProperty]).test(pDependency[pProperty]))
50
49
  );
51
50
  }
52
51
 
53
52
  export function matchesFromPath(pRule, pModule) {
54
- return !pRule.from.path || new RegExp(pRule.from.path).test(pModule.source);
53
+ return (
54
+ !pRule.from.path || getCachedRegExp(pRule.from.path).test(pModule.source)
55
+ );
55
56
  }
56
57
 
57
58
  export function matchesFromPathNot(pRule, pModule) {
58
59
  return (
59
- !pRule.from.pathNot || !new RegExp(pRule.from.pathNot).test(pModule.source)
60
+ !pRule.from.pathNot ||
61
+ !getCachedRegExp(pRule.from.pathNot).test(pModule.source)
60
62
  );
61
63
  }
62
64
 
63
65
  export function matchesModulePath(pRule, pModule) {
64
66
  return (
65
- !pRule.module.path || new RegExp(pRule.module.path).test(pModule.source)
67
+ !pRule.module.path ||
68
+ getCachedRegExp(pRule.module.path).test(pModule.source)
66
69
  );
67
70
  }
68
71
 
69
72
  export function matchesModulePathNot(pRule, pModule) {
70
73
  return (
71
74
  !pRule.module.pathNot ||
72
- !new RegExp(pRule.module.pathNot).test(pModule.source)
75
+ !getCachedRegExp(pRule.module.pathNot).test(pModule.source)
73
76
  );
74
77
  }
75
78
 
76
79
  function _matchesToPath(pRule, pString, pGroups = []) {
77
80
  return (
78
81
  !pRule.to.path ||
79
- new RegExp(replaceGroupPlaceholders(pRule.to.path, pGroups)).test(pString)
82
+ getCachedRegExp(replaceGroupPlaceholders(pRule.to.path, pGroups)).test(
83
+ pString,
84
+ )
80
85
  );
81
86
  }
82
87
 
@@ -91,7 +96,7 @@ export function matchToModulePath(pRule, pModule, pGroups) {
91
96
  function _matchesToPathNot(pRule, pString, pGroups = []) {
92
97
  return (
93
98
  !pRule.to.pathNot ||
94
- !new RegExp(replaceGroupPlaceholders(pRule.to.pathNot, pGroups)).test(
99
+ !getCachedRegExp(replaceGroupPlaceholders(pRule.to.pathNot, pGroups)).test(
95
100
  pString,
96
101
  )
97
102
  );
@@ -124,14 +129,14 @@ export function matchesToVia(pRule, pDependency, pGroups) {
124
129
  if (pRule.to.via && pDependency.cycle) {
125
130
  if (pRule.to.via.path) {
126
131
  lReturnValue = pDependency.cycle.some(({ name }) =>
127
- new RegExp(replaceGroupPlaceholders(pRule.to.via.path, pGroups)).test(
128
- name,
129
- ),
132
+ getCachedRegExp(
133
+ replaceGroupPlaceholders(pRule.to.via.path, pGroups),
134
+ ).test(name),
130
135
  );
131
136
  }
132
137
  if (pRule.to.via.pathNot) {
133
138
  lReturnValue = !pDependency.cycle.every(({ name }) =>
134
- new RegExp(
139
+ getCachedRegExp(
135
140
  replaceGroupPlaceholders(pRule.to.via.pathNot, pGroups),
136
141
  ).test(name),
137
142
  );
@@ -159,14 +164,14 @@ export function matchesToViaOnly(pRule, pDependency, pGroups) {
159
164
  if (pRule.to.viaOnly && pDependency.cycle) {
160
165
  if (pRule.to.viaOnly.path) {
161
166
  lReturnValue = pDependency.cycle.every(({ name }) =>
162
- new RegExp(
167
+ getCachedRegExp(
163
168
  replaceGroupPlaceholders(pRule.to.viaOnly.path, pGroups),
164
169
  ).test(name),
165
170
  );
166
171
  }
167
172
  if (pRule.to.viaOnly.pathNot) {
168
173
  lReturnValue = !pDependency.cycle.some(({ name }) =>
169
- new RegExp(
174
+ getCachedRegExp(
170
175
  replaceGroupPlaceholders(pRule.to.viaOnly.pathNot, pGroups),
171
176
  ).test(name),
172
177
  );