diff --git a/packages/svelte/src/compiler/migrate/index.js b/packages/svelte/src/compiler/migrate/index.js index 5ca9adb98b..05efd22e5f 100644 --- a/packages/svelte/src/compiler/migrate/index.js +++ b/packages/svelte/src/compiler/migrate/index.js @@ -18,7 +18,7 @@ import { import { migrate_svelte_ignore } from '../utils/extract_svelte_ignore.js'; import { validate_component_options } from '../validate-options.js'; import { is_reserved, is_svg, is_void } from '../../utils.js'; -import { regex_is_valid_identifier } from '../phases/patterns.js'; +import { regex_is_valid_identifier } from '../../regexes.js'; const regex_style_tags = /(]+>)([\S\s]*?)(<\/style>)/g; const style_placeholder = '/*$$__STYLE_CONTENT__$$*/'; diff --git a/packages/svelte/src/internal/client/proxy.js b/packages/svelte/src/internal/client/proxy.js index cd3fbb3249..f25d940fe3 100644 --- a/packages/svelte/src/internal/client/proxy.js +++ b/packages/svelte/src/internal/client/proxy.js @@ -15,6 +15,9 @@ import * as e from './errors.js'; import { get_stack, tag } from './dev/tracing.js'; import { tracing_mode_flag } from '../flags/index.js'; +// TODO move all regexes into shared module? +const regex_is_valid_identifier = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/; + /** * @template T * @param {T} value @@ -23,17 +26,11 @@ import { tracing_mode_flag } from '../flags/index.js'; * @returns {T} */ export function proxy(value, path, change_path = false) { - // if `DEV`, change the proxy `path` since we don't know if its still "owned" by its original source - if ( - DEV && - change_path && - typeof value === 'object' && - value !== null && - STATE_SYMBOL in value && - PROXY_PATH_SYMBOL in value - ) { - value[PROXY_PATH_SYMBOL] = path; + if (DEV && change_path) { + // @ts-expect-error + value?.[PROXY_PATH_SYMBOL]?.(path); } + // if non-proxyable, or is already a proxy, return `value` if (typeof value !== 'object' || value === null || STATE_SYMBOL in value) { return value; @@ -52,16 +49,6 @@ export function proxy(value, path, change_path = false) { 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}[Symbol(${prop.description ?? ''})]` - : typeof prop === 'number' || Number(prop) === Number(prop) - ? `${path}[${prop}]` - : `${path}.${prop}`; - } - : (prop) => undefined; /** * @template T @@ -85,6 +72,28 @@ export function proxy(value, path, change_path = false) { sources.set('length', DEV ? tag(length_source, to_trace_name('length')) : length_source); } + /** @param {string | symbol} prop */ + function to_trace_name(prop) { + if (typeof prop === 'symbol') return `${path}[Symbol(${prop.description ?? ''})]`; + if (regex_is_valid_identifier.test(prop)) return `${path}.${prop}`; + return /^\d+$/.test(prop) ? `${path}[${prop}]` : `${path}['${prop}']`; + } + + /** @param {string} new_path */ + function update_path(new_path) { + path = new_path; + + tag(version, `${path} version`); + + // rename all child sources and child proxies + for (const [prop, source] of sources) { + var label = to_trace_name(prop); + + tag(source, label); + source.v?.[PROXY_PATH_SYMBOL]?.(label); + } + } + return new Proxy(/** @type {any} */ (value), { defineProperty(_, prop, descriptor) { if ( @@ -147,8 +156,9 @@ export function proxy(value, path, change_path = false) { if (prop === STATE_SYMBOL) { return value; } + if (DEV && prop === PROXY_PATH_SYMBOL) { - return path; + return update_path; } var s = sources.get(prop); @@ -195,7 +205,7 @@ export function proxy(value, path, change_path = false) { }, has(target, prop) { - if (prop === STATE_SYMBOL || (DEV && prop === PROXY_PATH_SYMBOL)) { + if (prop === STATE_SYMBOL) { return true; } @@ -224,17 +234,6 @@ export function proxy(value, path, change_path = false) { }, set(target, prop, value, receiver) { - if (DEV && prop === PROXY_PATH_SYMBOL) { - path = value; - tag(version, `${path} version`); - // rename all child sources and child proxies - for (const [prop, source] of sources) { - tag(source, to_trace_name(prop)); - if (typeof source.v === 'object' && source.v !== null && PROXY_PATH_SYMBOL in source.v) { - source.v[PROXY_PATH_SYMBOL] = to_trace_name(prop); - } - } - } var s = sources.get(prop); var has = prop in target;