feat: add a custom formatter for state proxies

custom-formatter
Rich Harris 4 months ago
parent 4092b7cbde
commit 32e3a5f2ac

@ -4,6 +4,10 @@
> `%binding%` (%location%) is binding to a non-reactive property
## enable_custom_formatters
> We recommend enabling custom formatters for better results when logging `$state` objects — in your devtools, click the gear icon and check the 'Custom formatters' box
## event_handler_invalid
> %handler% should be a function. Did you mean to %suggestion%?

@ -1,43 +1,43 @@
import { STATE_SYMBOL } from '../constants.js';
import { VERSION } from '../../../version.js';
import { snapshot } from '../../shared/clone.js';
import * as w from '../warnings.js';
export function monkey_patch_console() {
for (const method of Object.keys(console)) {
// @ts-expect-error
const original = console[method];
export function install_custom_formatter() {
// Custom formatters are 'supported' in Firefox, but they're worse than useless.
// They're not supported in Firefox. We can maybe tweak this over time
var is_chrome = navigator.userAgent.includes('Chrome');
var custom_formatters_enabled = false;
if (is_chrome) {
// @ts-expect-error
console[method] = (...args) => {
for (const arg of args) {
if (contains_state_proxy(arg)) {
// TODO make this a proper warning
console.warn('contains state proxy!!!!');
break;
}
}
(window.devtoolsFormatters ??= []).push({
/**
* @param {any} object
* @param {any} config
*/
header(object, config) {
custom_formatters_enabled = true;
return original.apply(console, args);
};
}
}
/**
* @param {any} value
* @param {Set<any>} seen
* @returns {boolean}
*/
function contains_state_proxy(value, seen = new Set()) {
if (typeof value !== 'object' || value === null) return false;
if (STATE_SYMBOL in object) {
return [
'div',
{},
['span', { style: 'font-weight: bold' }, '$state'],
['object', { object: snapshot(object), config }]
];
}
if (seen.has(value)) return false;
seen.add(value);
return null;
},
if (STATE_SYMBOL in value) {
return true;
hasBody: () => false
});
}
for (const key in value) {
if (contains_state_proxy(value[key], seen)) {
return true;
}
console.log(`Running Svelte in development mode`, { version: VERSION });
if (is_chrome && !custom_formatters_enabled) {
w.enable_custom_formatters();
}
}

@ -1,5 +1,5 @@
import { DEV } from 'esm-env';
import { monkey_patch_console } from './dev/log.js';
import { install_custom_formatter } from './dev/log.js';
export { FILENAME, HMR } from '../../constants.js';
export { add_locations } from './dev/elements.js';
@ -169,5 +169,5 @@ export {
export { strict_equals, equals } from './dev/equality.js';
if (DEV) {
monkey_patch_console();
install_custom_formatter();
}

@ -138,4 +138,16 @@ export function state_proxy_equality_mismatch(operator) {
// TODO print a link to the documentation
console.warn("state_proxy_equality_mismatch");
}
}
/**
* We recommend enabling custom formatters for better results when logging `$state` objects in your devtools, click the gear icon and check the 'Custom formatters' box
*/
export function enable_custom_formatters() {
if (DEV) {
console.warn(`%c[svelte] enable_custom_formatters\n%cWe recommend enabling custom formatters for better results when logging \`$state\` objects — in your devtools, click the gear icon and check the 'Custom formatters' box`, bold, normal);
} else {
// TODO print a link to the documentation
console.warn("enable_custom_formatters");
}
}
Loading…
Cancel
Save