pull/16060/head
ComputerGuy 4 months ago
parent b5fcd112c6
commit 26173de279

@ -128,12 +128,17 @@ export function VariableDeclaration(node, context) {
const binding = /** @type {import('#compiler').Binding} */ (
context.state.scope.get(id.name)
);
if (rune === '$state' && should_proxy(value, context.state.scope)) {
value = b.call('$.proxy', value);
const is_state = is_state_source(binding, context.state.analysis);
const is_proxy = should_proxy(value, context.state.scope);
if (rune === '$state' && is_proxy) {
value = b.call('$.proxy', value, dev ? b.literal(id.name) : undefined);
}
if (is_state_source(binding, context.state.analysis)) {
if (is_state) {
value = b.call('$.state', value);
}
if (dev && is_state) {
value = b.call('$.tag_source', value, b.literal(id.name));
}
return value;
};
@ -154,7 +159,11 @@ export function VariableDeclaration(node, context) {
context.state.transform[id.name] = { read: get_value };
const expression = /** @type {Expression} */ (context.visit(b.thunk(value)));
return b.declarator(id, b.call('$.derived', expression));
const call = b.call('$.derived', expression);
return b.declarator(
id,
dev ? b.call('$.tag_source', call, b.literal(id.name)) : call
);
}),
...paths.map((path) => {
const value = /** @type {Expression} */ (context.visit(path.expression));
@ -176,8 +185,13 @@ export function VariableDeclaration(node, context) {
if (declarator.id.type === 'Identifier') {
let expression = /** @type {Expression} */ (context.visit(value));
if (rune === '$derived') expression = b.thunk(expression);
declarations.push(b.declarator(declarator.id, b.call('$.derived', expression)));
const call = b.call('$.derived', expression);
declarations.push(
b.declarator(
declarator.id,
dev ? b.call('$.tag_source', call, b.literal(declarator.id.name)) : call
)
);
} else {
const init = /** @type {CallExpression} */ (declarator.init);
@ -205,7 +219,19 @@ export function VariableDeclaration(node, context) {
for (const path of paths) {
const expression = /** @type {Expression} */ (context.visit(path.expression));
declarations.push(b.declarator(path.node, b.call('$.derived', b.thunk(expression))));
const call = b.call('$.derived', b.thunk(expression));
declarations.push(
b.declarator(
path.node,
dev
? b.call(
'$.tag_source',
call,
b.literal(/** @type {Identifier} */ (path.node).name)
)
: call
)
);
}
}

@ -25,3 +25,4 @@ export const EFFECT_IS_UPDATING = 1 << 21;
export const STATE_SYMBOL = Symbol('$state');
export const LEGACY_PROPS = Symbol('legacy props');
export const LOADING_ATTR_SYMBOL = Symbol('');
export const PROXY_PATH_SYMBOL = Symbol('proxy path');

@ -43,11 +43,14 @@ function log_entry(signal, entry) {
const type = (signal.f & DERIVED) !== 0 ? '$derived' : '$state';
const current_reaction = /** @type {Reaction} */ (active_reaction);
const dirty = signal.wv > current_reaction.wv || current_reaction.wv === 0;
const { trace_name: name } = signal;
const style = dirty
? 'color: CornflowerBlue; font-weight: bold'
: 'color: grey; font-weight: bold';
// eslint-disable-next-line no-console
console.groupCollapsed(
`%c${type}`,
dirty ? 'color: CornflowerBlue; font-weight: bold' : 'color: grey; font-weight: bold',
typeof name === 'string' ? `%c${name}${type}` : `%c${type}`,
style,
typeof value === 'object' && value !== null && STATE_SYMBOL in value
? snapshot(value, true)
: value
@ -92,11 +95,9 @@ export function trace(label, fn) {
var previously_tracing_expressions = tracing_expressions;
try {
tracing_expressions = { entries: new Map(), reaction: active_reaction };
var start = performance.now();
var value = fn();
var time = (performance.now() - start).toFixed(2);
if (!effect_tracking()) {
// eslint-disable-next-line no-console
console.log(`${label()} %cran outside of an effect (${time}ms)`, 'color: grey');
@ -177,3 +178,12 @@ export function get_stack(label) {
}
return error;
}
/**
* @param {Value} source
* @param {string} name
*/
export function tag_source(source, name) {
source.trace_name = name;
return source;
}

@ -7,7 +7,7 @@ export { add_locations } from './dev/elements.js';
export { hmr } from './dev/hmr.js';
export { create_ownership_validator } from './dev/ownership.js';
export { check_target, legacy_api } from './dev/legacy.js';
export { trace } from './dev/tracing.js';
export { trace, tag_source } from './dev/tracing.js';
export { inspect } from './dev/inspect.js';
export { validate_snippet_args } from './dev/validation.js';
export { await_block as await } from './dom/blocks/await.js';

@ -12,15 +12,16 @@ import { state as source, set } from './reactivity/sources.js';
import { STATE_SYMBOL } from '#client/constants';
import { UNINITIALIZED } from '../../constants.js';
import * as e from './errors.js';
import { get_stack } from './dev/tracing.js';
import { get_stack, tag_source } from './dev/tracing.js';
import { tracing_mode_flag } from '../flags/index.js';
/**
* @template T
* @param {T} value
* @param {string} [path]
* @returns {T}
*/
export function proxy(value) {
export function proxy(value, path) {
// if non-proxyable, or is already a proxy, return `value`
if (typeof value !== 'object' || value === null || STATE_SYMBOL in value) {
return value;
@ -39,6 +40,16 @@ export function proxy(value) {
var stack = DEV && tracing_mode_flag ? get_stack('CreatedAt') : null;
var reaction = active_reaction;
/** @type {(prop: any) => any} */
var to_trace_name = DEV
? (prop) => {
return typeof prop === 'symbol'
? `${path}[unique symbol]`
: typeof prop === 'number' || Number(prop) === Number(prop)
? `${path}[${prop}]`
: `${path}.${prop}`;
}
: (prop) => undefined;
/**
* @template T
@ -58,7 +69,8 @@ export function proxy(value) {
if (is_proxied_array) {
// We need to create the length source eagerly to ensure that
// mutations to the array are properly synced with our proxy
sources.set('length', source(/** @type {any[]} */ (value).length, stack));
const length_source = source(/** @type {any[]} */ (value).length, stack);
sources.set('length', DEV ? tag_source(length_source, to_trace_name('length')) : length_source);
}
return new Proxy(/** @type {any} */ (value), {
@ -80,11 +92,12 @@ export function proxy(value) {
if (s === undefined) {
s = with_parent(() => source(descriptor.value, stack));
s = DEV && typeof prop === 'string' ? tag_source(s, to_trace_name(prop)) : s;
sources.set(prop, s);
} else {
set(
s,
with_parent(() => proxy(descriptor.value))
with_parent(() => proxy(descriptor.value, to_trace_name(prop)))
);
}
@ -96,9 +109,10 @@ export function proxy(value) {
if (s === undefined) {
if (prop in target) {
const s = with_parent(() => source(UNINITIALIZED, stack));
sources.set(
prop,
with_parent(() => source(UNINITIALIZED, stack))
DEV && typeof prop === 'string' ? tag_source(s, to_trace_name(prop)) : s
);
update_version(version);
}
@ -130,7 +144,10 @@ export function proxy(value) {
// create a source, but only if it's an own property and not a prototype property
if (s === undefined && (!exists || get_descriptor(target, prop)?.writable)) {
s = with_parent(() => source(proxy(exists ? target[prop] : UNINITIALIZED), stack));
s = with_parent(() =>
source(proxy(exists ? target[prop] : UNINITIALIZED, to_trace_name(prop)), stack)
);
s = DEV && typeof prop === 'string' ? tag_source(s, to_trace_name(prop)) : s;
sources.set(prop, s);
}
@ -178,7 +195,10 @@ export function proxy(value) {
(active_effect !== null && (!has || get_descriptor(target, prop)?.writable))
) {
if (s === undefined) {
s = with_parent(() => source(has ? proxy(target[prop]) : UNINITIALIZED, stack));
s = with_parent(() =>
source(has ? proxy(target[prop], to_trace_name(prop)) : UNINITIALIZED, stack)
);
s = DEV && typeof prop === 'string' ? tag_source(s, to_trace_name(prop)) : s;
sources.set(prop, s);
}
@ -206,6 +226,7 @@ export function proxy(value) {
// else a later read of the property would result in a source being created with
// the value of the original item at that index.
other_s = with_parent(() => source(UNINITIALIZED, stack));
other_s = DEV ? tag_source(other_s, to_trace_name(i)) : other_s;
sources.set(i + '', other_s);
}
}
@ -218,9 +239,10 @@ export function proxy(value) {
if (s === undefined) {
if (!has || get_descriptor(target, prop)?.writable) {
s = with_parent(() => source(undefined, stack));
s = DEV && typeof prop === 'string' ? tag_source(s, to_trace_name(prop)) : s;
set(
s,
with_parent(() => proxy(value))
with_parent(() => proxy(value, to_trace_name(prop)))
);
sources.set(prop, s);
}
@ -228,7 +250,7 @@ export function proxy(value) {
has = s.v !== UNINITIALIZED;
set(
s,
with_parent(() => proxy(value))
with_parent(() => proxy(value, to_trace_name(prop)))
);
}

@ -139,7 +139,7 @@ export function set(source, value, should_proxy = false) {
e.state_unsafe_mutation();
}
let new_value = should_proxy ? proxy(value) : value;
let new_value = should_proxy ? proxy(value, DEV ? source.trace_name : undefined) : value;
return internal_set(source, new_value);
}

@ -21,6 +21,7 @@ export interface Value<V = unknown> extends Signal {
updated?: Error | null;
trace_need_increase?: boolean;
trace_v?: V;
trace_name?: string;
debug?: null | (() => void);
}

Loading…
Cancel
Save