-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
229 additions
and
120 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import {r} from '../src/utils.js'; | ||
import {ansi, areMatchDetailsEqual, err, ok, onigurumaResult, transpiledRegExpResult} from './utils.js'; | ||
|
||
// Help with improving this script or moving it into Jasmine specs would be very welcome | ||
|
||
compare([ | ||
[r`\x7F`, '\x7F'], | ||
[r`\x80`, '\x80'], | ||
[r`\x`, '\\x'], | ||
[r`\p{`, '\\p{'], | ||
[r`\O`, '\n'], | ||
[r`\u{A0}`, '\u{A0}\\u{A0}'] | ||
]); | ||
|
||
async function compare(tests) { | ||
let numSame = 0; | ||
let numDiff = 0; | ||
for (let i = 0; i < tests.length; i++) { | ||
const [pattern, str] = tests[i]; | ||
const lib = transpiledRegExpResult(pattern, str); | ||
const onig = await onigurumaResult(pattern, str); | ||
const searched = `/${pattern}/ with str "${esc(str)}" (len ${str.length})`; | ||
if (areMatchDetailsEqual(lib, onig)) { | ||
numSame++; | ||
ok(i, `Results matched for ${searched}${lib.error ? ` ${ansi.yellow}(both errored)${ansi.reset}` : ''}`); | ||
continue; | ||
} | ||
numDiff++; | ||
if (lib.error) { | ||
err(i, `Only lib errored for ${searched}`); | ||
} else if (onig.error) { | ||
err(i, `Only onig errored for ${searched}`); | ||
} else if (lib.result !== onig.result) { | ||
err(i, `Results differed for ${searched}: lib: ${lib.result && `"${esc(lib.result)}"`}, onig: ${onig.result && `"${esc(onig.result)}"`}`); | ||
} else if (lib.index !== onig.index) { | ||
err(i, `Match positions differed for ${searched}: lib: ${lib.index}, onig: ${onig.index}`); | ||
} | ||
} | ||
numSame &&= `${ansi.green}${numSame}${ansi.reset}`; | ||
numDiff &&= `${ansi.red}${numDiff}${ansi.reset}`; | ||
console.log(`\nFinished: ${numSame} same, ${numDiff} different`); | ||
} | ||
|
||
function esc(str) { | ||
return str. | ||
replace(/\n/g, '\\n'). | ||
replace(/\r/g, '\\r'). | ||
replace(/\0/g, '\\0'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import {areMatchDetailsEqual, err, ok, onigurumaResult, transpiledRegExpResult} from "./utils.js"; | ||
|
||
exec(process.argv.slice(2)); | ||
|
||
// Basic Oniguruma console-based tester that also does a comparison with Oniguruma-to-ES results | ||
async function exec([pattern, str]) { | ||
if (!(typeof pattern === 'string' && typeof str === 'string')) { | ||
err(null, 'pattern and str args expected'); | ||
return; | ||
} | ||
|
||
const libMatches = []; | ||
let libMatch = transpiledRegExpResult(pattern, str, 0); | ||
while (libMatch.result) { | ||
libMatches.push(libMatch); | ||
libMatch = transpiledRegExpResult(pattern, str, libMatch.index + libMatch.result.length); | ||
} | ||
const onigMatches = []; | ||
let onigMatch = await onigurumaResult(pattern, str, 0); | ||
while (onigMatch.result) { | ||
onigMatches.push(onigMatch); | ||
onigMatch = await onigurumaResult(pattern, str, onigMatch.index + onigMatch.result.length); | ||
} | ||
|
||
console.log('Pattern:', pattern); | ||
console.log('String:', str); | ||
if (onigMatch.error) { | ||
err(null, `Oniguruma error: ${onigMatch.error.message}`); | ||
} else { | ||
console.log('Oniguruma results:', onigMatches); | ||
} | ||
if (!!libMatch.error !== !!onigMatch.error) { | ||
err(null, `Oniguruma and library results differed (only ${libMatch.error ? 'library' : 'Oniguruma'} threw error)`); | ||
} else if (libMatches.length !== onigMatches.length) { | ||
err(null, `Oniguruma and library had different number of results (${onigMatches.length}, ${libMatches.length})`); | ||
} else { | ||
let hasDiff = false; | ||
for (let i = 0; i < libMatches.length; i++) { | ||
if (!areMatchDetailsEqual(libMatches[i], onigMatches[i])) { | ||
hasDiff = true; | ||
break; | ||
} | ||
} | ||
if (hasDiff) { | ||
err(null, 'Oniguruma and library results differed'); | ||
console.log('Library results:', libMatches); | ||
} else { | ||
ok(null, 'Oniguruma and library results matched'); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import {toRegExp} from '../dist/index.mjs'; | ||
import {readFileSync} from 'node:fs'; | ||
// vscode-oniguruma 2.0.1 uses Oniguruma 6.9.8 | ||
import oniguruma from 'vscode-oniguruma'; | ||
|
||
const ansi = { | ||
green: '\x1b[32m', | ||
red: '\x1b[31m', | ||
reset: '\x1b[0m', | ||
yellow: '\x1b[33m', | ||
}; | ||
|
||
function ok(i, msg) { | ||
console.log(`${i ? ` ${i}. ` : ''}${ansi.green}✅${ansi.reset} ${msg}`); | ||
} | ||
|
||
function err(i, msg) { | ||
console.log(`${i ? ` ${i}. ` : ''}${ansi.red}❌ ${msg}${ansi.reset}`); | ||
} | ||
|
||
/** | ||
@typedef {{ | ||
result: string | null; | ||
index: number | null; | ||
error?: Error; | ||
}} MatchDetails | ||
*/ | ||
/** | ||
@template [T=MatchDetails] | ||
@typedef MatchDetailsFn | ||
@type {{ | ||
(pattern: string, str: string, pos?: number): T; | ||
}} | ||
*/ | ||
/** | ||
@param {RegExpExecArray | null | Error} match | ||
@returns {MatchDetails} | ||
*/ | ||
function getMatchDetails(match) { | ||
if (!match) { | ||
return { | ||
result: null, | ||
index: null, | ||
} | ||
} | ||
if (match instanceof Error) { | ||
return { | ||
result: null, | ||
index: null, | ||
error: match, | ||
}; | ||
} | ||
return { | ||
result: match[0], | ||
index: match.index, | ||
}; | ||
} | ||
|
||
/** | ||
@type {MatchDetailsFn<Promise<MatchDetails>>} | ||
*/ | ||
const onigurumaResult = async (pattern, str, pos) => { | ||
let result; | ||
try { | ||
result = await onigurumaExec(pattern, str, pos); | ||
} catch (err) { | ||
result = err; | ||
} | ||
return getMatchDetails(result); | ||
}; | ||
|
||
/** | ||
@type {MatchDetailsFn} | ||
*/ | ||
const transpiledRegExpResult = (pattern, str, pos) => { | ||
let result; | ||
try { | ||
const options = pos ? {global: true} : undefined; | ||
const re = toRegExp(pattern, '', options); | ||
if (pos) { | ||
re.lastIndex = pos; | ||
} | ||
result = re.exec(str); | ||
} catch (err) { | ||
result = err; | ||
} | ||
return getMatchDetails(result); | ||
}; | ||
|
||
async function onigurumaExec(pattern, str, pos = 0) { | ||
await loadOniguruma(); | ||
// See https://github.com/microsoft/vscode-oniguruma/blob/main/main.d.ts | ||
const re = new oniguruma.OnigScanner([pattern]); | ||
const match = re.findNextMatchSync(str, pos); | ||
if (!match) { | ||
return null; | ||
} | ||
const m = match.captureIndices[0]; | ||
return { | ||
'0': str.slice(m.start, m.end), | ||
index: m.start, | ||
}; | ||
} | ||
|
||
async function loadOniguruma() { | ||
const wasmPath = `${import.meta.dirname}/../node_modules/vscode-oniguruma/release/onig.wasm`; | ||
const wasmBin = readFileSync(wasmPath).buffer; | ||
await oniguruma.loadWASM(wasmBin); | ||
} | ||
|
||
/** | ||
@param {MatchDetails} a | ||
@param {MatchDetails} b | ||
@returns {boolean} | ||
*/ | ||
function areMatchDetailsEqual(a, b) { | ||
return !(a.index !== b.index || a.result !== b.result || !!a.error !== !!b.error); | ||
} | ||
|
||
export { | ||
ansi, | ||
areMatchDetailsEqual, | ||
err, | ||
ok, | ||
onigurumaResult, | ||
transpiledRegExpResult, | ||
}; |
This file was deleted.
Oops, something went wrong.