Whitespace cleanups. CRLF => LF

This commit is contained in:
Leo Balter 2019-10-08 15:40:54 -04:00 committed by Rick Waldron
parent bb6ce7e435
commit d49777de27
17 changed files with 729 additions and 898 deletions

54
LICENSE
View File

@ -1,28 +1,28 @@
The << Software identified by reference to the Ecma Standard* ("Software)">> is protected by copyright and is being
made available under the "BSD License", included below. This Software may be subject to third party rights (rights
from parties other than Ecma International), including patent rights, and no licenses under such third party rights
are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA
CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT http://www.ecma-international.org/memento/codeofconduct.htm FOR
INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS*.
Copyright (C) 2012-2013 Ecma International
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
The << Software identified by reference to the Ecma Standard* ("Software)">> is protected by copyright and is being
made available under the "BSD License", included below. This Software may be subject to third party rights (rights
from parties other than Ecma International), including patent rights, and no licenses under such third party rights
are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA
CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT http://www.ecma-international.org/memento/codeofconduct.htm FOR
INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS*.
Copyright (C) 2012-2013 Ecma International
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
* Ecma International Standards hereafter means Ecma International Standards as well as Ecma Technical Reports

View File

@ -1,415 +1,273 @@
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: |
Compare two values structurally
defines: [assert.deepEqual]
---*/
// @ts-check
var deepEqual = (function () {
/**
* @typedef {0} UNKNOWN
* @typedef {1} EQUAL
* @typedef {-1} NOT_EQUAL
* @typedef {Map<unknown, Map<unknown, EQUAL | NOT_EQUAL>>} ComparisonCache
*/
/** @type {EQUAL} */
var EQUAL = 1;
/** @type {NOT_EQUAL} */
var NOT_EQUAL = -1;
/** @type {UNKNOWN} */
var UNKNOWN = 0;
/**
* @template T
* @param {T} a
* @param {T} b
* @returns {boolean}
*/
function deepEqual(a, b) {
return compareEquality(a, b) === EQUAL;
}
/**
* @param {unknown} a
* @param {unknown} b
* @param {ComparisonCache} [cache]
* @returns {EQUAL | NOT_EQUAL}
*/
function compareEquality(a, b, cache) {
return compareIf(a, b, isOptional, compareOptionality)
|| compareIf(a, b, isPrimitiveEquatable, comparePrimitiveEquality)
|| compareIf(a, b, isObjectEquatable, compareObjectEquality, cache)
|| NOT_EQUAL;
}
/**
* @template T
* @param {unknown} a
* @param {unknown} b
* @param {(value: unknown) => value is T} test
* @param {(a: T, b: T, cache?: ComparisonCache) => EQUAL | NOT_EQUAL} compare
* @param {ComparisonCache} [cache]
* @returns {EQUAL | NOT_EQUAL | UNKNOWN}
*/
function compareIf(a, b, test, compare, cache) {
return !test(a)
? !test(b) ? UNKNOWN : NOT_EQUAL
: !test(b) ? NOT_EQUAL : cacheComparison(a, b, compare, cache);
}
/**
* @returns {EQUAL | UNKNOWN}
*/
function tryCompareStrictEquality(a, b) {
return a === b ? EQUAL : UNKNOWN;
}
/**
* @returns {NOT_EQUAL | UNKNOWN}
*/
function tryCompareTypeOfEquality(a, b) {
return typeof a !== typeof b ? NOT_EQUAL : UNKNOWN;
}
/**
* @returns {NOT_EQUAL | UNKNOWN}
*/
function tryCompareToStringTagEquality(a, b) {
var aTag = Symbol.toStringTag in a ? a[Symbol.toStringTag] : undefined;
var bTag = Symbol.toStringTag in b ? b[Symbol.toStringTag] : undefined;
return aTag !== bTag ? NOT_EQUAL : UNKNOWN;
}
/**
* @returns {value is null | undefined}
*/
function isOptional(value) {
return value === undefined
|| value === null;
}
/**
* @returns {EQUAL | NOT_EQUAL}
*/
function compareOptionality(a, b) {
return tryCompareStrictEquality(a, b)
|| NOT_EQUAL;
}
/**
* @returns {value is number | bigint | string | symbol | boolean | undefined}
*/
function isPrimitiveEquatable(value) {
switch (typeof value) {
case 'string':
case 'number':
case 'bigint':
case 'boolean':
case 'symbol':
return true;
default:
return isBoxed(value);
}
}
/**
* @returns {EQUAL | NOT_EQUAL}
*/
function comparePrimitiveEquality(a, b) {
if (isBoxed(a)) a = a.valueOf();
if (isBoxed(b)) b = b.valueOf();
return tryCompareStrictEquality(a, b)
|| tryCompareTypeOfEquality(a, b)
|| compareIf(a, b, isNaNEquatable, compareNaNEquality)
|| NOT_EQUAL;
}
/**
* @returns {value is number}
*/
function isNaNEquatable(value) {
return typeof value === 'number';
}
/**
* @param {number} a
* @param {number} b
* @returns {EQUAL | NOT_EQUAL}
*/
function compareNaNEquality(a, b) {
return isNaN(a) && isNaN(b) ? EQUAL : NOT_EQUAL;
}
/**
* @returns {value is object}
*/
function isObjectEquatable(value) {
return typeof value === 'object';
}
/**
* @param {ComparisonCache} cache
* @returns {EQUAL | NOT_EQUAL}
*/
function compareObjectEquality(a, b, cache) {
if (!cache) cache = new Map();
return getCache(cache, a, b)
|| setCache(cache, a, b, EQUAL) // consider equal for now
|| cacheComparison(a, b, tryCompareStrictEquality, cache)
|| cacheComparison(a, b, tryCompareToStringTagEquality, cache)
|| compareIf(a, b, isValueOfEquatable, compareValueOfEquality)
|| compareIf(a, b, isToStringEquatable, compareToStringEquality)
|| compareIf(a, b, isArrayLikeEquatable, compareArrayLikeEquality, cache)
|| compareIf(a, b, isStructurallyEquatable, compareStructuralEquality, cache)
|| compareIf(a, b, isIterableEquatable, compareIterableEquality, cache)
|| cacheComparison(a, b, fail, cache);
}
function isBoxed(value) {
return value instanceof String
|| value instanceof Number
|| value instanceof Boolean
|| typeof Symbol === 'function' && value instanceof Symbol
|| typeof BigInt === 'function' && value instanceof BigInt;
}
/**
* @returns {value is { valueOf(): any }}
*/
function isValueOfEquatable(value) {
return value instanceof Date;
}
/**
* @param {{ valueOf(): any }} a
* @param {{ valueOf(): any }} b
* @returns {EQUAL | NOT_EQUAL}
*/
function compareValueOfEquality(a, b) {
return compareIf(a.valueOf(), b.valueOf(), isPrimitiveEquatable, comparePrimitiveEquality)
|| NOT_EQUAL;
}
/**
* @returns {value is { toString(): string }}
*/
function isToStringEquatable(value) {
return value instanceof RegExp;
}
/**
* @param {{ toString(): string }} a
* @param {{ toString(): string }} b
* @returns {EQUAL | NOT_EQUAL}
*/
function compareToStringEquality(a, b) {
return compareIf(a.toString(), b.toString(), isPrimitiveEquatable, comparePrimitiveEquality)
|| NOT_EQUAL;
}
/**
* @returns {value is ArrayLike<unknown>}
*/
function isArrayLikeEquatable(value) {
return (Array.isArray ? Array.isArray(value) : value instanceof Array)
|| (typeof Uint8Array === 'function' && value instanceof Uint8Array)
|| (typeof Uint8ClampedArray === 'function' && value instanceof Uint8ClampedArray)
|| (typeof Uint16Array === 'function' && value instanceof Uint16Array)
|| (typeof Uint32Array === 'function' && value instanceof Uint32Array)
|| (typeof Int8Array === 'function' && value instanceof Int8Array)
|| (typeof Int16Array === 'function' && value instanceof Int16Array)
|| (typeof Int32Array === 'function' && value instanceof Int32Array)
|| (typeof Float32Array === 'function' && value instanceof Float32Array)
|| (typeof Float64Array === 'function' && value instanceof Float64Array)
|| (typeof BigUint64Array === 'function' && value instanceof BigUint64Array)
|| (typeof BigInt64Array === 'function' && value instanceof BigInt64Array);
}
/**
* @template T
* @param {ArrayLike<T>} a
* @param {ArrayLike<T>} b
* @param {ComparisonCache} cache
* @returns {EQUAL | NOT_EQUAL}
*/
function compareArrayLikeEquality(a, b, cache) {
if (a.length !== b.length) return NOT_EQUAL;
for (var i = 0; i < a.length; i++) {
if (compareEquality(a[i], b[i], cache) === NOT_EQUAL) {
return NOT_EQUAL;
}
}
return EQUAL;
}
/**
* @template T
* @param {T} value
* @returns {value is Exclude<T, Promise | WeakMap | WeakSet | Map | Set>}
*/
function isStructurallyEquatable(value) {
return !(typeof Promise === 'function' && value instanceof Promise // only comparable by reference
|| typeof WeakMap === 'function' && value instanceof WeakMap // only comparable by reference
|| typeof WeakSet === 'function' && value instanceof WeakSet // only comparable by reference
|| typeof Map === 'function' && value instanceof Map // comparable via @@iterator
|| typeof Set === 'function' && value instanceof Set); // comparable via @@iterator
}
/**
* @param {ComparisonCache} cache
* @returns {EQUAL | NOT_EQUAL}
*/
function compareStructuralEquality(a, b, cache) {
var aKeys = [];
for (var key in a) aKeys.push(key);
var bKeys = [];
for (var key in b) bKeys.push(key);
if (aKeys.length !== bKeys.length) {
return NOT_EQUAL;
}
aKeys.sort();
bKeys.sort();
for (var i = 0; i < aKeys.length; i++) {
var aKey = aKeys[i];
var bKey = bKeys[i];
if (compareEquality(aKey, bKey, cache) === NOT_EQUAL) {
return NOT_EQUAL;
}
if (compareEquality(a[aKey], b[bKey], cache) === NOT_EQUAL) {
return NOT_EQUAL;
}
}
return compareIf(a, b, isIterableEquatable, compareIterableEquality, cache)
|| EQUAL;
}
/**
* @returns {value is Iterable<unknown>}
*/
function isIterableEquatable(value) {
return typeof Symbol === 'function'
&& typeof value[Symbol.iterator] === 'function';
}
/**
* @template T
* @param {Iterator<T>} a
* @param {Iterator<T>} b
* @param {ComparisonCache} cache
* @returns {EQUAL | NOT_EQUAL}
*/
function compareIteratorEquality(a, b, cache) {
if (typeof Map === 'function' && a instanceof Map && b instanceof Map ||
typeof Set === 'function' && a instanceof Set && b instanceof Set) {
if (a.size !== b.size) return NOT_EQUAL; // exit early if we detect a difference in size
}
var ar, br;
while (true) {
ar = a.next();
br = b.next();
if (ar.done) {
if (br.done) return EQUAL;
if (b.return) b.return();
return NOT_EQUAL;
}
if (br.done) {
if (a.return) a.return();
return NOT_EQUAL;
}
if (compareEquality(ar.value, br.value, cache) === NOT_EQUAL) {
if (a.return) a.return();
if (b.return) b.return();
return NOT_EQUAL;
}
}
}
/**
* @template T
* @param {Iterable<T>} a
* @param {Iterable<T>} b
* @param {ComparisonCache} cache
* @returns {EQUAL | NOT_EQUAL}
*/
function compareIterableEquality(a, b, cache) {
return compareIteratorEquality(a[Symbol.iterator](), b[Symbol.iterator](), cache);
}
/**
* @template T
* @template {EQUAL | NOT_EQUAL | UNKNOWN} R
* @param {(a: T, b: T, circular?: ComparisonCache) => R} compare
* @param {ComparisonCache} [cache]
*/
function cacheComparison(a, b, compare, cache) {
var result = compare(a, b, cache);
if (cache && (result === EQUAL || result === NOT_EQUAL)) {
setCache(cache, a, b, /** @type {EQUAL | NOT_EQUAL} */(result));
}
return result;
}
function fail() {
return NOT_EQUAL;
}
/**
* @param {EQUAL | NOT_EQUAL} result
* @param {ComparisonCache} cache
*/
function setCache(cache, left, right, result) {
var otherCache;
otherCache = cache.get(left);
if (!otherCache) cache.set(left, otherCache = new Map());
otherCache.set(right, result);
otherCache = cache.get(right);
if (!otherCache) cache.set(right, otherCache = new Map());
otherCache.set(left, result);
}
/**
* @param {ComparisonCache} cache
*/
function getCache(cache, left, right) {
var otherCache;
/** @type {EQUAL | NOT_EQUAL | UNKNOWN | undefined} */
var result;
otherCache = cache.get(left);
result = otherCache && otherCache.get(right);
if (result) return result;
otherCache = cache.get(right);
result = otherCache && otherCache.get(left);
if (result) return result;
return UNKNOWN;
}
return deepEqual;
})();
/**
* @template T
* @param {T} actual
* @param {T} expected
* @param {string} [message]
*/
assert.deepEqual = function (actual, expected, message) {
assert(deepEqual(actual, expected),
'Expected ' + assert._formatValue(actual) + ' to be structurally equal to ' + assert._formatValue(expected) + '. ' + (message || ''));
};
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: >
Compare two values structurally
defines: [assert.deepEqual]
---*/
var deepEqual = (function () {
var EQUAL = 1;
var NOT_EQUAL = -1;
var UNKNOWN = 0;
function deepEqual(a, b) {
return compareEquality(a, b) === EQUAL;
}
function compareEquality(a, b, cache) {
return compareIf(a, b, isOptional, compareOptionality)
|| compareIf(a, b, isPrimitiveEquatable, comparePrimitiveEquality)
|| compareIf(a, b, isObjectEquatable, compareObjectEquality, cache)
|| NOT_EQUAL;
}
function compareIf(a, b, test, compare, cache) {
return !test(a)
? !test(b) ? UNKNOWN : NOT_EQUAL
: !test(b) ? NOT_EQUAL : cacheComparison(a, b, compare, cache);
}
function tryCompareStrictEquality(a, b) {
return a === b ? EQUAL : UNKNOWN;
}
function tryCompareTypeOfEquality(a, b) {
return typeof a !== typeof b ? NOT_EQUAL : UNKNOWN;
}
function tryCompareToStringTagEquality(a, b) {
var aTag = Symbol.toStringTag in a ? a[Symbol.toStringTag] : undefined;
var bTag = Symbol.toStringTag in b ? b[Symbol.toStringTag] : undefined;
return aTag !== bTag ? NOT_EQUAL : UNKNOWN;
}
function isOptional(value) {
return value === undefined
|| value === null;
}
function compareOptionality(a, b) {
return tryCompareStrictEquality(a, b)
|| NOT_EQUAL;
}
function isPrimitiveEquatable(value) {
switch (typeof value) {
case 'string':
case 'number':
case 'bigint':
case 'boolean':
case 'symbol':
return true;
default:
return isBoxed(value);
}
}
function comparePrimitiveEquality(a, b) {
if (isBoxed(a)) a = a.valueOf();
if (isBoxed(b)) b = b.valueOf();
return tryCompareStrictEquality(a, b)
|| tryCompareTypeOfEquality(a, b)
|| compareIf(a, b, isNaNEquatable, compareNaNEquality)
|| NOT_EQUAL;
}
function isNaNEquatable(value) {
return typeof value === 'number';
}
function compareNaNEquality(a, b) {
return isNaN(a) && isNaN(b) ? EQUAL : NOT_EQUAL;
}
function isObjectEquatable(value) {
return typeof value === 'object';
}
function compareObjectEquality(a, b, cache) {
if (!cache) cache = new Map();
return getCache(cache, a, b)
|| setCache(cache, a, b, EQUAL) // consider equal for now
|| cacheComparison(a, b, tryCompareStrictEquality, cache)
|| cacheComparison(a, b, tryCompareToStringTagEquality, cache)
|| compareIf(a, b, isValueOfEquatable, compareValueOfEquality)
|| compareIf(a, b, isToStringEquatable, compareToStringEquality)
|| compareIf(a, b, isArrayLikeEquatable, compareArrayLikeEquality, cache)
|| compareIf(a, b, isStructurallyEquatable, compareStructuralEquality, cache)
|| compareIf(a, b, isIterableEquatable, compareIterableEquality, cache)
|| cacheComparison(a, b, fail, cache);
}
function isBoxed(value) {
return value instanceof String
|| value instanceof Number
|| value instanceof Boolean
|| typeof Symbol === 'function' && value instanceof Symbol
|| typeof BigInt === 'function' && value instanceof BigInt;
}
function isValueOfEquatable(value) {
return value instanceof Date;
}
function compareValueOfEquality(a, b) {
return compareIf(a.valueOf(), b.valueOf(), isPrimitiveEquatable, comparePrimitiveEquality)
|| NOT_EQUAL;
}
function isToStringEquatable(value) {
return value instanceof RegExp;
}
function compareToStringEquality(a, b) {
return compareIf(a.toString(), b.toString(), isPrimitiveEquatable, comparePrimitiveEquality)
|| NOT_EQUAL;
}
function isArrayLikeEquatable(value) {
return (Array.isArray ? Array.isArray(value) : value instanceof Array)
|| (typeof Uint8Array === 'function' && value instanceof Uint8Array)
|| (typeof Uint8ClampedArray === 'function' && value instanceof Uint8ClampedArray)
|| (typeof Uint16Array === 'function' && value instanceof Uint16Array)
|| (typeof Uint32Array === 'function' && value instanceof Uint32Array)
|| (typeof Int8Array === 'function' && value instanceof Int8Array)
|| (typeof Int16Array === 'function' && value instanceof Int16Array)
|| (typeof Int32Array === 'function' && value instanceof Int32Array)
|| (typeof Float32Array === 'function' && value instanceof Float32Array)
|| (typeof Float64Array === 'function' && value instanceof Float64Array)
|| (typeof BigUint64Array === 'function' && value instanceof BigUint64Array)
|| (typeof BigInt64Array === 'function' && value instanceof BigInt64Array);
}
function compareArrayLikeEquality(a, b, cache) {
if (a.length !== b.length) return NOT_EQUAL;
for (var i = 0; i < a.length; i++) {
if (compareEquality(a[i], b[i], cache) === NOT_EQUAL) {
return NOT_EQUAL;
}
}
return EQUAL;
}
function isStructurallyEquatable(value) {
return !(typeof Promise === 'function' && value instanceof Promise // only comparable by reference
|| typeof WeakMap === 'function' && value instanceof WeakMap // only comparable by reference
|| typeof WeakSet === 'function' && value instanceof WeakSet // only comparable by reference
|| typeof Map === 'function' && value instanceof Map // comparable via @@iterator
|| typeof Set === 'function' && value instanceof Set); // comparable via @@iterator
}
function compareStructuralEquality(a, b, cache) {
var aKeys = [];
for (var key in a) aKeys.push(key);
var bKeys = [];
for (var key in b) bKeys.push(key);
if (aKeys.length !== bKeys.length) {
return NOT_EQUAL;
}
aKeys.sort();
bKeys.sort();
for (var i = 0; i < aKeys.length; i++) {
var aKey = aKeys[i];
var bKey = bKeys[i];
if (compareEquality(aKey, bKey, cache) === NOT_EQUAL) {
return NOT_EQUAL;
}
if (compareEquality(a[aKey], b[bKey], cache) === NOT_EQUAL) {
return NOT_EQUAL;
}
}
return compareIf(a, b, isIterableEquatable, compareIterableEquality, cache)
|| EQUAL;
}
function isIterableEquatable(value) {
return typeof Symbol === 'function'
&& typeof value[Symbol.iterator] === 'function';
}
function compareIteratorEquality(a, b, cache) {
if (typeof Map === 'function' && a instanceof Map && b instanceof Map ||
typeof Set === 'function' && a instanceof Set && b instanceof Set) {
if (a.size !== b.size) return NOT_EQUAL; // exit early if we detect a difference in size
}
var ar, br;
while (true) {
ar = a.next();
br = b.next();
if (ar.done) {
if (br.done) return EQUAL;
if (b.return) b.return();
return NOT_EQUAL;
}
if (br.done) {
if (a.return) a.return();
return NOT_EQUAL;
}
if (compareEquality(ar.value, br.value, cache) === NOT_EQUAL) {
if (a.return) a.return();
if (b.return) b.return();
return NOT_EQUAL;
}
}
}
function compareIterableEquality(a, b, cache) {
return compareIteratorEquality(a[Symbol.iterator](), b[Symbol.iterator](), cache);
}
function cacheComparison(a, b, compare, cache) {
var result = compare(a, b, cache);
if (cache && (result === EQUAL || result === NOT_EQUAL)) {
setCache(cache, a, b, /** @type {EQUAL | NOT_EQUAL} */(result));
}
return result;
}
function fail() {
return NOT_EQUAL;
}
function setCache(cache, left, right, result) {
var otherCache;
otherCache = cache.get(left);
if (!otherCache) cache.set(left, otherCache = new Map());
otherCache.set(right, result);
otherCache = cache.get(right);
if (!otherCache) cache.set(right, otherCache = new Map());
otherCache.set(left, result);
}
function getCache(cache, left, right) {
var otherCache;
/** @type {EQUAL | NOT_EQUAL | UNKNOWN | undefined} */
var result;
otherCache = cache.get(left);
result = otherCache && otherCache.get(right);
if (result) return result;
otherCache = cache.get(right);
result = otherCache && otherCache.get(left);
if (result) return result;
return UNKNOWN;
}
return deepEqual;
})();
assert.deepEqual = function (actual, expected, message) {
assert(deepEqual(actual, expected),
'Expected ' + assert._formatValue(actual) + ' to be structurally equal to ' + assert._formatValue(expected) + '. ' + (message || ''));
};

14
harness/types.d.ts vendored
View File

@ -1,14 +0,0 @@
declare function $ERROR(text: string): void;
// Proposal: regexp-match-indices
interface RegExpExecArray {
indices: RegExpIndicesArray;
}
interface RegExpMatchArray {
indices: RegExpIndicesArray;
}
interface RegExpIndicesArray extends Array<[number, number]> {
groups?: { [group: string]: [number, number] };
}

View File

@ -1,28 +1,27 @@
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: A matching element of indices is an Array with exactly two number properties.
esid: sec-getmatchindicesarray
features: [regexp-match-indices]
info: |
GetMatchIndicesArray ( S, match )
5. Return CreateArrayFromList(« _match_.[[StartIndex]], _match_.[[EndIndex]] »).
---*/
let input = "abcd";
let match = /b(c)/.exec(input);
let indices = match.indices;
// `indices[0]` is an array
assert.sameValue(Object.getPrototypeOf(indices[0]), Array.prototype);
assert.sameValue(indices[0].length, 2);
assert.sameValue(typeof indices[0][0], "number");
assert.sameValue(typeof indices[0][1], "number");
// `indices[1]` is an array
assert.sameValue(Object.getPrototypeOf(indices[1]), Array.prototype);
assert.sameValue(indices[1].length, 2);
assert.sameValue(typeof indices[1][0], "number");
assert.sameValue(typeof indices[1][1], "number");
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: A matching element of indices is an Array with exactly two number properties.
esid: sec-getmatchindicesarray
features: [regexp-match-indices]
info: |
GetMatchIndicesArray ( S, match )
5. Return CreateArrayFromList(« _match_.[[StartIndex]], _match_.[[EndIndex]] »).
---*/
let input = "abcd";
let match = /b(c)/.exec(input);
let indices = match.indices;
// `indices[0]` is an array
assert.sameValue(Object.getPrototypeOf(indices[0]), Array.prototype);
assert.sameValue(indices[0].length, 2);
assert.sameValue(typeof indices[0][0], "number");
assert.sameValue(typeof indices[0][1], "number");
// `indices[1]` is an array
assert.sameValue(Object.getPrototypeOf(indices[1]), Array.prototype);
assert.sameValue(indices[1].length, 2);
assert.sameValue(typeof indices[1][0], "number");
assert.sameValue(typeof indices[1][1], "number");

View File

@ -1,39 +1,38 @@
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: The properties of the "indices" array correspond to the start/end indices of the same values in the match.
includes: [compareArray.js]
esid: sec-makeindicesarray
features: [regexp-match-indices]
info: |
MakeIndicesArray ( S, indices, groupNames )
4. Let _n_ be the number of elements in _indices_.
...
6. Set _A_ to ! ArrayCreate(_n_).
...
11. For each integer _i_ such that _i_ >= 0 and _i_ < _n_, do
a. Let _matchIndices_ be _indices_[_i_].
b. If _matchIndices_ is not *undefined*, then
i. Let _matchIndicesArray_ be ! GetMatchIndicesArray(_S_, _matchIndices_).
c. Else,
i. Let _matchIndicesArray_ be *undefined*.
d. Perform ! CreateDataProperty(_A_, ! ToString(_n_), _matchIndicesArray_).
...
---*/
let input = "abcd";
let match = /b(c)/.exec(input);
let indices = match.indices;
// `indices` has the same length as match
assert.sameValue(indices.length, match.length);
// The first element of `indices` contains the start/end indices of the match
assert.compareArray(indices[0], [1, 3]);
assert.sameValue(input.slice(indices[0][0], indices[0][1]), match[0]);
// The second element of `indices` contains the start/end indices of the first capture
assert.compareArray(indices[1], [2, 3]);
assert.sameValue(input.slice(indices[1][0], indices[1][1]), match[1]);
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: The properties of the "indices" array correspond to the start/end indices of the same values in the match.
includes: [compareArray.js]
esid: sec-makeindicesarray
features: [regexp-match-indices]
info: |
MakeIndicesArray ( S, indices, groupNames )
4. Let _n_ be the number of elements in _indices_.
...
6. Set _A_ to ! ArrayCreate(_n_).
...
11. For each integer _i_ such that _i_ >= 0 and _i_ < _n_, do
a. Let _matchIndices_ be _indices_[_i_].
b. If _matchIndices_ is not *undefined*, then
i. Let _matchIndicesArray_ be ! GetMatchIndicesArray(_S_, _matchIndices_).
c. Else,
i. Let _matchIndicesArray_ be *undefined*.
d. Perform ! CreateDataProperty(_A_, ! ToString(_n_), _matchIndicesArray_).
...
---*/
let input = "abcd";
let match = /b(c)/.exec(input);
let indices = match.indices;
// `indices` has the same length as match
assert.sameValue(indices.length, match.length);
// The first element of `indices` contains the start/end indices of the match
assert.compareArray(indices[0], [1, 3]);
assert.sameValue(input.slice(indices[0][0], indices[0][1]), match[0]);
// The second element of `indices` contains the start/end indices of the first capture
assert.compareArray(indices[1], [2, 3]);
assert.sameValue(input.slice(indices[1][0], indices[1][1]), match[1]);

View File

@ -1,76 +1,75 @@
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Basic matching cases with non-unicode matches.
includes: [compareArray.js, propertyHelper.js, deepEqual.js]
esid: sec-regexpbuiltinexec
features: [regexp-match-indices]
info: |
Runtime Semantics: RegExpBuiltinExec ( R, S )
...
4. Let _lastIndex_ be ? ToLength(? Get(_R_, `"lastIndex")).
...
25. Let _indices_ be a new empty List.
26. Let _match_ be the Match { [[StartIndex]]: _lastIndex_, [[EndIndex]]: _e_ }.
27. Add _match_ as the last element of _indices_.
...
33. For each integer _i_ such that _i_ > 0 and _i_ <= _n_, in ascending order, do
...
f. Else,
i. Let _captureStart_ be _captureI_'s _startIndex_.
ii. Let _captureEnd_ be _captureI_'s _endIndex_.
...
iv. Let _capture_ be the Match { [[StartIndex]]: _captureStart_, [[EndIndex]]: _captureEnd_ }.
v. Append _capture_ to _indices_.
...
34. Let _indicesArray_ be MakeIndicesArray( _S_, _indices_, _groupNames_).
---*/
assert.deepEqual([[1, 2], [1, 2]], "bab".match(/(a)/).indices);
assert.deepEqual([[0, 3], [1, 2]], "bab".match(/.(a)./).indices);
assert.deepEqual([[0, 3], [1, 2], [2, 3]], "bab".match(/.(a)(.)/).indices);
assert.deepEqual([[0, 3], [1, 3]], "bab".match(/.(\w\w)/).indices);
assert.deepEqual([[0, 3], [0, 3]], "bab".match(/(\w\w\w)/).indices);
assert.deepEqual([[0, 3], [0, 2], [2, 3]], "bab".match(/(\w\w)(\w)/).indices);
assert.deepEqual([[0, 2], [0, 2], undefined], "bab".match(/(\w\w)(\W)?/).indices);
let groups = /(?<a>.)(?<b>.)(?<c>.)\k<c>\k<b>\k<a>/.exec("abccba").indices.groups;
assert.compareArray([0, 1], groups.a);
assert.compareArray([1, 2], groups.b);
assert.compareArray([2, 3], groups.c);
verifyProperty(groups, "a", {
enumerable: true,
writable: true,
configurable: true
});
verifyProperty(groups, "b", {
enumerable: true,
writable: true,
configurable: true
});
verifyProperty(groups, "c", {
enumerable: true,
writable: true,
configurable: true
});
// "𝐁" is U+1d401 MATHEMATICAL BOLD CAPITAL B
// - Also representable as the code point "\u{1d401}"
// - Also representable as the surrogate pair "\uD835\uDC01"
// Verify assumptions:
assert.sameValue("𝐁".length, 2, 'The length of "𝐁" is 2');
assert.sameValue("\u{1d401}".length, 2, 'The length of "\\u{1d401}" is 2');
assert.sameValue("\uD835\uDC01".length, 2, 'The length of "\\uD835\\uDC01" is 2');
assert.sameValue("𝐁".match(/./)[0].length, 1, 'The length of a single code unit match against "𝐁" is 1 (without /u flag)');
assert.sameValue("\u{1d401}".match(/./)[0].length, 1, 'The length of a single code unit match against "\\u{1d401}" is 1 (without /u flag)');
assert.sameValue("\uD835\uDC01".match(/./)[0].length, 1, 'The length of a single code unit match against "\\ud835\\udc01" is 1 (without /u flag)');
assert.compareArray([0, 1], "𝐁".match(/./).indices[0], 'Indices for non-unicode match against "𝐁" (without /u flag)');
assert.compareArray([0, 1], "\u{1d401}".match(/./).indices[0], 'Indices for non-unicode match against "\\u{1d401}" (without /u flag)');
assert.compareArray([0, 1], "\uD835\uDC01".match(/./).indices[0], 'Indices for non-unicode match against "\\ud835\\udc01" (without /u flag)');
assert.compareArray([0, 1], "𝐁".match(/(?<a>.)/).indices.groups.a, 'Indices for non-unicode match against "𝐁" in groups.a (without /u flag)');
assert.compareArray([0, 1], "\u{1d401}".match(/(?<a>.)/).indices.groups.a, 'Indices for non-unicode match against "\\u{1d401}" in groups.a (without /u flag)');
assert.compareArray([0, 1], "\uD835\uDC01".match(/(?<a>.)/).indices.groups.a, 'Indices for non-unicode match against "\\ud835\\udc01" in groups.a (without /u flag)');
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Basic matching cases with non-unicode matches.
includes: [compareArray.js, propertyHelper.js, deepEqual.js]
esid: sec-regexpbuiltinexec
features: [regexp-match-indices]
info: |
Runtime Semantics: RegExpBuiltinExec ( R, S )
...
4. Let _lastIndex_ be ? ToLength(? Get(_R_, `"lastIndex")).
...
25. Let _indices_ be a new empty List.
26. Let _match_ be the Match { [[StartIndex]]: _lastIndex_, [[EndIndex]]: _e_ }.
27. Add _match_ as the last element of _indices_.
...
33. For each integer _i_ such that _i_ > 0 and _i_ <= _n_, in ascending order, do
...
f. Else,
i. Let _captureStart_ be _captureI_'s _startIndex_.
ii. Let _captureEnd_ be _captureI_'s _endIndex_.
...
iv. Let _capture_ be the Match { [[StartIndex]]: _captureStart_, [[EndIndex]]: _captureEnd_ }.
v. Append _capture_ to _indices_.
...
34. Let _indicesArray_ be MakeIndicesArray( _S_, _indices_, _groupNames_).
---*/
assert.deepEqual([[1, 2], [1, 2]], "bab".match(/(a)/).indices);
assert.deepEqual([[0, 3], [1, 2]], "bab".match(/.(a)./).indices);
assert.deepEqual([[0, 3], [1, 2], [2, 3]], "bab".match(/.(a)(.)/).indices);
assert.deepEqual([[0, 3], [1, 3]], "bab".match(/.(\w\w)/).indices);
assert.deepEqual([[0, 3], [0, 3]], "bab".match(/(\w\w\w)/).indices);
assert.deepEqual([[0, 3], [0, 2], [2, 3]], "bab".match(/(\w\w)(\w)/).indices);
assert.deepEqual([[0, 2], [0, 2], undefined], "bab".match(/(\w\w)(\W)?/).indices);
let groups = /(?<a>.)(?<b>.)(?<c>.)\k<c>\k<b>\k<a>/.exec("abccba").indices.groups;
assert.compareArray([0, 1], groups.a);
assert.compareArray([1, 2], groups.b);
assert.compareArray([2, 3], groups.c);
verifyProperty(groups, "a", {
enumerable: true,
writable: true,
configurable: true
});
verifyProperty(groups, "b", {
enumerable: true,
writable: true,
configurable: true
});
verifyProperty(groups, "c", {
enumerable: true,
writable: true,
configurable: true
});
// "𝐁" is U+1d401 MATHEMATICAL BOLD CAPITAL B
// - Also representable as the code point "\u{1d401}"
// - Also representable as the surrogate pair "\uD835\uDC01"
// Verify assumptions:
assert.sameValue("𝐁".length, 2, 'The length of "𝐁" is 2');
assert.sameValue("\u{1d401}".length, 2, 'The length of "\\u{1d401}" is 2');
assert.sameValue("\uD835\uDC01".length, 2, 'The length of "\\uD835\\uDC01" is 2');
assert.sameValue("𝐁".match(/./)[0].length, 1, 'The length of a single code unit match against "𝐁" is 1 (without /u flag)');
assert.sameValue("\u{1d401}".match(/./)[0].length, 1, 'The length of a single code unit match against "\\u{1d401}" is 1 (without /u flag)');
assert.sameValue("\uD835\uDC01".match(/./)[0].length, 1, 'The length of a single code unit match against "\\ud835\\udc01" is 1 (without /u flag)');
assert.compareArray([0, 1], "𝐁".match(/./).indices[0], 'Indices for non-unicode match against "𝐁" (without /u flag)');
assert.compareArray([0, 1], "\u{1d401}".match(/./).indices[0], 'Indices for non-unicode match against "\\u{1d401}" (without /u flag)');
assert.compareArray([0, 1], "\uD835\uDC01".match(/./).indices[0], 'Indices for non-unicode match against "\\ud835\\udc01" (without /u flag)');
assert.compareArray([0, 1], "𝐁".match(/(?<a>.)/).indices.groups.a, 'Indices for non-unicode match against "𝐁" in groups.a (without /u flag)');
assert.compareArray([0, 1], "\u{1d401}".match(/(?<a>.)/).indices.groups.a, 'Indices for non-unicode match against "\\u{1d401}" in groups.a (without /u flag)');
assert.compareArray([0, 1], "\uD835\uDC01".match(/(?<a>.)/).indices.groups.a, 'Indices for non-unicode match against "\\ud835\\udc01" in groups.a (without /u flag)');

View File

@ -1,30 +1,29 @@
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: The properties of the "indices" array are created with CreateDataProperty.
includes: [propertyHelper.js]
esid: sec-makeindicesarray
features: [regexp-match-indices]
info: |
MakeIndicesArray ( S, indices, groupNames )
11. For each integer _i_ such that _i_ >= 0 and _i_ < _n_, do
d. Perform ! CreateDataProperty(_A_, ! ToString(_n_), _matchIndicesArray_).
---*/
let input = "abcd";
let match = /b(c)/.exec(input);
let indices = match.indices;
verifyProperty(indices, '0', {
enumerable: true,
configurable: true,
writable: true
});
verifyProperty(indices, '1', {
enumerable: true,
configurable: true,
writable: true
});
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: The properties of the "indices" array are created with CreateDataProperty.
includes: [propertyHelper.js]
esid: sec-makeindicesarray
features: [regexp-match-indices]
info: |
MakeIndicesArray ( S, indices, groupNames )
11. For each integer _i_ such that _i_ >= 0 and _i_ < _n_, do
d. Perform ! CreateDataProperty(_A_, ! ToString(_n_), _matchIndicesArray_).
---*/
let input = "abcd";
let match = /b(c)/.exec(input);
let indices = match.indices;
verifyProperty(indices, '0', {
enumerable: true,
configurable: true,
writable: true
});
verifyProperty(indices, '1', {
enumerable: true,
configurable: true,
writable: true
});

View File

@ -1,85 +1,84 @@
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Basic matching cases with non-unicode matches.
includes: [compareArray.js, propertyHelper.js, deepEqual.js]
esid: sec-regexpbuiltinexec
features: [regexp-match-indices]
info: |
Runtime Semantics: RegExpBuiltinExec ( R, S )
...
4. Let _lastIndex_ be ? ToLength(? Get(_R_, `"lastIndex")).
...
16. If _fullUnicode_ is *true*, set _e_ to ! GetStringIndex(_S_, _Input_, _e_).
...
25. Let _indices_ be a new empty List.
26. Let _match_ be the Match { [[StartIndex]]: _lastIndex_, [[EndIndex]]: _e_ }.
27. Add _match_ as the last element of _indices_.
...
33. For each integer _i_ such that _i_ > 0 and _i_ <= _n_, in ascending order, do
...
f. Else,
i. Let _captureStart_ be _captureI_'s _startIndex_.
ii. Let _captureEnd_ be _captureI_'s _endIndex_.
iii. If _fullUnicode_ is *true*, then
1. Set _captureStart_ to ! GetStringIndex(_S_, _Input_, _captureStart_).
1. Set _captureEnd_ to ! GetStringIndex(_S_, _Input_, _captureEnd_).
iv. Let _capture_ be the Match { [[StartIndex]]: _captureStart_, [[EndIndex]]: _captureEnd_ }.
v. Append _capture_ to _indices_.
...
34. Let _indicesArray_ be MakeIndicesArray( _S_, _indices_, _groupNames_).
GetStringIndex ( S, Input, e )
...
4. Let _eUTF_ be the smallest index into _S_ that corresponds to the character at element _e_ of _Input_. If _e_ is greater than or equal to the number of elements in _Input_, then _eUTF_ is the number of code units in _S_.
5. Return _eUTF_.
---*/
assert.deepEqual([[1, 2], [1, 2]], "bab".match(/(a)/u).indices);
assert.deepEqual([[0, 3], [1, 2]], "bab".match(/.(a)./u).indices);
assert.deepEqual([[0, 3], [1, 2], [2, 3]], "bab".match(/.(a)(.)/u).indices);
assert.deepEqual([[0, 3], [1, 3]], "bab".match(/.(\w\w)/u).indices);
assert.deepEqual([[0, 3], [0, 3]], "bab".match(/(\w\w\w)/u).indices);
assert.deepEqual([[0, 3], [0, 2], [2, 3]], "bab".match(/(\w\w)(\w)/u).indices);
assert.deepEqual([[0, 2], [0, 2], undefined], "bab".match(/(\w\w)(\W)?/u).indices);
let groups = /(?<a>.)(?<b>.)(?<c>.)\k<c>\k<b>\k<a>/u.exec("abccba").indices.groups;
assert.compareArray([0, 1], groups.a);
assert.compareArray([1, 2], groups.b);
assert.compareArray([2, 3], groups.c);
verifyProperty(groups, "a", {
enumerable: true,
writable: true,
configurable: true
});
verifyProperty(groups, "b", {
enumerable: true,
writable: true,
configurable: true
});
verifyProperty(groups, "c", {
enumerable: true,
writable: true,
configurable: true
});
// "𝐁" is U+1d401 MATHEMATICAL BOLD CAPITAL B
// - Also representable as the code point "\u{1d401}"
// - Also representable as the surrogate pair "\uD835\uDC01"
// Verify assumptions:
assert.sameValue("𝐁".length, 2, 'The length of "𝐁" is 2');
assert.sameValue("\u{1d401}".length, 2, 'The length of "\\u{1d401}" is 2');
assert.sameValue("\uD835\uDC01".length, 2, 'The length of "\\uD835\\uDC01" is 2');
assert.sameValue(2, "𝐁".match(/./u)[0].length, 'The length of a single code point match against "𝐁" is 2 (with /u flag)');
assert.sameValue(2, "\u{1d401}".match(/./u)[0].length, 'The length of a single code point match against "\\u{1d401}" is 2 (with /u flag)');
assert.sameValue(2, "\uD835\uDC01".match(/./u)[0].length, 'The length of a single code point match against "\\ud835\\udc01" is 2 (with /u flag)');
assert.compareArray([0, 2], "𝐁".match(/./u).indices[0], 'Indices for unicode match against "𝐁" (with /u flag)');
assert.compareArray([0, 2], "\u{1d401}".match(/./u).indices[0], 'Indices for unicode match against \\u{1d401} (with /u flag)');
assert.compareArray([0, 2], "\uD835\uDC01".match(/./u).indices[0], 'Indices for unicode match against \\ud835\\udc01 (with /u flag)');
assert.compareArray([0, 2], "𝐁".match(/(?<a>.)/u).indices.groups.a, 'Indices for unicode match against 𝐁 in groups.a (with /u flag)');
assert.compareArray([0, 2], "\u{1d401}".match(/(?<a>.)/u).indices.groups.a, 'Indices for unicode match against \\u{1d401} in groups.a (with /u flag)');
assert.compareArray([0, 2], "\uD835\uDC01".match(/(?<a>.)/u).indices.groups.a, 'Indices for unicode match against \\ud835\\udc01 in groups.a (with /u flag)');
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Basic matching cases with non-unicode matches.
includes: [compareArray.js, propertyHelper.js, deepEqual.js]
esid: sec-regexpbuiltinexec
features: [regexp-match-indices]
info: |
Runtime Semantics: RegExpBuiltinExec ( R, S )
...
4. Let _lastIndex_ be ? ToLength(? Get(_R_, `"lastIndex")).
...
16. If _fullUnicode_ is *true*, set _e_ to ! GetStringIndex(_S_, _Input_, _e_).
...
25. Let _indices_ be a new empty List.
26. Let _match_ be the Match { [[StartIndex]]: _lastIndex_, [[EndIndex]]: _e_ }.
27. Add _match_ as the last element of _indices_.
...
33. For each integer _i_ such that _i_ > 0 and _i_ <= _n_, in ascending order, do
...
f. Else,
i. Let _captureStart_ be _captureI_'s _startIndex_.
ii. Let _captureEnd_ be _captureI_'s _endIndex_.
iii. If _fullUnicode_ is *true*, then
1. Set _captureStart_ to ! GetStringIndex(_S_, _Input_, _captureStart_).
1. Set _captureEnd_ to ! GetStringIndex(_S_, _Input_, _captureEnd_).
iv. Let _capture_ be the Match { [[StartIndex]]: _captureStart_, [[EndIndex]]: _captureEnd_ }.
v. Append _capture_ to _indices_.
...
34. Let _indicesArray_ be MakeIndicesArray( _S_, _indices_, _groupNames_).
GetStringIndex ( S, Input, e )
...
4. Let _eUTF_ be the smallest index into _S_ that corresponds to the character at element _e_ of _Input_. If _e_ is greater than or equal to the number of elements in _Input_, then _eUTF_ is the number of code units in _S_.
5. Return _eUTF_.
---*/
assert.deepEqual([[1, 2], [1, 2]], "bab".match(/(a)/u).indices);
assert.deepEqual([[0, 3], [1, 2]], "bab".match(/.(a)./u).indices);
assert.deepEqual([[0, 3], [1, 2], [2, 3]], "bab".match(/.(a)(.)/u).indices);
assert.deepEqual([[0, 3], [1, 3]], "bab".match(/.(\w\w)/u).indices);
assert.deepEqual([[0, 3], [0, 3]], "bab".match(/(\w\w\w)/u).indices);
assert.deepEqual([[0, 3], [0, 2], [2, 3]], "bab".match(/(\w\w)(\w)/u).indices);
assert.deepEqual([[0, 2], [0, 2], undefined], "bab".match(/(\w\w)(\W)?/u).indices);
let groups = /(?<a>.)(?<b>.)(?<c>.)\k<c>\k<b>\k<a>/u.exec("abccba").indices.groups;
assert.compareArray([0, 1], groups.a);
assert.compareArray([1, 2], groups.b);
assert.compareArray([2, 3], groups.c);
verifyProperty(groups, "a", {
enumerable: true,
writable: true,
configurable: true
});
verifyProperty(groups, "b", {
enumerable: true,
writable: true,
configurable: true
});
verifyProperty(groups, "c", {
enumerable: true,
writable: true,
configurable: true
});
// "𝐁" is U+1d401 MATHEMATICAL BOLD CAPITAL B
// - Also representable as the code point "\u{1d401}"
// - Also representable as the surrogate pair "\uD835\uDC01"
// Verify assumptions:
assert.sameValue("𝐁".length, 2, 'The length of "𝐁" is 2');
assert.sameValue("\u{1d401}".length, 2, 'The length of "\\u{1d401}" is 2');
assert.sameValue("\uD835\uDC01".length, 2, 'The length of "\\uD835\\uDC01" is 2');
assert.sameValue(2, "𝐁".match(/./u)[0].length, 'The length of a single code point match against "𝐁" is 2 (with /u flag)');
assert.sameValue(2, "\u{1d401}".match(/./u)[0].length, 'The length of a single code point match against "\\u{1d401}" is 2 (with /u flag)');
assert.sameValue(2, "\uD835\uDC01".match(/./u)[0].length, 'The length of a single code point match against "\\ud835\\udc01" is 2 (with /u flag)');
assert.compareArray([0, 2], "𝐁".match(/./u).indices[0], 'Indices for unicode match against "𝐁" (with /u flag)');
assert.compareArray([0, 2], "\u{1d401}".match(/./u).indices[0], 'Indices for unicode match against \\u{1d401} (with /u flag)');
assert.compareArray([0, 2], "\uD835\uDC01".match(/./u).indices[0], 'Indices for unicode match against \\ud835\\udc01 (with /u flag)');
assert.compareArray([0, 2], "𝐁".match(/(?<a>.)/u).indices.groups.a, 'Indices for unicode match against 𝐁 in groups.a (with /u flag)');
assert.compareArray([0, 2], "\u{1d401}".match(/(?<a>.)/u).indices.groups.a, 'Indices for unicode match against \\u{1d401} in groups.a (with /u flag)');
assert.compareArray([0, 2], "\uD835\uDC01".match(/(?<a>.)/u).indices.groups.a, 'Indices for unicode match against \\ud835\\udc01 in groups.a (with /u flag)');

View File

@ -1,21 +1,20 @@
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Basic matching cases with non-unicode matches.
includes: [compareArray.js]
esid: sec-makeindicesarray
features: [regexp-match-indices]
---*/
assert.compareArray([1, 2], /(?<π>a)/u.exec("bab").indices.groups.π);
assert.compareArray([1, 2], /(?<\u{03C0}>a)/u.exec("bab").indices.groups.π);
assert.compareArray([1, 2], /(?<π>a)/u.exec("bab").indices.groups.\u03C0);
assert.compareArray([1, 2], /(?<\u{03C0}>a)/u.exec("bab").indices.groups.\u03C0);
assert.compareArray([1, 2], /(?<$>a)/u.exec("bab").indices.groups.$);
assert.compareArray([1, 2], /(?<_>a)/u.exec("bab").indices.groups._);
assert.compareArray([1, 2], /(?<$𐒤>a)/u.exec("bab").indices.groups.$𐒤);
assert.compareArray([1, 2], /(?<_\u200C>a)/u.exec("bab").indices.groups._\u200C);
assert.compareArray([1, 2], /(?<_\u200D>a)/u.exec("bab").indices.groups._\u200D);
assert.compareArray([1, 2], /(?<ಠ_ಠ>a)/u.exec("bab").indices.groups._ಠ);
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Basic matching cases with non-unicode matches.
includes: [compareArray.js]
esid: sec-makeindicesarray
features: [regexp-match-indices]
---*/
assert.compareArray([1, 2], /(?<π>a)/u.exec("bab").indices.groups.π);
assert.compareArray([1, 2], /(?<\u{03C0}>a)/u.exec("bab").indices.groups.π);
assert.compareArray([1, 2], /(?<π>a)/u.exec("bab").indices.groups.\u03C0);
assert.compareArray([1, 2], /(?<\u{03C0}>a)/u.exec("bab").indices.groups.\u03C0);
assert.compareArray([1, 2], /(?<$>a)/u.exec("bab").indices.groups.$);
assert.compareArray([1, 2], /(?<_>a)/u.exec("bab").indices.groups._);
assert.compareArray([1, 2], /(?<$𐒤>a)/u.exec("bab").indices.groups.$𐒤);
assert.compareArray([1, 2], /(?<_\u200C>a)/u.exec("bab").indices.groups._\u200C);
assert.compareArray([1, 2], /(?<_\u200D>a)/u.exec("bab").indices.groups._\u200D);
assert.compareArray([1, 2], /(?<ಠ_ಠ>a)/u.exec("bab").indices.groups._ಠ);

View File

@ -1,33 +1,32 @@
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: An unmatched capture in a match corresponds to an unmatched capture in "indices"
esid: sec-makeindicesarray
features: [regexp-match-indices]
info: |
MakeIndicesArray ( S, indices, groupNames )
4. Let _n_ be the number of elements in _indices_.
...
6. Set _A_ to ! ArrayCreate(_n_).
...
11. For each integer _i_ such that _i_ >= 0 and _i_ < _n_, do
a. Let _matchIndices_ be _indices_[_i_].
b. If _matchIndices_ is not *undefined*, then
i. Let _matchIndicesArray_ be ! GetMatchIndicesArray(_S_, _matchIndices_).
c. Else,
i. Let _matchIndicesArray_ be *undefined*.
d. Perform ! CreateDataProperty(_A_, ! ToString(_n_), _matchIndicesArray_).
...
---*/
let input = "abd";
let match = /b(c)?/.exec(input);
let indices = match.indices;
// `indices` has the same length as match
assert.sameValue(indices.length, match.length);
// The second element of `indices` should be undefined.
assert.sameValue(indices[1], undefined);
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: An unmatched capture in a match corresponds to an unmatched capture in "indices"
esid: sec-makeindicesarray
features: [regexp-match-indices]
info: |
MakeIndicesArray ( S, indices, groupNames )
4. Let _n_ be the number of elements in _indices_.
...
6. Set _A_ to ! ArrayCreate(_n_).
...
11. For each integer _i_ such that _i_ >= 0 and _i_ < _n_, do
a. Let _matchIndices_ be _indices_[_i_].
b. If _matchIndices_ is not *undefined*, then
i. Let _matchIndicesArray_ be ! GetMatchIndicesArray(_S_, _matchIndices_).
c. Else,
i. Let _matchIndicesArray_ be *undefined*.
d. Perform ! CreateDataProperty(_A_, ! ToString(_n_), _matchIndicesArray_).
...
---*/
let input = "abd";
let match = /b(c)?/.exec(input);
let indices = match.indices;
// `indices` has the same length as match
assert.sameValue(indices.length, match.length);
// The second element of `indices` should be undefined.
assert.sameValue(indices[1], undefined);

View File

@ -1,19 +1,18 @@
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: The "indices" property is an Array.
esid: sec-makeindicesarray
features: [regexp-match-indices]
info: |
MakeIndicesArray ( S, indices, groupNames )
6. Set _A_ to ! ArrayCreate(_n_).
---*/
let match = /a/.exec("a");
let indices = match.indices;
// `indices` is an array
assert.sameValue(Object.getPrototypeOf(indices), Array.prototype);
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: The "indices" property is an Array.
esid: sec-makeindicesarray
features: [regexp-match-indices]
info: |
MakeIndicesArray ( S, indices, groupNames )
6. Set _A_ to ! ArrayCreate(_n_).
---*/
let match = /a/.exec("a");
let indices = match.indices;
// `indices` is an array
assert.sameValue(Object.getPrototypeOf(indices), Array.prototype);
assert(Array.isArray(indices));

View File

@ -1,30 +1,29 @@
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: The "indices" property is created with DefinePropertyOrThrow
includes: [propertyHelper.js]
esid: sec-regexpbuiltinexec
features: [regexp-match-indices]
info: |
Runtime Semantics: RegExpBuiltinExec ( R, S )
34. Let _indicesArray_ be MakeIndicesArray(_S_, _indices_, _groupNames_).
35. Perform ! DefinePropertyOrThrow(_A_, `"indices"`, PropertyDescriptor { [[Value]]: _indicesArray_, [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: *true* }).
---*/
// `indices` is created with Define, not Set.
let counter = 0;
Object.defineProperty(Array.prototype, "indices", {
set() { counter++; }
});
let match = /a/.exec("a");
assert.sameValue(counter, 0);
// `indices` is a non-writable, non-enumerable, and configurable data-property.
verifyProperty(match, 'indices', {
writable: true,
enumerable: true,
configurable: true
});
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: The "indices" property is created with DefinePropertyOrThrow
includes: [propertyHelper.js]
esid: sec-regexpbuiltinexec
features: [regexp-match-indices]
info: |
Runtime Semantics: RegExpBuiltinExec ( R, S )
34. Let _indicesArray_ be MakeIndicesArray(_S_, _indices_, _groupNames_).
35. Perform ! DefinePropertyOrThrow(_A_, `"indices"`, PropertyDescriptor { [[Value]]: _indicesArray_, [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: *true* }).
---*/
// `indices` is created with Define, not Set.
let counter = 0;
Object.defineProperty(Array.prototype, "indices", {
set() { counter++; }
});
let match = /a/.exec("a");
assert.sameValue(counter, 0);
// `indices` is a non-writable, non-enumerable, and configurable data-property.
verifyProperty(match, 'indices', {
writable: true,
enumerable: true,
configurable: true
});

View File

@ -1,15 +1,14 @@
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: >
array values compare correctly.
includes: [deepEqual.js]
---*/
assert.deepEqual([], []);
assert.deepEqual([1, "a", true], [1, "a", true]);
assert.throws(Test262Error, function () { assert.deepEqual([], [1]); });
assert.throws(Test262Error, function () { assert.deepEqual([1, "a", true], [1, "a", false]); });
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: >
array values compare correctly.
includes: [deepEqual.js]
---*/
assert.deepEqual([], []);
assert.deepEqual([1, "a", true], [1, "a", true]);
assert.throws(Test262Error, function () { assert.deepEqual([], [1]); });
assert.throws(Test262Error, function () { assert.deepEqual([1, "a", true], [1, "a", false]); });

View File

@ -1,18 +1,17 @@
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: >
values compare correctly with circular references.
includes: [deepEqual.js]
---*/
var a = { x: 1 };
var b = { x: 1 };
a.a = a;
a.b = b;
b.a = b;
b.b = a;
assert.deepEqual(a, b);
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: >
values compare correctly with circular references.
includes: [deepEqual.js]
---*/
var a = { x: 1 };
var b = { x: 1 };
a.a = a;
a.b = b;
b.a = b;
b.b = a;
assert.deepEqual(a, b);

View File

@ -1,14 +1,13 @@
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: >
values compare correctly.
includes: [deepEqual.js]
---*/
assert.deepEqual({ a: { x: 1 }, b: [true] }, { a: { x: 1 }, b: [true] });
assert.throws(Test262Error, function () { assert.deepEqual({}, { a: { x: 1 }, b: [true] }); });
assert.throws(Test262Error, function () { assert.deepEqual({ a: { x: 1 }, b: [true] }, { a: { x: 1 }, b: [false] }); });
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: >
values compare correctly.
includes: [deepEqual.js]
---*/
assert.deepEqual({ a: { x: 1 }, b: [true] }, { a: { x: 1 }, b: [true] });
assert.throws(Test262Error, function () { assert.deepEqual({}, { a: { x: 1 }, b: [true] }); });
assert.throws(Test262Error, function () { assert.deepEqual({ a: { x: 1 }, b: [true] }, { a: { x: 1 }, b: [false] }); });

View File

@ -1,20 +1,19 @@
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: >
map/set values compare correctly.
includes: [deepEqual.js]
---*/
assert.deepEqual(new Set(), new Set());
assert.deepEqual(new Set([1, "a", true]), new Set([1, "a", true]));
assert.deepEqual(new Map(), new Map());
assert.deepEqual(new Map([[1, "a"], ["b", true]]), new Map([[1, "a"], ["b", true]]));
assert.throws(Test262Error, function () { assert.deepEqual(new Set([]), new Set([1])); });
assert.throws(Test262Error, function () { assert.deepEqual(new Set([1, "a", true]), new Set([1, "a", false])); });
assert.throws(Test262Error, function () { assert.deepEqual(new Map([]), new Map([[1, "a"], ["b", true]])); });
assert.throws(Test262Error, function () { assert.deepEqual(new Map([[1, "a"], ["b", true]]), new Map([[1, "a"], ["b", false]])); });
assert.throws(Test262Error, function () { assert.deepEqual(new Map([[1, "a"], ["b", true]]), new Set([[1, "a"], ["b", false]])); });
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: >
map/set values compare correctly.
includes: [deepEqual.js]
---*/
assert.deepEqual(new Set(), new Set());
assert.deepEqual(new Set([1, "a", true]), new Set([1, "a", true]));
assert.deepEqual(new Map(), new Map());
assert.deepEqual(new Map([[1, "a"], ["b", true]]), new Map([[1, "a"], ["b", true]]));
assert.throws(Test262Error, function () { assert.deepEqual(new Set([]), new Set([1])); });
assert.throws(Test262Error, function () { assert.deepEqual(new Set([1, "a", true]), new Set([1, "a", false])); });
assert.throws(Test262Error, function () { assert.deepEqual(new Map([]), new Map([[1, "a"], ["b", true]])); });
assert.throws(Test262Error, function () { assert.deepEqual(new Map([[1, "a"], ["b", true]]), new Map([[1, "a"], ["b", false]])); });
assert.throws(Test262Error, function () { assert.deepEqual(new Map([[1, "a"], ["b", true]]), new Set([[1, "a"], ["b", false]])); });

View File

@ -1,15 +1,15 @@
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: >
object values compare correctly.
includes: [deepEqual.js]
---*/
assert.deepEqual({}, {});
assert.deepEqual({ a: 1, b: true }, { a: 1, b: true });
assert.throws(Test262Error, function () { assert.deepEqual({}, { a: 1, b: true }); });
assert.throws(Test262Error, function () { assert.deepEqual({ a: 1, b: true }, { a: 1, b: false }); });
// Copyright 2019 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: >
object values compare correctly.
includes: [deepEqual.js]
---*/
assert.deepEqual({}, {});
assert.deepEqual({ a: 1, b: true }, { a: 1, b: true });
assert.throws(Test262Error, function () { assert.deepEqual({}, { a: 1, b: true }); });
assert.throws(Test262Error, function () { assert.deepEqual({ a: 1, b: true }, { a: 1, b: false }); });