| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -28,14 +28,15 @@ const { | |||
| 28 | 28 | ReflectGetOwnPropertyDescriptor, | |
| 29 | 29 | ReflectOwnKeys, | |
| 30 | 30 | RegExpPrototypeExec, | |
| 31 | - RegExpPrototypeSymbolReplace, | ||
| 32 | 31 | SafeMap, | |
| 33 | - SafePromiseAll, | ||
| 32 | + SafePromiseAllReturnArrayLike, | ||
| 33 | + SafePromiseAllReturnVoid, | ||
| 34 | 34 | String, | |
| 35 | 35 | StringFromCharCode, | |
| 36 | 36 | StringPrototypeEndsWith, | |
| 37 | 37 | StringPrototypeIncludes, | |
| 38 | 38 | StringPrototypeRepeat, | |
| 39 | + StringPrototypeReplaceAll, | ||
| 39 | 40 | StringPrototypeSlice, | |
| 40 | 41 | StringPrototypeSplit, | |
| 41 | 42 | StringPrototypeStartsWith, | |
@@ -53,7 +54,7 @@ const Repl = require('repl'); | |||
| 53 | 54 | const vm = require('vm'); | |
| 54 | 55 | const { fileURLToPath } = require('internal/url'); | |
| 55 | 56 | ||
| 56 | - const { customInspectSymbol } = require('internal/util'); | ||
| 57 | + const { customInspectSymbol, SideEffectFreeRegExpPrototypeSymbolReplace } = require('internal/util'); | ||
| 57 | 58 | const { inspect: utilInspect } = require('internal/util/inspect'); | |
| 58 | 59 | const debuglog = require('internal/util/debuglog').debuglog('inspect'); | |
| 59 | 60 | ||
@@ -121,7 +122,7 @@ const { | |||
| 121 | 122 | } = internalBinding('builtins'); | |
| 122 | 123 | const NATIVES = internalBinding('natives'); | |
| 123 | 124 | function isNativeUrl(url) { | |
| 124 | - url = RegExpPrototypeSymbolReplace(/\.js$/, url, ''); | ||
| 125 | + url = SideEffectFreeRegExpPrototypeSymbolReplace(/\.js$/, url, ''); | ||
| 125 | 126 | ||
| 126 | 127 | return StringPrototypeStartsWith(url, 'node:internal/') || | |
| 127 | 128 | ArrayPrototypeIncludes(PUBLIC_BUILTINS, url) || | |
@@ -159,8 +160,8 @@ function markSourceColumn(sourceText, position, useColors) { | |||
| 159 | 160 | ||
| 160 | 161 | // Colourize char if stdout supports colours | |
| 161 | 162 | if (useColors) { | |
| 162 | - tail = RegExpPrototypeSymbolReplace(/(.+?)([^\w]|$)/, tail, | ||
| 163 | - '\u001b[32m$1\u001b[39m$2'); | ||
| 163 | + tail = SideEffectFreeRegExpPrototypeSymbolReplace(/(.+?)([^\w]|$)/, tail, | ||
| 164 | + '\u001b[32m$1\u001b[39m$2'); | ||
| 164 | 165 | } | |
| 165 | 166 | ||
| 166 | 167 | // Return source line with coloured char at `position` | |
@@ -340,9 +341,9 @@ class ScopeSnapshot { | |||
| 340 | 341 | StringPrototypeSlice(this.type, 1); | |
| 341 | 342 | const name = this.name ? `<${this.name}>` : ''; | |
| 342 | 343 | const prefix = `${type}${name} `; | |
| 343 | - return RegExpPrototypeSymbolReplace(/^Map /, | ||
| 344 | - utilInspect(this.properties, opts), | ||
| 345 | - prefix); | ||
| 344 | + return SideEffectFreeRegExpPrototypeSymbolReplace(/^Map /, | ||
| 345 | + utilInspect(this.properties, opts), | ||
| 346 | + prefix); | ||
| 346 | 347 | } | |
| 347 | 348 | } | |
| 348 | 349 | ||
@@ -517,7 +518,7 @@ function createRepl(inspector) { | |||
| 517 | 518 | } | |
| 518 | 519 | ||
| 519 | 520 | loadScopes() { | |
| 520 | - return SafePromiseAll( | ||
| 521 | + return SafePromiseAllReturnArrayLike( | ||
| 521 | 522 | ArrayPrototypeFilter( | |
| 522 | 523 | this.scopeChain, | |
| 523 | 524 | (scope) => scope.type !== 'global' | |
@@ -656,14 +657,14 @@ function createRepl(inspector) { | |||
| 656 | 657 | (error) => `<${error.message}>`); | |
| 657 | 658 | const lastIndex = watchedExpressions.length - 1; | |
| 658 | 659 | ||
| 659 | - const values = await SafePromiseAll(watchedExpressions, inspectValue); | ||
| 660 | + const values = await SafePromiseAllReturnArrayLike(watchedExpressions, inspectValue); | ||
| 660 | 661 | const lines = ArrayPrototypeMap(watchedExpressions, (expr, idx) => { | |
| 661 | 662 | const prefix = `${leftPad(idx, ' ', lastIndex)}: ${expr} =`; | |
| 662 | 663 | const value = inspect(values[idx]); | |
| 663 | 664 | if (!StringPrototypeIncludes(value, '\n')) { | |
| 664 | 665 | return `${prefix} ${value}`; | |
| 665 | 666 | } | |
| 666 | - return `${prefix}\n ${RegExpPrototypeSymbolReplace(/\n/g, value, '\n ')}`; | ||
| 667 | + return `${prefix}\n ${StringPrototypeReplaceAll(value, '\n', '\n ')}`; | ||
| 667 | 668 | }); | |
| 668 | 669 | const valueList = ArrayPrototypeJoin(lines, '\n'); | |
| 669 | 670 | return verbose ? `Watchers:\n${valueList}\n` : valueList; | |
@@ -805,8 +806,8 @@ function createRepl(inspector) { | |||
| 805 | 806 | registerBreakpoint); | |
| 806 | 807 | } | |
| 807 | 808 | ||
| 808 | - const escapedPath = RegExpPrototypeSymbolReplace(/([/\\.?*()^${}|[\]])/g, | ||
| 809 | - script, '\\$1'); | ||
| 809 | + const escapedPath = SideEffectFreeRegExpPrototypeSymbolReplace(/([/\\.?*()^${}|[\]])/g, | ||
| 810 | + script, '\\$1'); | ||
| 810 | 811 | const urlRegex = `^(.*[\\/\\\\])?${escapedPath}$`; | |
| 811 | 812 | ||
| 812 | 813 | return PromisePrototypeThen( | |
@@ -860,9 +861,9 @@ function createRepl(inspector) { | |||
| 860 | 861 | location.lineNumber + 1)); | |
| 861 | 862 | if (!newBreakpoints.length) return PromiseResolve(); | |
| 862 | 863 | return PromisePrototypeThen( | |
| 863 | - SafePromiseAll(newBreakpoints), | ||
| 864 | - (results) => { | ||
| 865 | - print(`${results.length} breakpoints restored.`); | ||
| 864 | + SafePromiseAllReturnVoid(newBreakpoints), | ||
| 865 | + () => { | ||
| 866 | + print(`${newBreakpoints.length} breakpoints restored.`); | ||
| 866 | 867 | }); | |
| 867 | 868 | } | |
| 868 | 869 | ||
@@ -896,7 +897,7 @@ function createRepl(inspector) { | |||
| 896 | 897 | ||
| 897 | 898 | inspector.suspendReplWhile(() => | |
| 898 | 899 | PromisePrototypeThen( | |
| 899 | - SafePromiseAll([formatWatchers(true), selectedFrame.list(2)]), | ||
| 900 | + SafePromiseAllReturnArrayLike([formatWatchers(true), selectedFrame.list(2)]), | ||
| 900 | 901 | ({ 0: watcherList, 1: context }) => { | |
| 901 | 902 | const breakContext = watcherList ? | |
| 902 | 903 | `${watcherList}\n${inspect(context)}` : | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -23,13 +23,24 @@ const { | |||
| 23 | 23 | ReflectApply, | |
| 24 | 24 | ReflectConstruct, | |
| 25 | 25 | RegExpPrototypeExec, | |
| 26 | + RegExpPrototypeGetDotAll, | ||
| 27 | + RegExpPrototypeGetGlobal, | ||
| 28 | + RegExpPrototypeGetHasIndices, | ||
| 29 | + RegExpPrototypeGetIgnoreCase, | ||
| 30 | + RegExpPrototypeGetMultiline, | ||
| 31 | + RegExpPrototypeGetSticky, | ||
| 32 | + RegExpPrototypeGetUnicode, | ||
| 33 | + RegExpPrototypeGetSource, | ||
| 26 | 34 | SafeMap, | |
| 27 | 35 | SafeSet, | |
| 36 | + SafeWeakMap, | ||
| 28 | 37 | StringPrototypeReplace, | |
| 29 | 38 | StringPrototypeToLowerCase, | |
| 30 | 39 | StringPrototypeToUpperCase, | |
| 31 | 40 | Symbol, | |
| 32 | 41 | SymbolFor, | |
| 42 | + SymbolReplace, | ||
| 43 | + SymbolSplit, | ||
| 33 | 44 | } = primordials; | |
| 34 | 45 | ||
| 35 | 46 | const { | |
@@ -559,6 +570,35 @@ function SideEffectFreeRegExpPrototypeExec(regex, string) { | |||
| 559 | 570 | return FunctionPrototypeCall(RegExpFromAnotherRealm.prototype.exec, regex, string); | |
| 560 | 571 | } | |
| 561 | 572 | ||
| 573 | + const crossRelmRegexes = new SafeWeakMap(); | ||
| 574 | + function getCrossRelmRegex(regex) { | ||
| 575 | + const cached = crossRelmRegexes.get(regex); | ||
| 576 | + if (cached) return cached; | ||
| 577 | + | ||
| 578 | + let flagString = ''; | ||
| 579 | + if (RegExpPrototypeGetHasIndices(regex)) flagString += 'd'; | ||
| 580 | + if (RegExpPrototypeGetGlobal(regex)) flagString += 'g'; | ||
| 581 | + if (RegExpPrototypeGetIgnoreCase(regex)) flagString += 'i'; | ||
| 582 | + if (RegExpPrototypeGetMultiline(regex)) flagString += 'm'; | ||
| 583 | + if (RegExpPrototypeGetDotAll(regex)) flagString += 's'; | ||
| 584 | + if (RegExpPrototypeGetUnicode(regex)) flagString += 'u'; | ||
| 585 | + if (RegExpPrototypeGetSticky(regex)) flagString += 'y'; | ||
| 586 | + | ||
| 587 | + const { RegExp: RegExpFromAnotherRealm } = getInternalGlobal(); | ||
| 588 | + const crossRelmRegex = new RegExpFromAnotherRealm(RegExpPrototypeGetSource(regex), flagString); | ||
| 589 | + crossRelmRegexes.set(regex, crossRelmRegex); | ||
| 590 | + return crossRelmRegex; | ||
| 591 | + } | ||
| 592 | + | ||
| 593 | + function SideEffectFreeRegExpPrototypeSymbolReplace(regex, string, replacement) { | ||
| 594 | + return getCrossRelmRegex(regex)[SymbolReplace](string, replacement); | ||
| 595 | + } | ||
| 596 | + | ||
| 597 | + function SideEffectFreeRegExpPrototypeSymbolSplit(regex, string, limit = undefined) { | ||
| 598 | + return getCrossRelmRegex(regex)[SymbolSplit](string, limit); | ||
| 599 | + } | ||
| 600 | + | ||
| 601 | + | ||
| 562 | 602 | function isArrayBufferDetached(value) { | |
| 563 | 603 | if (ArrayBufferPrototypeGetByteLength(value) === 0) { | |
| 564 | 604 | return _isArrayBufferDetached(value); | |
@@ -594,6 +634,8 @@ module.exports = { | |||
| 594 | 634 | once, | |
| 595 | 635 | promisify, | |
| 596 | 636 | SideEffectFreeRegExpPrototypeExec, | |
| 637 | + SideEffectFreeRegExpPrototypeSymbolReplace, | ||
| 638 | + SideEffectFreeRegExpPrototypeSymbolSplit, | ||
| 597 | 639 | sleep, | |
| 598 | 640 | spliceOne, | |
| 599 | 641 | toUSVString, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -77,8 +77,6 @@ const { | |||
| 77 | 77 | ReflectApply, | |
| 78 | 78 | RegExp, | |
| 79 | 79 | RegExpPrototypeExec, | |
| 80 | - RegExpPrototypeSymbolReplace, | ||
| 81 | - RegExpPrototypeSymbolSplit, | ||
| 82 | 80 | SafePromiseRace, | |
| 83 | 81 | SafeSet, | |
| 84 | 82 | SafeWeakSet, | |
@@ -111,7 +109,9 @@ const { | |||
| 111 | 109 | const { | |
| 112 | 110 | decorateErrorStack, | |
| 113 | 111 | isError, | |
| 114 | - deprecate | ||
| 112 | + deprecate, | ||
| 113 | + SideEffectFreeRegExpPrototypeSymbolReplace, | ||
| 114 | + SideEffectFreeRegExpPrototypeSymbolSplit, | ||
| 115 | 115 | } = require('internal/util'); | |
| 116 | 116 | const { inspect } = require('internal/util/inspect'); | |
| 117 | 117 | const vm = require('vm'); | |
@@ -456,7 +456,7 @@ function REPLServer(prompt, | |||
| 456 | 456 | ||
| 457 | 457 | // Remove all "await"s and attempt running the script | |
| 458 | 458 | // in order to detect if error is truly non recoverable | |
| 459 | - const fallbackCode = RegExpPrototypeSymbolReplace(/\bawait\b/g, code, ''); | ||
| 459 | + const fallbackCode = SideEffectFreeRegExpPrototypeSymbolReplace(/\bawait\b/g, code, ''); | ||
| 460 | 460 | try { | |
| 461 | 461 | vm.createScript(fallbackCode, { | |
| 462 | 462 | filename: file, | |
@@ -681,22 +681,22 @@ function REPLServer(prompt, | |||
| 681 | 681 | if (e.stack) { | |
| 682 | 682 | if (e.name === 'SyntaxError') { | |
| 683 | 683 | // Remove stack trace. | |
| 684 | - e.stack = RegExpPrototypeSymbolReplace( | ||
| 684 | + e.stack = SideEffectFreeRegExpPrototypeSymbolReplace( | ||
| 685 | 685 | /^\s+at\s.*\n?/gm, | |
| 686 | - RegExpPrototypeSymbolReplace(/^REPL\d+:\d+\r?\n/, e.stack, ''), | ||
| 686 | + SideEffectFreeRegExpPrototypeSymbolReplace(/^REPL\d+:\d+\r?\n/, e.stack, ''), | ||
| 687 | 687 | ''); | |
| 688 | 688 | const importErrorStr = 'Cannot use import statement outside a ' + | |
| 689 | 689 | 'module'; | |
| 690 | 690 | if (StringPrototypeIncludes(e.message, importErrorStr)) { | |
| 691 | 691 | e.message = 'Cannot use import statement inside the Node.js ' + | |
| 692 | 692 | 'REPL, alternatively use dynamic import'; | |
| 693 | - e.stack = RegExpPrototypeSymbolReplace( | ||
| 693 | + e.stack = SideEffectFreeRegExpPrototypeSymbolReplace( | ||
| 694 | 694 | /SyntaxError:.*\n/, | |
| 695 | 695 | e.stack, | |
| 696 | 696 | `SyntaxError: ${e.message}\n`); | |
| 697 | 697 | } | |
| 698 | 698 | } else if (self.replMode === module.exports.REPL_MODE_STRICT) { | |
| 699 | - e.stack = RegExpPrototypeSymbolReplace( | ||
| 699 | + e.stack = SideEffectFreeRegExpPrototypeSymbolReplace( | ||
| 700 | 700 | /(\s+at\s+REPL\d+:)(\d+)/, | |
| 701 | 701 | e.stack, | |
| 702 | 702 | (_, pre, line) => pre + (line - 1) | |
@@ -728,7 +728,7 @@ function REPLServer(prompt, | |||
| 728 | 728 | if (errStack === '') { | |
| 729 | 729 | errStack = self.writer(e); | |
| 730 | 730 | } | |
| 731 | - const lines = RegExpPrototypeSymbolSplit(/(?<=\n)/, errStack); | ||
| 731 | + const lines = SideEffectFreeRegExpPrototypeSymbolSplit(/(?<=\n)/, errStack); | ||
| 732 | 732 | let matched = false; | |
| 733 | 733 | ||
| 734 | 734 | errStack = ''; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,13 +5,20 @@ const { mustNotCall } = require('../common'); | |||
| 5 | 5 | const assert = require('assert'); | |
| 6 | 6 | ||
| 7 | 7 | const { | |
| 8 | + RegExpPrototypeExec, | ||
| 8 | 9 | RegExpPrototypeSymbolReplace, | |
| 9 | 10 | RegExpPrototypeSymbolSearch, | |
| 10 | 11 | RegExpPrototypeSymbolSplit, | |
| 11 | 12 | SafeStringPrototypeSearch, | |
| 12 | 13 | hardenRegExp, | |
| 13 | 14 | } = require('internal/test/binding').primordials; | |
| 14 | 15 | ||
| 16 | + const { | ||
| 17 | + SideEffectFreeRegExpPrototypeExec, | ||
| 18 | + SideEffectFreeRegExpPrototypeSymbolReplace, | ||
| 19 | + SideEffectFreeRegExpPrototypeSymbolSplit, | ||
| 20 | + } = require('internal/util'); | ||
| 21 | + | ||
| 15 | 22 | ||
| 16 | 23 | Object.defineProperties(RegExp.prototype, { | |
| 17 | 24 | [Symbol.match]: { | |
@@ -89,14 +96,46 @@ hardenRegExp(hardenRegExp(/1/)); | |||
| 89 | 96 | // IMO there are no valid use cases in node core to use RegExpPrototypeSymbolMatch | |
| 90 | 97 | // or RegExpPrototypeSymbolMatchAll, they are inherently unsafe. | |
| 91 | 98 | ||
| 99 | + assert.strictEqual(RegExpPrototypeExec(/foo/, 'bar'), null); | ||
| 100 | + assert.strictEqual(RegExpPrototypeExec(hardenRegExp(/foo/), 'bar'), null); | ||
| 101 | + assert.strictEqual(SideEffectFreeRegExpPrototypeExec(/foo/, 'bar'), null); | ||
| 102 | + assert.strictEqual(SideEffectFreeRegExpPrototypeExec(hardenRegExp(/foo/), 'bar'), null); | ||
| 103 | + { | ||
| 104 | + const expected = ['bar']; | ||
| 105 | + Object.defineProperties(expected, { | ||
| 106 | + index: { __proto__: null, configurable: true, writable: true, enumerable: true, value: 0 }, | ||
| 107 | + input: { __proto__: null, configurable: true, writable: true, enumerable: true, value: 'bar' }, | ||
| 108 | + groups: { __proto__: null, configurable: true, writable: true, enumerable: true }, | ||
| 109 | + }); | ||
| 110 | + const actual = SideEffectFreeRegExpPrototypeExec(/bar/, 'bar'); | ||
| 111 | + | ||
| 112 | + // assert.deepStrictEqual(actual, expected) doesn't work for cross-realm comparison. | ||
| 113 | + | ||
| 114 | + assert.strictEqual(Array.isArray(actual), Array.isArray(expected)); | ||
| 115 | + assert.deepStrictEqual(Reflect.ownKeys(actual), Reflect.ownKeys(expected)); | ||
| 116 | + for (const key of Reflect.ownKeys(expected)) { | ||
| 117 | + assert.deepStrictEqual( | ||
| 118 | + Reflect.getOwnPropertyDescriptor(actual, key), | ||
| 119 | + Reflect.getOwnPropertyDescriptor(expected, key), | ||
| 120 | + ); | ||
| 121 | + } | ||
| 122 | + } | ||
| 92 | 123 | { | |
| 93 | 124 | const myRegex = hardenRegExp(/a/); | |
| 94 | 125 | assert.strictEqual(RegExpPrototypeSymbolReplace(myRegex, 'baar', 'e'), 'bear'); | |
| 95 | 126 | } | |
| 127 | + { | ||
| 128 | + const myRegex = /a/; | ||
| 129 | + assert.strictEqual(SideEffectFreeRegExpPrototypeSymbolReplace(myRegex, 'baar', 'e'), 'bear'); | ||
| 130 | + } | ||
| 96 | 131 | { | |
| 97 | 132 | const myRegex = hardenRegExp(/a/g); | |
| 98 | 133 | assert.strictEqual(RegExpPrototypeSymbolReplace(myRegex, 'baar', 'e'), 'beer'); | |
| 99 | 134 | } | |
| 135 | + { | ||
| 136 | + const myRegex = /a/g; | ||
| 137 | + assert.strictEqual(SideEffectFreeRegExpPrototypeSymbolReplace(myRegex, 'baar', 'e'), 'beer'); | ||
| 138 | + } | ||
| 100 | 139 | { | |
| 101 | 140 | const myRegex = hardenRegExp(/a/); | |
| 102 | 141 | assert.strictEqual(RegExpPrototypeSymbolSearch(myRegex, 'baar'), 1); | |
@@ -109,6 +148,22 @@ hardenRegExp(hardenRegExp(/1/)); | |||
| 109 | 148 | const myRegex = hardenRegExp(/a/); | |
| 110 | 149 | assert.deepStrictEqual(RegExpPrototypeSymbolSplit(myRegex, 'baar', 0), []); | |
| 111 | 150 | } | |
| 151 | + { | ||
| 152 | + const myRegex = /a/; | ||
| 153 | + const expected = []; | ||
| 154 | + const actual = SideEffectFreeRegExpPrototypeSymbolSplit(myRegex, 'baar', 0); | ||
| 155 | + | ||
| 156 | + // assert.deepStrictEqual(actual, expected) doesn't work for cross-realm comparison. | ||
| 157 | + | ||
| 158 | + assert.strictEqual(Array.isArray(actual), Array.isArray(expected)); | ||
| 159 | + assert.deepStrictEqual(Reflect.ownKeys(actual), Reflect.ownKeys(expected)); | ||
| 160 | + for (const key of Reflect.ownKeys(expected)) { | ||
| 161 | + assert.deepStrictEqual( | ||
| 162 | + Reflect.getOwnPropertyDescriptor(actual, key), | ||
| 163 | + Reflect.getOwnPropertyDescriptor(expected, key), | ||
| 164 | + ); | ||
| 165 | + } | ||
| 166 | + } | ||
| 112 | 167 | { | |
| 113 | 168 | const myRegex = hardenRegExp(/a/); | |
| 114 | 169 | assert.deepStrictEqual(RegExpPrototypeSymbolSplit(myRegex, 'baar', 1), ['b']); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -40,6 +40,23 @@ const allRegExpStatics = | |||
| 40 | 40 | assert.strictEqual(child.signal, null); | |
| 41 | 41 | } | |
| 42 | 42 | ||
| 43 | + { | ||
| 44 | + const child = spawnSync(process.execPath, | ||
| 45 | + [ '--expose-internals', '-p', `const { | ||
| 46 | + SideEffectFreeRegExpPrototypeExec, | ||
| 47 | + SideEffectFreeRegExpPrototypeSymbolReplace, | ||
| 48 | + SideEffectFreeRegExpPrototypeSymbolSplit, | ||
| 49 | + } = require("internal/util"); | ||
| 50 | + SideEffectFreeRegExpPrototypeExec(/foo/, "foo"); | ||
| 51 | + SideEffectFreeRegExpPrototypeSymbolReplace(/o/, "foo", "a"); | ||
| 52 | + SideEffectFreeRegExpPrototypeSymbolSplit(/o/, "foo"); | ||
| 53 | + ${allRegExpStatics}` ], | ||
| 54 | + { stdio: ['inherit', 'pipe', 'inherit'] }); | ||
| 55 | + assert.match(child.stdout.toString(), /^undefined\r?\n$/); | ||
| 56 | + assert.strictEqual(child.status, 0); | ||
| 57 | + assert.strictEqual(child.signal, null); | ||
| 58 | + } | ||
| 59 | + | ||
| 43 | 60 | { | |
| 44 | 61 | const child = spawnSync(process.execPath, | |
| 45 | 62 | [ '-e', `console.log(${allRegExpStatics})`, '--input-type=module' ], | |
| Back | FazBrowse Home | New Git URL |
0 commit comments