@@ -2,7 +2,7 @@ import { DEV } from 'esm-env';
22import { subscribe_to_store } from '../../store/utils.js' ;
33import { EMPTY_FUNC , run_all } from '../common.js' ;
44import { unwrap } from './render.js' ;
5- import { is_array } from './utils.js' ;
5+ import { get_descriptors , is_array } from './utils.js' ;
66
77export const SOURCE = 1 ;
88export const DERIVED = 1 << 1 ;
@@ -69,8 +69,14 @@ let current_skip_consumer = false;
6969// Handle collecting all signals which are read during a specific time frame
7070let is_signals_recorded = false ;
7171let captured_signals = new Set ( ) ;
72- // Handle rendering tree blocks and anchors
7372
73+ /** @type {Function | null } */
74+ let inspect_fn = null ;
75+
76+ /** @type {Array<import('./types.js').SourceSignal & import('./types.js').SourceSignalDebug> } */
77+ let inspect_captured_signals = [ ] ;
78+
79+ // Handle rendering tree blocks and anchors
7480/** @type {null | import('./types.js').Block } */
7581export let current_block = null ;
7682// Handling runtime component context
@@ -145,10 +151,26 @@ function default_equals(a, b) {
145151 * @template V
146152 * @param {import('./types.js').SignalFlags } flags
147153 * @param {V } value
148- * @returns {import('./types.js').SourceSignal<V> }
154+ * @returns {import('./types.js').SourceSignal<V> | import('./types.js').SourceSignal<V> & import('./types.js').SourceSignalDebug }
149155 */
150156function create_source_signal ( flags , value ) {
151- const source = {
157+ if ( DEV ) {
158+ return {
159+ // consumers
160+ c : null ,
161+ // equals
162+ e : null ,
163+ // flags
164+ f : flags ,
165+ // value
166+ v : value ,
167+ // context: We can remove this if we get rid of beforeUpdate/afterUpdate
168+ x : null ,
169+ // this is for DEV only
170+ inspect : new Set ( )
171+ } ;
172+ }
173+ return {
152174 // consumers
153175 c : null ,
154176 // equals
@@ -160,7 +182,6 @@ function create_source_signal(flags, value) {
160182 // context: We can remove this if we get rid of beforeUpdate/afterUpdate
161183 x : null
162184 } ;
163- return source ;
164185}
165186
166187/**
@@ -688,7 +709,7 @@ export function store_get(store, store_name, stores) {
688709/**
689710 * @template V
690711 * @param {import('./types.js').Store<V> | null | undefined } store
691- * @param {import('./types.js').Signal <V> } source
712+ * @param {import('./types.js').SourceSignal <V> } source
692713 */
693714function connect_store_to_signal ( store , source ) {
694715 if ( store == null ) {
@@ -756,6 +777,14 @@ export function exposable(fn) {
756777 * @returns {V }
757778 */
758779export function get ( signal ) {
780+ // @ts -expect-error
781+ if ( DEV && signal . inspect && inspect_fn ) {
782+ // @ts -expect-error
783+ signal . inspect . add ( inspect_fn ) ;
784+ // @ts -expect-error
785+ inspect_captured_signals . push ( signal ) ;
786+ }
787+
759788 const flags = signal . f ;
760789 if ( ( flags & DESTROYED ) !== 0 ) {
761790 return signal . v ;
@@ -811,7 +840,7 @@ export function set(signal, value) {
811840 * @returns {void }
812841 */
813842export function set_sync ( signal , value ) {
814- flushSync ( ( ) => set_signal_value ( signal , value ) ) ;
843+ flushSync ( ( ) => set ( signal , value ) ) ;
815844}
816845
817846/**
@@ -1016,6 +1045,12 @@ export function set_signal_value(signal, value) {
10161045 } ) ;
10171046 }
10181047 }
1048+
1049+ // @ts -expect-error
1050+ if ( DEV && signal . inspect ) {
1051+ // @ts -expect-error
1052+ for ( const fn of signal . inspect ) fn ( ) ;
1053+ }
10191054 }
10201055}
10211056
@@ -1727,3 +1762,69 @@ export function pop(accessors) {
17271762 context_stack_item . m = true ;
17281763 }
17291764}
1765+
1766+ /**
1767+ * @param {any } value
1768+ * @param {Set<any> } visited
1769+ * @returns {void }
1770+ */
1771+ function deep_read ( value , visited = new Set ( ) ) {
1772+ if ( typeof value === 'object' && value !== null && ! visited . has ( value ) ) {
1773+ visited . add ( value ) ;
1774+ for ( let key in value ) {
1775+ deep_read ( value [ key ] , visited ) ;
1776+ }
1777+ const proto = Object . getPrototypeOf ( value ) ;
1778+ if (
1779+ proto !== Object . prototype &&
1780+ proto !== Array . prototype &&
1781+ proto !== Map . prototype &&
1782+ proto !== Set . prototype &&
1783+ proto !== Date . prototype
1784+ ) {
1785+ const descriptors = get_descriptors ( proto ) ;
1786+ for ( let key in descriptors ) {
1787+ const get = descriptors [ key ] . get ;
1788+ if ( get ) {
1789+ get . call ( value ) ;
1790+ }
1791+ }
1792+ }
1793+ }
1794+ }
1795+
1796+ /**
1797+ * @param {() => import('./types.js').MaybeSignal<> } get_value
1798+ * @param {Function } inspect
1799+ * @returns {void }
1800+ */
1801+ // eslint-disable-next-line no-console
1802+ export function inspect ( get_value , inspect = console . log ) {
1803+ let initial = true ;
1804+
1805+ pre_effect ( ( ) => {
1806+ const fn = ( ) => {
1807+ const value = get_value ( ) ;
1808+ inspect ( value , initial ? 'init' : 'update' ) ;
1809+ } ;
1810+
1811+ inspect_fn = fn ;
1812+ const value = get_value ( ) ;
1813+ deep_read ( value ) ;
1814+ inspect_fn = null ;
1815+
1816+ const signals = inspect_captured_signals . slice ( ) ;
1817+ inspect_captured_signals = [ ] ;
1818+
1819+ if ( initial ) {
1820+ fn ( ) ;
1821+ initial = false ;
1822+ }
1823+
1824+ return ( ) => {
1825+ for ( const s of signals ) {
1826+ s . inspect . delete ( fn ) ;
1827+ }
1828+ } ;
1829+ } ) ;
1830+ }
0 commit comments