Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions JSTests/test262/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ flags:
uint8array-base64: useUint8ArrayBase64Methods
RegExp.escape: useRegExpEscape
Math.sumPrecise: useMathSumPreciseMethod
Error.isError: useErrorIsError
skip:
features:
- callable-boundary-realms
Expand All @@ -19,6 +20,7 @@ skip:
- explicit-resource-management
- regexp-modifiers
- source-phase-imports
- json-parse-with-source
paths:
- test/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO
- test/built-ins/Temporal/Now/plainDateISO
Expand Down
885 changes: 492 additions & 393 deletions JSTests/test262/expectations.yaml

Large diffs are not rendered by default.

23 changes: 18 additions & 5 deletions JSTests/test262/harness/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,18 +101,31 @@ assert.throws = function (expectedErrorConstructor, func, message) {
throw new Test262Error(message);
};

assert._formatIdentityFreeValue = function formatIdentityFreeValue(value) {
switch (value === null ? 'null' : typeof value) {
case 'string':
return typeof JSON !== "undefined" ? JSON.stringify(value) : `"${value}"`;
case 'bigint':
return `${value}n`;
case 'number':
if (value === 0 && 1 / value === -Infinity) return '-0';
// falls through
case 'boolean':
case 'undefined':
case 'null':
return String(value);
}
};

assert._toString = function (value) {
var basic = assert._formatIdentityFreeValue(value);
if (basic) return basic;
try {
if (value === 0 && 1 / value === -Infinity) {
return '-0';
}

return String(value);
} catch (err) {
if (err.name === 'TypeError') {
return Object.prototype.toString.call(value);
}

throw err;
}
};
142 changes: 104 additions & 38 deletions JSTests/test262/harness/deepEqual.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,56 +14,122 @@ assert.deepEqual = function(actual, expected, message) {
);
};

let getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
let join = arr => arr.join(', ');
function stringFromTemplate(strings, ...subs) {
let parts = strings.map((str, i) => `${i === 0 ? '' : subs[i - 1]}${str}`);
return parts.join('');
}
function escapeKey(key) {
if (typeof key === 'symbol') return `[${String(key)}]`;
if (/^[a-zA-Z0-9_$]+$/.test(key)) return key;
return assert._formatIdentityFreeValue(key);
}

assert.deepEqual.format = function(value, seen) {
switch (typeof value) {
let basic = assert._formatIdentityFreeValue(value);
if (basic) return basic;
switch (value === null ? 'null' : typeof value) {
case 'string':
return typeof JSON !== "undefined" ? JSON.stringify(value) : `"${value}"`;
case 'bigint':
case 'number':
case 'boolean':
case 'symbol':
case 'bigint':
return value.toString();
case 'undefined':
return 'undefined';
case 'null':
assert(false, 'values without identity should use basic formatting');
break;
case 'symbol':
case 'function':
return `[Function${value.name ? `: ${value.name}` : ''}]`;
case 'object':
if (value === null) return 'null';
if (value instanceof Date) return `Date "${value.toISOString()}"`;
if (value instanceof RegExp) return value.toString();
if (!seen) {
seen = {
counter: 0,
map: new Map()
};
}
break;
default:
return typeof value;
}

let usage = seen.map.get(value);
if (usage) {
usage.used = true;
return `[Ref: #${usage.id}]`;
if (!seen) {
seen = {
counter: 0,
map: new Map()
};
}
let usage = seen.map.get(value);
if (usage) {
usage.used = true;
return `ref #${usage.id}`;
}
usage = { id: ++seen.counter, used: false };
seen.map.set(value, usage);

// Properly communicating multiple references requires deferred rendering of
// all identity-bearing values until the outermost format call finishes,
// because the current value can also in appear in a not-yet-visited part of
// the object graph (which, when visited, will update the usage object).
//
// To preserve readability of the desired output formatting, we accomplish
// this deferral using tagged template literals.
// Evaluation closes over the usage object and returns a function that accepts
// "mapper" arguments for rendering the corresponding substitution values and
// returns an object with only a toString method which will itself be invoked
// when trying to use the result as a string in assert.deepEqual.
//
// For convenience, any absent mapper is presumed to be `String`, and the
// function itself has a toString method that self-invokes with no mappers
// (allowing returning the function directly when every mapper is `String`).
function lazyResult(strings, ...subs) {
function acceptMappers(...mappers) {
function toString() {
let renderings = subs.map((sub, i) => (mappers[i] || String)(sub));
let rendered = stringFromTemplate(strings, ...renderings);
if (usage.used) rendered += ` as #${usage.id}`;
return rendered;
}

usage = { id: ++seen.counter, used: false };
seen.map.set(value, usage);
return { toString };
}

if (typeof Set !== "undefined" && value instanceof Set) {
return `Set {${Array.from(value).map(value => assert.deepEqual.format(value, seen)).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`;
}
if (typeof Map !== "undefined" && value instanceof Map) {
return `Map {${Array.from(value).map(pair => `${assert.deepEqual.format(pair[0], seen)} => ${assert.deepEqual.format(pair[1], seen)}}`).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`;
}
if (Array.isArray ? Array.isArray(value) : value instanceof Array) {
return `[${value.map(value => assert.deepEqual.format(value, seen)).join(', ')}]${usage.used ? ` as #${usage.id}` : ''}`;
}
let tag = Symbol.toStringTag in value ? value[Symbol.toStringTag] : 'Object';
if (tag === 'Object' && Object.getPrototypeOf(value) === null) {
tag = '[Object: null prototype]';
}
return `${tag ? `${tag} ` : ''}{ ${Object.keys(value).map(key => `${key.toString()}: ${assert.deepEqual.format(value[key], seen)}`).join(', ')} }${usage.used ? ` as #${usage.id}` : ''}`;
default:
return typeof value;
acceptMappers.toString = () => String(acceptMappers());
return acceptMappers;
}

let format = assert.deepEqual.format;
function lazyString(strings, ...subs) {
return { toString: () => stringFromTemplate(strings, ...subs) };
}

if (typeof value === 'function') {
return lazyResult`function${value.name ? ` ${String(value.name)}` : ''}`;
}
if (typeof value !== 'object') {
// probably a symbol
return lazyResult`${value}`;
}
if (Array.isArray ? Array.isArray(value) : value instanceof Array) {
return lazyResult`[${value.map(value => format(value, seen))}]`(join);
}
if (value instanceof Date) {
return lazyResult`Date(${format(value.toISOString(), seen)})`;
}
if (value instanceof Error) {
return lazyResult`error ${value.name || 'Error'}(${format(value.message, seen)})`;
}
if (value instanceof RegExp) {
return lazyResult`${value}`;
}
if (typeof Map !== "undefined" && value instanceof Map) {
let contents = Array.from(value).map(pair => lazyString`${format(pair[0], seen)} => ${format(pair[1], seen)}`);
return lazyResult`Map {${contents}}`(join);
}
if (typeof Set !== "undefined" && value instanceof Set) {
let contents = Array.from(value).map(value => format(value, seen));
return lazyResult`Set {${contents}}`(join);
}

let tag = Symbol.toStringTag && Symbol.toStringTag in value
? value[Symbol.toStringTag]
: Object.getPrototypeOf(value) === null ? '[Object: null prototype]' : 'Object';
let keys = Reflect.ownKeys(value).filter(key => getOwnPropertyDescriptor(value, key).enumerable);
let contents = keys.map(key => lazyString`${escapeKey(key)}: ${format(value[key], seen)}`);
return lazyResult`${tag ? `${tag} ` : ''}{${contents}}`(String, join);
};

assert.deepEqual._compare = (function () {
Expand Down
8 changes: 8 additions & 0 deletions JSTests/test262/harness/propertyHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ defines:
- verifyNotEnumerable # deprecated
- verifyConfigurable # deprecated
- verifyNotConfigurable # deprecated
- verifyPrimordialProperty
---*/

// @ts-check
Expand Down Expand Up @@ -280,3 +281,10 @@ function verifyNotConfigurable(obj, name) {
throw new Test262Error("Expected obj[" + String(name) + "] NOT to be configurable, but was.");
}
}

/**
* Use this function to verify the properties of a primordial object.
* For non-primordial objects, use verifyProperty.
* See: https://github.com/tc39/how-we-work/blob/main/terminology.md#primordial
*/
var verifyPrimordialProperty = verifyProperty;
2 changes: 2 additions & 0 deletions JSTests/test262/harness/testIntl.js
Original file line number Diff line number Diff line change
Expand Up @@ -2673,6 +2673,8 @@ function partitionDurationFormatPattern(durationFormat, duration) {
nfOpts.style = "unit";
nfOpts.unit = numberFormatUnit;
nfOpts.unitDisplay = style;
} else {
nfOpts.useGrouping = false;
}

let nf = new Intl.NumberFormat(locale, nfOpts);
Expand Down
Loading