Skip to content

Commit 98abea8

Browse files
committed
Defer to native /s flag in ES2018 environments
1 parent fbd9869 commit 98abea8

File tree

5 files changed

+33
-20
lines changed

5 files changed

+33
-20
lines changed

src/xregexp.js

+18-11
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ function hasNativeFlag(flag) {
7272
}
7373
return isSupported;
7474
}
75+
// Check for ES2018 `s` flag support
76+
const hasNativeS = hasNativeFlag('s');
7577
// Check for ES6 `u` flag support
7678
const hasNativeU = hasNativeFlag('u');
7779
// Check for ES6 `y` flag support
@@ -81,9 +83,12 @@ const registeredFlags = {
8183
g: true,
8284
i: true,
8385
m: true,
86+
s: hasNativeS,
8487
u: hasNativeU,
8588
y: hasNativeY
8689
};
90+
// Flags to remove when passing to native `RegExp` constructor
91+
const nonnativeFlags = hasNativeS ? /[^gimsuy]+/g : /[^gimuy]+/g;
8792

8893
/**
8994
* Attaches extended data and `XRegExp.prototype` properties to a regex object.
@@ -521,7 +526,7 @@ function setNamespacing(on) {
521526
* - `y` - sticky (Firefox 3+, ES6)
522527
* Additional XRegExp flags:
523528
* - `n` - explicit capture
524-
* - `s` - dot matches all (aka singleline)
529+
* - `s` - dot matches all (aka singleline) - works even when not natively supported
525530
* - `x` - free-spacing and line comments (aka extended)
526531
* - `A` - astral (requires the Unicode Base addon)
527532
* Flags cannot be provided when constructing one `RegExp` from another.
@@ -611,7 +616,7 @@ function XRegExp(pattern, flags) {
611616
// separated. However, more than one empty group in a row is never needed.
612617
pattern: output.replace(/(?:\(\?:\))+/g, '(?:)'),
613618
// Strip all but native flags
614-
flags: appliedFlags.replace(/[^gimuy]+/g, ''),
619+
flags: appliedFlags.replace(nonnativeFlags, ''),
615620
// `context.captureNames` has an item for each capturing group, even if unnamed
616621
captures: context.hasNamedCapture ? context.captureNames : null
617622
};
@@ -1772,16 +1777,18 @@ XRegExp.addToken(
17721777
);
17731778

17741779
/*
1775-
* Dot, in dotall mode (aka singleline mode, flag s) only.
1780+
* Dot, in dotAll mode (aka singleline mode, flag s) only.
17761781
*/
1777-
XRegExp.addToken(
1778-
/\./,
1779-
() => '[\\s\\S]',
1780-
{
1781-
flag: 's',
1782-
leadChar: '.'
1783-
}
1784-
);
1782+
if (!hasNativeS) {
1783+
XRegExp.addToken(
1784+
/\./,
1785+
() => '[\\s\\S]',
1786+
{
1787+
flag: 's',
1788+
leadChar: '.'
1789+
}
1790+
);
1791+
}
17851792

17861793
/*
17871794
* Named backreference: `\k<name>`. Backreference names can use RegExpIdentifierName characters

tests/.eslintrc.js

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module.exports = {
66
"XRegExp": true,
77
"resetFeatures": true,
88
"REGEX_DATA": true,
9+
"hasNativeS": true,
910
"hasNativeU": true,
1011
"hasNativeY": true,
1112
"hasStrictMode": true,

tests/helpers/h.js

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ global.resetFeatures = function() {
1313
// Property name used for extended regex instance data
1414
global.REGEX_DATA = 'xregexp';
1515

16+
// Check for ES2018 `s` flag support
17+
global.hasNativeS = XRegExp._hasNativeFlag('s');
1618
// Check for ES6 `u` flag support
1719
global.hasNativeU = XRegExp._hasNativeFlag('u');
1820
// Check for ES6 `y` flag support

tests/spec/s-xregexp.js

+11-8
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,10 @@ describe('XRegExp()', function() {
121121

122122
// These properties are `undefined`, but future ES may define them with value `false`
123123
it('should not set properties for nonnative flags', function() {
124+
if (!hasNativeS) {
125+
expect(XRegExp('', 's').dotAll).toBeFalsy();
126+
}
124127
expect(XRegExp('', 'n').explicitCapture).toBeFalsy();
125-
expect(XRegExp('', 's').singleline).toBeFalsy();
126-
expect(XRegExp('', 's').dotall).toBeFalsy();
127-
expect(XRegExp('', 's').dotAll).toBeFalsy();
128128
expect(XRegExp('', 'x').extended).toBeFalsy();
129129
// Flag A is added by Unicode Base
130130
//expect(XRegExp('', 'A').astral).toBeFalsy();
@@ -293,10 +293,10 @@ describe('XRegExp()', function() {
293293

294294
// These properties are `undefined`, but future ES may define them with value `false`
295295
it('should not set properties for nonnative flags', function() {
296+
if (!hasNativeS) {
297+
expect(XRegExp('(?s)').dotAll).toBeFalsy();
298+
}
296299
expect(XRegExp('(?n)').explicitCapture).toBeFalsy();
297-
expect(XRegExp('(?s)').singleline).toBeFalsy();
298-
expect(XRegExp('(?s)').dotall).toBeFalsy();
299-
expect(XRegExp('(?s)').dotAll).toBeFalsy();
300300
expect(XRegExp('(?x)').extended).toBeFalsy();
301301
// Flag A is added by Unicode Base
302302
//expect(XRegExp('(?A)').astral).toBeFalsy();
@@ -332,8 +332,11 @@ describe('XRegExp()', function() {
332332
expect(regex.ignoreCase).toBe(true);
333333
expect(regex.global).toBe(true);
334334
expect(regex.multiline).toBe(true);
335-
// Test nonnative flag s
336-
expect(regex.test('\n')).toBe(true);
335+
if (hasNativeS) {
336+
expect(regex.dotAll).toBe(true);
337+
} else {
338+
expect(regex.test('\n')).toBe(true);
339+
}
337340
});
338341

339342
it('should throw an exception if unknown flags are used', function() {

types/index.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export = XRegExp;
2424
*
2525
* Additional XRegExp flags:
2626
* - `n` - explicit capture
27-
* - `s` - dot matches all (aka singleline)
27+
* - `s` - dot matches all (aka singleline) - works even when not natively supported
2828
* - `x` - free-spacing and line comments (aka extended)
2929
* - `A` - astral (requires the Unicode Base addon)
3030
*

0 commit comments

Comments
 (0)