Skip to content

Commit

Permalink
Test fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
slevithan committed Oct 30, 2024
1 parent 33d3808 commit 76c32cd
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 15 deletions.
2 changes: 1 addition & 1 deletion dist/index.min.js

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion spec/helpers/features.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
export const duplicateCaptureNamesSupported = (() => {
const duplicateCaptureNamesSupported = (() => {
try {
new RegExp('(?<n>)|(?<n>)');
} catch (e) {
return false;
}
return true;
})();

const maxTargetForDuplicateNames = duplicateCaptureNamesSupported ? null : 'ES2024';

export {
maxTargetForDuplicateNames,
};
48 changes: 38 additions & 10 deletions spec/match-backreference.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {compile} from '../dist/index.mjs';
import {cp, r} from '../src/utils.js';
import {duplicateCaptureNamesSupported} from './helpers/features.js';
import {maxTargetForDuplicateNames} from './helpers/features.js';
import {matchers} from './helpers/matchers.js';

beforeEach(() => {
Expand All @@ -18,6 +18,7 @@ describe('Backreference', () => {
expect('').not.toFindMatch(r`(((\2)))`);
expect(['a', 'aa']).not.toFindMatch(r`(a\1)`);
expect('').not.toFindMatch(r`(\g<2>(\1))`);
expect('').not.toFindMatch(r`(\g<2>(\2))`);
});

it('should throw if not enough captures to the left', () => {
Expand Down Expand Up @@ -88,6 +89,7 @@ describe('Backreference', () => {
expect('').not.toFindMatch(r`(((\k<2>)))`);
expect(['a', 'aa']).not.toFindMatch(r`(a\k<1>)`);
expect('').not.toFindMatch(r`(\g<2>(\k<1>))`);
expect('').not.toFindMatch(r`(\g<2>(\k<2>))`);
});

it('should throw if not enough captures to the left', () => {
Expand Down Expand Up @@ -170,6 +172,7 @@ describe('Backreference', () => {
expect('').not.toFindMatch(r`(((\k<-2>)))`);
expect(['a', 'aa']).not.toFindMatch(r`(a\k<-1>)`);
expect('').not.toFindMatch(r`(\g<+1>(\k<-2>))`);
expect('').not.toFindMatch(r`(\g<+1>(\k<-1>))`);
});

it('should throw if not enough captures to the left', () => {
Expand Down Expand Up @@ -259,16 +262,29 @@ describe('Backreference', () => {
expect('').not.toFindMatch(r`(?<a>(?<b>(?<c>\k<b>)))`);
expect(['a', 'aa']).not.toFindMatch(r`(?<a>a\k<a>)`);
expect('').not.toFindMatch(r`(?<a>\g<b>(?<b>\k<a>))`);
expect('').not.toFindMatch(r`(?<a>\g<b>(?<b>\k<b>))`);
expect('').not.toFindMatch(r`(?<a>(?<a>\k<a>))`);
expect('aa').toExactlyMatch(r`(?<n>a)\k<n>|(?<n>b\k<n>)`);
expect(['a', 'b', 'ba', 'bb']).not.toFindMatch(r`(?<n>a)\k<n>|(?<n>b\k<n>)`);
expect('aa').toExactlyMatch({
pattern: r`(?<n>a)\k<n>|(?<n>b\k<n>)`,
maxTarget: maxTargetForDuplicateNames,
});
expect(['a', 'b', 'ba', 'bb']).not.toFindMatch({
pattern: r`(?<n>a)\k<n>|(?<n>b\k<n>)`,
maxTarget: maxTargetForDuplicateNames,
});
});

it('should preclude only the not-yet-closed groups when multiplexing', () => {
expect('aa').toExactlyMatch(r`(?<a>a)(?<a>\k<a>)`);
expect('aba').toExactlyMatch(r`(?<n>a)(?<n>b\k<n>)`);
expect(['aa', 'bcb']).toExactlyMatch(r`(?<n>a)\k<n>|(?<n>b)(?<n>c\k<n>)`);
expect(['a', 'bc', 'bca', 'bcc']).not.toFindMatch(r`(?<n>a)\k<n>|(?<n>b)(?<n>c\k<n>)`);
expect(['aa', 'bcb']).toExactlyMatch({
pattern: r`(?<n>a)\k<n>|(?<n>b)(?<n>c\k<n>)`,
maxTarget: maxTargetForDuplicateNames,
});
expect(['a', 'bc', 'bca', 'bcc']).not.toFindMatch({
pattern: r`(?<n>a)\k<n>|(?<n>b)(?<n>c\k<n>)`,
maxTarget: maxTargetForDuplicateNames,
});
});

it('should throw if capture is not to the left', () => {
Expand Down Expand Up @@ -296,7 +312,7 @@ describe('Backreference', () => {
expect('aab').toExactlyMatch(r`(?<n>a)\k<n>(?<n>b)`);
expect('aa').toExactlyMatch({
pattern: r`(?<n>a)\k<n>|(?<n>b)`,
maxTarget: duplicateCaptureNamesSupported ? null : 'ES2024',
maxTarget: maxTargetForDuplicateNames,
});
});

Expand Down Expand Up @@ -342,10 +358,22 @@ describe('Backreference', () => {
it('should preclude groups not in the alternation path when multiplexing', () => {
// This enforces Oniguruma logic where backrefs to nonparticipating groups fail to match
// rather than JS logic where they match the empty string
expect(['aa', 'bb']).toExactlyMatch(r`(?<n>a)\k<n>|(?<n>b)\k<n>`);
expect(['a', 'b', 'ba']).not.toFindMatch(r`(?<n>a)\k<n>|(?<n>b)\k<n>`);
expect(['aa', 'bcb', 'bcc']).toExactlyMatch(r`(?<n>a)\k<n>|(?<n>b)(?<n>c)\k<n>`);
expect(['a', 'bc', 'bca']).not.toFindMatch(r`(?<n>a)\k<n>|(?<n>b)(?<n>c)\k<n>`);
expect(['aa', 'bb']).toExactlyMatch({
pattern: r`(?<n>a)\k<n>|(?<n>b)\k<n>`,
maxTarget: maxTargetForDuplicateNames,
});
expect(['a', 'b', 'ba']).not.toFindMatch({
pattern: r`(?<n>a)\k<n>|(?<n>b)\k<n>`,
maxTarget: maxTargetForDuplicateNames,
});
expect(['aa', 'bcb', 'bcc']).toExactlyMatch({
pattern: r`(?<n>a)\k<n>|(?<n>b)(?<n>c)\k<n>`,
maxTarget: maxTargetForDuplicateNames,
});
expect(['a', 'bc', 'bca']).not.toFindMatch({
pattern: r`(?<n>a)\k<n>|(?<n>b)(?<n>c)\k<n>`,
maxTarget: maxTargetForDuplicateNames,
});
});

it('should track independent captures when used in a group referenced by a subroutine', () => {
Expand Down
7 changes: 4 additions & 3 deletions src/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -511,16 +511,17 @@ const ThirdPassVisitor = {
if (refNodes.length > 1) {
const alts = refNodes.map(reffedGroupNode => adoptAndSwapKids(
createAlternative(),
[ unclosedCaps.some(cap => cap.number === reffedGroupNode.number) ?
[ unclosedCaps.some(capture => capture.number === reffedGroupNode.number) ?
createLookaround({negate: true}) :
createBackreference(reffedGroupNode.number)
]
));
replaceWith(adoptAndSwapKids(createGroup(), alts));
} else if (unclosedCaps.some(cap => cap.number === node.ref || cap.name === node.ref)) {
replaceWith(createLookaround({negate: true}));
} else {
node.ref = refNodes[0].number;
if (unclosedCaps.some(capture => capture.number === node.ref)) {
replaceWith(createLookaround({negate: true}));
}
}
},
};
Expand Down

0 comments on commit 76c32cd

Please sign in to comment.