Skip to content

Commit 0ba2c45

Browse files
committed
More prune work
1 parent 1a2a8b5 commit 0ba2c45

File tree

2 files changed

+388
-310
lines changed

2 files changed

+388
-310
lines changed

packages/core/src/Utils.ts

Lines changed: 64 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ export function endsWith(input: string, suffix: string): boolean {
189189
*/
190190
export function prune(value: unknown, depth: number = 10): unknown {
191191
function isUnsupportedType(value: unknown): boolean {
192+
if (value === null || value === undefined) {
193+
return false;
194+
}
195+
192196
switch (typeof value) {
193197
case "function":
194198
return true;
@@ -205,6 +209,11 @@ export function prune(value: unknown, depth: number = 10): unknown {
205209
return true;
206210
}
207211

212+
// Check for buffer;
213+
if ("writeBigInt64LE" in value) {
214+
return true;
215+
}
216+
208217
break;
209218
}
210219

@@ -254,35 +263,47 @@ export function prune(value: unknown, depth: number = 10): unknown {
254263
return value;
255264
}
256265

266+
if (currentDepth > maxDepth) {
267+
return undefined;
268+
}
269+
257270
if (isUnsupportedType(value)) {
258271
return undefined;
259272
}
260273

261-
if (typeof value === "object") {
262-
const normalizedValue = normalizeValue(value);
274+
const normalizedValue = normalizeValue(value);
275+
if (typeof normalizedValue === "object") {
276+
if (normalizedValue instanceof Date) {
277+
return normalizedValue;
278+
}
279+
263280
if (Array.isArray(normalizedValue)) {
264-
return currentDepth < maxDepth
265-
? normalizedValue.map(e => pruneImpl(e, maxDepth, currentDepth + 1, seen))
266-
: [];
281+
return normalizedValue.map(e => pruneImpl(e, maxDepth, currentDepth + 1, seen));
267282
}
268283

269284
// Check for circular references
270-
if (currentDepth >= maxDepth || seen.has(value)) {
271-
return undefined;
272-
}
285+
if (Object.prototype.toString.call(normalizedValue) === "[object Object]") {
286+
if (seen.has(normalizedValue as object)) {
287+
return undefined;
288+
}
273289

274-
seen.add(value);
290+
seen.add(normalizedValue as object);
291+
}
275292

276293
const result: Record<PropertyKey, unknown> = {};
277-
for (const key of getAllKeysConditionally(value, true, true, false, true, true, false, true)) {
294+
for (const key in value) {
278295
const val = (value as { [index: PropertyKey]: unknown })[key];
279296
result[key] = pruneImpl(val, maxDepth, currentDepth + 1, seen);
280297
}
281298

282299
return result;
283300
}
284301

285-
return value;
302+
return normalizedValue;
303+
}
304+
305+
if (depth < 0) {
306+
return undefined;
286307
}
287308

288309
return pruneImpl(value, depth, 0);
@@ -304,38 +325,38 @@ export function stringify(data: unknown, exclusions?: string[], maxDepth: number
304325
}
305326

306327
// https://stackoverflow.com/questions/8024149/is-it-possible-to-get-the-non-enumerable-inherited-property-names-of-an-object
307-
function getAllKeysConditionally(obj: object, includeSelf = true, includePrototypeChain = true, includeTop = false, includeEnumerables = true, includeNonenumerables = true, includeStrings = true, includeSymbols = true) {
308-
309-
// Boolean (mini-)functions to determine unknown given key's eligibility:
310-
const isEnumerable = (obj: object, key: PropertyKey) => Object.propertyIsEnumerable.call(obj, key);
311-
const isString = (key: PropertyKey) => typeof key === 'string';
312-
const isSymbol = (key: PropertyKey) => typeof key === 'symbol';
313-
const includeBasedOnEnumerability = (obj: object, key: PropertyKey) => (includeEnumerables && isEnumerable(obj, key)) || (includeNonenumerables && !isEnumerable(obj, key));
314-
const includeBasedOnKeyType = (key: PropertyKey) => (includeStrings && isString(key)) || (includeSymbols && isSymbol(key));
315-
const include = (obj: object, key: PropertyKey) => includeBasedOnEnumerability(obj, key) && includeBasedOnKeyType(key);
316-
const notYetRetrieved = (keys: PropertyKey[], key: PropertyKey) => !keys.includes(key);
317-
318-
// filter function putting all the above together:
319-
const filterFn = (key: PropertyKey) => notYetRetrieved(keys, key) && include(obj, key);
320-
321-
// conditional chooses one of two functions to determine whether to exclude the top level or not:
322-
const stopFn = includeTop ? ((obj: unknown) => obj === null) : ((obj: unknown) => Object.getPrototypeOf(obj) === null);
323-
324-
// and now the loop to collect and filter everything:
325-
let keys: PropertyKey[] = [];
326-
while (!stopFn(obj)) {
327-
if (includeSelf) {
328-
const ownKeys = Reflect.ownKeys(obj).filter(filterFn);
329-
keys = keys.concat(ownKeys);
330-
}
331-
if (!includePrototypeChain) { break; }
332-
else {
333-
includeSelf = true;
334-
obj = Object.getPrototypeOf(obj);
335-
}
336-
}
337-
return keys;
338-
}
328+
// function getAllKeysConditionally(obj: object, includeSelf = true, includePrototypeChain = true, includeTop = false, includeEnumerables = true, includeNonenumerables = true, includeStrings = true, includeSymbols = true) {
329+
//
330+
// // Boolean (mini-)functions to determine unknown given key's eligibility:
331+
// const isEnumerable = (obj: object, key: PropertyKey) => Object.propertyIsEnumerable.call(obj, key);
332+
// const isString = (key: PropertyKey) => typeof key === 'string';
333+
// const isSymbol = (key: PropertyKey) => typeof key === 'symbol';
334+
// const includeBasedOnEnumerability = (obj: object, key: PropertyKey) => (includeEnumerables && isEnumerable(obj, key)) || (includeNonenumerables && !isEnumerable(obj, key));
335+
// const includeBasedOnKeyType = (key: PropertyKey) => (includeStrings && isString(key)) || (includeSymbols && isSymbol(key));
336+
// const include = (obj: object, key: PropertyKey) => includeBasedOnEnumerability(obj, key) && includeBasedOnKeyType(key);
337+
// const notYetRetrieved = (keys: PropertyKey[], key: PropertyKey) => !keys.includes(key);
338+
//
339+
// // filter function putting all the above together:
340+
// const filterFn = (key: PropertyKey) => notYetRetrieved(keys, key) && include(obj, key);
341+
//
342+
// // conditional chooses one of two functions to determine whether to exclude the top level or not:
343+
// const stopFn = includeTop ? ((obj: unknown) => obj === null) : ((obj: unknown) => Object.getPrototypeOf(obj) === null);
344+
//
345+
// // and now the loop to collect and filter everything:
346+
// let keys: PropertyKey[] = [];
347+
// while (!stopFn(obj)) {
348+
// if (includeSelf) {
349+
// const ownKeys = Reflect.ownKeys(obj).filter(filterFn);
350+
// keys = keys.concat(ownKeys);
351+
// }
352+
// if (!includePrototypeChain) { break; }
353+
// else {
354+
// includeSelf = true;
355+
// obj = Object.getPrototypeOf(obj);
356+
// }
357+
// }
358+
// return keys;
359+
// }
339360

340361
// export function stringify(data: unknown, exclusions?: string[], maxDepth?: number = Infinity): string | undefined {
341362
// function stringifyImpl(obj: unknown, excludedKeys: string[], maxDepth?: number = Infinity, currentDepth: number, cache: WeakSet): string | undefined {

0 commit comments

Comments
 (0)