All files / src/internal/client/dev inspect.js

67.18% Statements 43/64
62.5% Branches 5/8
100% Functions 2/2
65.57% Lines 40/61

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 622x 2x 2x 2x 2x 2x 2x 2x 2x 2x 22x 22x 22x 22x 22x 44x 44x 22x 22x 2x 2x 2x 2x 2x 2x 2x 2x 2x 44x 44x 44x 44x 44x 44x 44x 44x         44x                                 44x   44x 44x  
import { snapshot } from '../../shared/clone.js';
import { inspect_effect, validate_effect } from '../reactivity/effects.js';
import { array_prototype, get_prototype_of, object_prototype } from '../../shared/utils.js';
 
/**
 * @param {() => any[]} get_value
 * @param {Function} [inspector]
 */
// eslint-disable-next-line no-console
export function inspect(get_value, inspector = console.log) {
	validate_effect('$inspect');
 
	let initial = true;
 
	inspect_effect(() => {
		inspector(initial ? 'init' : 'update', ...deep_snapshot(get_value()));
		initial = false;
	});
}
 
// TODO do we still need this?
 
/**
 * Like `snapshot`, but recursively traverses into normal arrays/objects to find potential states in them.
 * @param {any} value
 * @param {Map<any, any>} visited
 * @returns {any}
 */
function deep_snapshot(value, visited = new Map()) {
	if (typeof value === 'object' && value !== null && !visited.has(value)) {
		const unstated = snapshot(value);
 
		if (unstated !== value) {
			visited.set(value, unstated);
			return unstated;
		}

		const prototype = get_prototype_of(value);

		// Only deeply snapshot plain objects and arrays
		if (prototype === object_prototype || prototype === array_prototype) {
			let contains_unstated = false;
			/** @type {any} */
			const nested_unstated = Array.isArray(value) ? [] : {};

			for (let key in value) {
				const result = deep_snapshot(value[key], visited);
				nested_unstated[key] = result;
				if (result !== value[key]) {
					contains_unstated = true;
				}
			}

			visited.set(value, contains_unstated ? nested_unstated : value);
		} else {
			visited.set(value, value);
		}
	}

	return visited.get(value) ?? value;
}