Skip to content

Commit 8aefada

Browse files
committed
harness/deepEqual.js: Consolidate handling of identity-bearing values with lazy multi-use indication
1 parent 8f7d403 commit 8aefada

File tree

1 file changed

+54
-37
lines changed

1 file changed

+54
-37
lines changed

harness/deepEqual.js

Lines changed: 54 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,59 +15,76 @@ assert.deepEqual = function(actual, expected, message) {
1515
};
1616

1717
assert.deepEqual.format = (function () {
18+
function lazyStringFactory(strings, ...subs) {
19+
return function(...mappers) {
20+
assert(mappers.length === subs.length, 'mappers must be paired with substitutions');
21+
let toString = () => {
22+
let mappedSubs = subs.map((sub, i) => mappers[i](sub));
23+
return strings.map((str, i) => `${i === 0 ? '' : mappedSubs[i - 1]}${str}`).join('');
24+
};
25+
return { toString };
26+
};
27+
}
28+
let renderUsage = usage => usage.used ? ` as #${usage.id}` : '';
29+
1830
return function format(value, seen) {
1931
switch (typeof value) {
2032
case 'string':
2133
return typeof JSON !== "undefined" ? JSON.stringify(value) : `"${value}"`;
2234
case 'bigint':
2335
return `${value}n`;
2436
case 'boolean':
25-
case 'symbol':
2637
case 'undefined':
2738
case 'number':
2839
return value === 0 && 1 / value === -Infinity ? '-0' : String(value);
40+
case 'symbol':
2941
case 'function':
30-
return `function${value.name ? ` ${String(value.name)}` : ''}`;
3142
case 'object':
3243
if (value === null) return 'null';
33-
if (value instanceof Date) return `Date("${value.toISOString()}")`;
34-
if (value instanceof Error) return `${value.name || 'Error'}("${value.message}")`;
35-
if (value instanceof RegExp) return value.toString();
36-
if (!seen) {
37-
seen = {
38-
counter: 0,
39-
map: new Map()
40-
};
41-
}
42-
43-
let usage = seen.map.get(value);
44-
if (usage) {
45-
usage.used = true;
46-
return `ref #${usage.id}`;
47-
}
48-
49-
usage = { id: ++seen.counter, used: false };
50-
seen.map.set(value, usage);
51-
52-
if (typeof Set !== "undefined" && value instanceof Set) {
53-
return `Set {${Array.from(value).map(value => assert.deepEqual.format(value, seen)).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`;
54-
}
55-
if (typeof Map !== "undefined" && value instanceof Map) {
56-
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}` : ''}`;
57-
}
58-
if (Array.isArray ? Array.isArray(value) : value instanceof Array) {
59-
return `[${value.map(value => assert.deepEqual.format(value, seen)).join(', ')}]${usage.used ? ` as #${usage.id}` : ''}`;
60-
}
61-
let tag = Symbol.toStringTag && Symbol.toStringTag in value
62-
? value[Symbol.toStringTag]
63-
: 'Object';
64-
if (tag === 'Object' && Object.getPrototypeOf(value) === null) {
65-
tag = '[Object: null prototype]';
66-
}
67-
return `${tag ? `${tag} ` : ''}{${Object.keys(value).map(key => `${key.toString()}: ${assert.deepEqual.format(value[key], seen)}`).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`;
44+
break;
6845
default:
6946
return typeof value;
7047
}
48+
49+
if (!seen) {
50+
seen = {
51+
counter: 0,
52+
map: new Map()
53+
};
54+
}
55+
let usage = seen.map.get(value);
56+
if (usage) {
57+
usage.used = true;
58+
return `ref #${usage.id}`;
59+
}
60+
usage = { id: ++seen.counter, used: false };
61+
seen.map.set(value, usage);
62+
63+
if (typeof value === 'function') {
64+
return lazyStringFactory`function${value.name ? ` ${String(value.name)}` : ''}${usage}`(String, renderUsage);
65+
} else if (typeof value !== 'object') {
66+
return lazyStringFactory`${value}${usage}`(String, renderUsage);
67+
} else if (Array.isArray ? Array.isArray(value) : value instanceof Array) {
68+
return lazyStringFactory`[${value.map(value => assert.deepEqual.format(value, seen))}]${usage}`(arr => arr.join(', '), renderUsage);
69+
} else if (value instanceof Date) {
70+
return lazyStringFactory`Date(${assert.deepEqual.format(value.toISOString(), seen)})${usage}`(String, renderUsage);
71+
} else if (value instanceof Error) {
72+
return lazyStringFactory`${value.name || 'Error'}(${assert.deepEqual.format(value.message, seen)})${usage}`(String, String, renderUsage);
73+
} else if (value instanceof RegExp) {
74+
return lazyStringFactory`${value}${usage}`(String, renderUsage);
75+
} else if (typeof Map !== "undefined" && value instanceof Map) {
76+
return lazyStringFactory`Map {${Array.from(value).map(pair => `${assert.deepEqual.format(pair[0], seen)} => ${assert.deepEqual.format(pair[1], seen)}`)}}${usage}`(arr => arr.join(', '), renderUsage);
77+
} else if (typeof Set !== "undefined" && value instanceof Set) {
78+
return lazyStringFactory`Set {${Array.from(value).map(value => assert.deepEqual.format(value, seen))}}${usage}`(arr => arr.join(', '), renderUsage);
79+
}
80+
81+
let tag = Symbol.toStringTag && Symbol.toStringTag in value
82+
? value[Symbol.toStringTag]
83+
: 'Object';
84+
if (tag === 'Object' && Object.getPrototypeOf(value) === null) {
85+
tag = '[Object: null prototype]';
86+
}
87+
return lazyStringFactory`${tag ? `${tag} ` : ''}{${Object.keys(value).map(key => `${key.toString()}: ${assert.deepEqual.format(value[key], seen)}`)}}${usage}`(String, arr => arr.join(', '), renderUsage);
7188
};
7289
})();
7390

0 commit comments

Comments
 (0)