Merge pull request #1683 from anba/regexp-perf

Reduce time needed in RegExp tests and test fixes
This commit is contained in:
Leo Balter 2018-08-17 13:15:45 -04:00 committed by GitHub
commit 62c6470bab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 230 additions and 387 deletions

View File

@ -7,17 +7,20 @@ description: |
function buildString({ loneCodePoints, ranges }) {
const CHUNK_SIZE = 10000;
let result = String.fromCodePoint(...loneCodePoints);
for (const [start, end] of ranges) {
let result = Reflect.apply(String.fromCodePoint, null, loneCodePoints);
for (let i = 0; i < ranges.length; i++) {
const range = ranges[i];
const start = range[0];
const end = range[1];
const codePoints = [];
for (let length = 0, codePoint = start; codePoint <= end; codePoint++) {
codePoints[length++] = codePoint;
if (length === CHUNK_SIZE) {
result += String.fromCodePoint(...codePoints);
result += Reflect.apply(String.fromCodePoint, null, codePoints);
codePoints.length = length = 0;
}
}
result += String.fromCodePoint(...codePoints);
result += Reflect.apply(String.fromCodePoint, null, codePoints);
}
return result;
}

View File

@ -56,4 +56,4 @@ assert.sameValue(
'timed-out',
'$262.agent.getReport() returns "timed-out"'
);
assert.sameValue(Atomics.nofity(i32a, 0), 0, 'Atomics.nofity(i32a, 0) returns 0');
assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0');

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0x10ffff / 0x10000);
for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0x10FFFF]]});
const re = /\d/ug;
const matchingRange = /[0-9]/ug;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0x10ffff / 0x10000);
for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0x10FFFF]]});
const re = /\d+/ug;
const matchingRange = /[0-9]+/ug;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0xffff / 0x10000);
for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0xFFFF]]});
const re = /\d+/g;
const matchingRange = /[0-9]+/g;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0xffff / 0x10000);
for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0xFFFF]]});
const re = /\d/g;
const matchingRange = /[0-9]/g;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0x10ffff / 0x10000);
for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0x10FFFF]]});
const re = /\D/ug;
const matchingRange = /[\0-\/:-\u{10FFFF}]/ug;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0x10ffff / 0x10000);
for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0x10FFFF]]});
const re = /\D+/ug;
const matchingRange = /[\0-\/:-\u{10FFFF}]+/ug;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0xffff / 0x10000);
for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0xFFFF]]});
const re = /\D+/g;
const matchingRange = /[\0-\/:-\uFFFF]+/g;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0xffff / 0x10000);
for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0xFFFF]]});
const re = /\D/g;
const matchingRange = /[\0-\/:-\uFFFF]/g;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0x10ffff / 0x10000);
for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0x10FFFF]]});
const re = /\S/ug;
const matchingRange = /[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uFEFE\uFF00-\u{10FFFF}]/ug;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0x10ffff / 0x10000);
for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0x10FFFF]]});
const re = /\S+/ug;
const matchingRange = /[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uFEFE\uFF00-\u{10FFFF}]+/ug;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0xffff / 0x10000);
for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0xFFFF]]});
const re = /\S+/g;
const matchingRange = /[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uFEFE\uFF00-\uFFFF]+/g;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0xffff / 0x10000);
for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0xFFFF]]});
const re = /\S/g;
const matchingRange = /[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uFEFE\uFF00-\uFFFF]/g;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0x10ffff / 0x10000);
for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0x10FFFF]]});
const re = /\W/ug;
const matchingRange = /[\0-\/:-@\[-\^`\{-\u{10FFFF}]/ug;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0x10ffff / 0x10000);
for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0x10FFFF]]});
const re = /\W+/ug;
const matchingRange = /[\0-\/:-@\[-\^`\{-\u{10FFFF}]+/ug;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0xffff / 0x10000);
for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0xFFFF]]});
const re = /\W+/g;
const matchingRange = /[\0-\/:-@\[-\^`\{-\uFFFF]+/g;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0xffff / 0x10000);
for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0xFFFF]]});
const re = /\W/g;
const matchingRange = /[\0-\/:-@\[-\^`\{-\uFFFF]/g;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0x10ffff / 0x10000);
for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0x10FFFF]]});
const re = /\s/ug;
const matchingRange = /[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]/ug;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0x10ffff / 0x10000);
for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0x10FFFF]]});
const re = /\s+/ug;
const matchingRange = /[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+/ug;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0xffff / 0x10000);
for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0xFFFF]]});
const re = /\s+/g;
const matchingRange = /[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+/g;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0xffff / 0x10000);
for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0xFFFF]]});
const re = /\s/g;
const matchingRange = /[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]/g;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0x10ffff / 0x10000);
for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0x10FFFF]]});
const re = /\w/ug;
const matchingRange = /[0-9A-Z_a-z]/ug;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0x10ffff / 0x10000);
for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0x10FFFF]]});
const re = /\w+/ug;
const matchingRange = /[0-9A-Z_a-z]+/ug;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0xffff / 0x10000);
for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0xFFFF]]});
const re = /\w+/g;
const matchingRange = /[0-9A-Z_a-z]+/g;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -33,15 +33,10 @@ info: |
The production CharacterClassEscape :: W evaluates as follows:
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
features: [String.fromCodePoint]
includes: [regExpUtils.js]
---*/
const chunks = [];
const totalChunks = Math.ceil(0xffff / 0x10000);
for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
// split strings to avoid a super long one;
chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
}
const str = buildString({loneCodePoints: [], ranges: [[0, 0xFFFF]]});
const re = /\w/g;
const matchingRange = /[0-9A-Z_a-z]/g;
@ -52,16 +47,14 @@ function matching(str) {
return str.replace(re, '') === str.replace(matchingRange, '');
}
for (const str of chunks) {
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
if (!matching(str)) {
// Error, let's find out where
for (const char of str) {
if (!matching(char)) {
errors.push('0x' + char.codePointAt(0).toString(16));
}
}
};
}
assert.sameValue(
errors.length,

View File

@ -30,6 +30,11 @@ const exceptions = {
"0": "this year",
"1": "next year",
},
"quarter": {
"-1": "last quarter",
"0": "this quarter",
"1": "next quarter",
},
"month": {
"-1": "last month",
"0": "this month",

View File

@ -9,14 +9,14 @@ locale: [en-US]
---*/
const units = {
"second": "sec.",
"minute": "min.",
"hour": "hr.",
"day": undefined,
"week": "wk.",
"month": "mo.",
"quarter": "qtr.",
"year": "yr.",
"second": ["sec."],
"minute": ["min."],
"hour": ["hr."],
"day": ["day", "days"],
"week": ["wk."],
"month": ["mo."],
"quarter": ["qtr.", "qtrs."],
"year": ["yr."],
};
const rtf = new Intl.RelativeTimeFormat("en-US", {
@ -25,9 +25,8 @@ const rtf = new Intl.RelativeTimeFormat("en-US", {
assert.sameValue(typeof rtf.format, "function", "format should be supported");
for (const [unitArgument, unitString] of Object.entries(units)) {
const singular = unitString || `${unitArgument}`;
const plural = unitString || `${unitArgument}s`;
for (const [unitArgument, unitStrings] of Object.entries(units)) {
const [singular, plural = singular] = unitStrings;
assert.sameValue(rtf.format(1000, unitArgument), `in 1,000 ${plural}`);
assert.sameValue(rtf.format(10, unitArgument), `in 10 ${plural}`);
assert.sameValue(rtf.format(2, unitArgument), `in 2 ${plural}`);

View File

@ -26,6 +26,11 @@ function expected(key, unit, default_) {
"0": "this year",
"1": "next year",
},
"quarter": {
"-1": "last quarter",
"0": "this quarter",
"1": "next quarter",
},
"month": {
"-1": "last month",
"0": "this month",

View File

@ -19,14 +19,14 @@ function verifyFormatParts(actual, expected, message) {
}
const units = {
"second": "sec.",
"minute": "min.",
"hour": "hr.",
"day": undefined,
"week": "wk.",
"month": "mo.",
"quarter": "qtr.",
"year": "yr.",
"second": ["sec."],
"minute": ["min."],
"hour": ["hr."],
"day": ["day", "days"],
"week": ["wk."],
"month": ["mo."],
"quarter": ["qtr.", "qtrs."],
"year": ["yr."],
};
const rtf = new Intl.RelativeTimeFormat("en-US", {
@ -35,9 +35,8 @@ const rtf = new Intl.RelativeTimeFormat("en-US", {
assert.sameValue(typeof rtf.formatToParts, "function", "formatToParts should be supported");
for (const [unitArgument, unitString] of Object.entries(units)) {
const singular = unitString || `${unitArgument}`;
const plural = unitString || `${unitArgument}s`;
for (const [unitArgument, unitStrings] of Object.entries(units)) {
const [singular, plural = singular] = unitStrings;
verifyFormatParts(rtf.formatToParts(1000, unitArgument), [
{ "type": "literal", "value": "in " },