diff --git a/.changeset/fluffy-colts-grin.md b/.changeset/fluffy-colts-grin.md new file mode 100644 index 0000000000..f4023f454d --- /dev/null +++ b/.changeset/fluffy-colts-grin.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +feat: move dev-time component properties to private symbols' diff --git a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js index e0e55c5337..0ef05eeac0 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js @@ -418,7 +418,7 @@ export function client_component(source, analysis, options) { if (options.hmr) { const accept_fn_body = [ - b.stmt(b.call('$.set', b.id('s'), b.member(b.id('module.default'), b.id('original')))) + b.stmt(b.call('$.set', b.id('s'), b.member(b.id('module.default'), b.id('$.ORIGINAL'), true))) ]; if (analysis.css.hash) { @@ -446,7 +446,11 @@ export function client_component(source, analysis, options) { // Assign the original component to the wrapper so we can use it on hot reload patching, // else we would call the HMR function two times b.stmt( - b.assignment('=', b.member(b.id(analysis.name), b.id('original')), b.id('$$original')) + b.assignment( + '=', + b.member(b.id(analysis.name), b.id('$.ORIGINAL'), true), + b.id('$$original') + ) ), b.stmt(b.call('import.meta.hot.accept', b.arrow([b.id('module')], b.block(accept_fn_body)))) ]); @@ -458,10 +462,14 @@ export function client_component(source, analysis, options) { if (options.dev) { if (filename) { - // add `App.filename = 'App.svelte'` so that we can print useful messages later + // add `App[$.FILENAME] = 'App.svelte'` so that we can print useful messages later body.unshift( b.stmt( - b.assignment('=', b.member(b.id(analysis.name), b.id('filename')), b.literal(filename)) + b.assignment( + '=', + b.member(b.id(analysis.name), b.id('$.FILENAME'), true), + b.literal(filename) + ) ) ); } diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js index d005b23c5d..573efe211a 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js @@ -1640,7 +1640,7 @@ export const template_visitors = { call = b.call( '$.add_locations', call, - b.member(b.id(context.state.analysis.name), b.id('filename')), + b.member(b.id(context.state.analysis.name), b.id('$.FILENAME'), true), serialize_locations(state.locations) ); } diff --git a/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js b/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js index 4519b06ead..3038316ede 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js @@ -2249,10 +2249,14 @@ export function server_component(analysis, options) { } if (options.dev && filename) { - // add `App.filename = 'App.svelte'` so that we can print useful messages later + // add `App[$.FILENAME] = 'App.svelte'` so that we can print useful messages later body.unshift( b.stmt( - b.assignment('=', b.member(b.id(analysis.name), b.id('filename')), b.literal(filename)) + b.assignment( + '=', + b.member(b.id(analysis.name), b.id('$.FILENAME'), true), + b.literal(filename) + ) ) ); } diff --git a/packages/svelte/src/constants.js b/packages/svelte/src/constants.js index 6f5b03ec38..f6adc94f50 100644 --- a/packages/svelte/src/constants.js +++ b/packages/svelte/src/constants.js @@ -30,6 +30,10 @@ export const ELEMENT_PRESERVE_ATTRIBUTE_CASE = 1 << 1; export const UNINITIALIZED = Symbol(); +// Dev-time component properties +export const FILENAME = Symbol('filename'); +export const ORIGINAL = Symbol('original'); + /** List of elements that require raw contents and should not have SSR comments put in them */ export const RawTextElements = ['textarea', 'script', 'style', 'title']; diff --git a/packages/svelte/src/internal/client/dev/legacy.js b/packages/svelte/src/internal/client/dev/legacy.js index 1262c62db0..25473f54c4 100644 --- a/packages/svelte/src/internal/client/dev/legacy.js +++ b/packages/svelte/src/internal/client/dev/legacy.js @@ -1,11 +1,12 @@ import * as e from '../errors.js'; import { current_component_context } from '../runtime.js'; +import { FILENAME } from '../../../constants.js'; import { get_component } from './ownership.js'; -/** @param {Function & { filename: string }} target */ +/** @param {Function & { [FILENAME]: string }} target */ export function check_target(target) { if (target) { - e.component_api_invalid_new(target.filename ?? 'a component', target.name); + e.component_api_invalid_new(target[FILENAME] ?? 'a component', target.name); } } @@ -15,8 +16,8 @@ export function legacy_api() { /** @param {string} method */ function error(method) { // @ts-expect-error - const parent = get_component()?.filename ?? 'Something'; - e.component_api_changed(parent, method, component.filename); + const parent = get_component()?.[FILENAME] ?? 'Something'; + e.component_api_changed(parent, method, component[FILENAME]); } return { diff --git a/packages/svelte/src/internal/client/dev/ownership.js b/packages/svelte/src/internal/client/dev/ownership.js index 4f07a57554..7d10118788 100644 --- a/packages/svelte/src/internal/client/dev/ownership.js +++ b/packages/svelte/src/internal/client/dev/ownership.js @@ -6,6 +6,7 @@ import { render_effect, user_pre_effect } from '../reactivity/effects.js'; import { dev_current_component_function } from '../runtime.js'; import { get_prototype_of } from '../../shared/utils.js'; import * as w from '../warnings.js'; +import { FILENAME } from '../../../constants.js'; /** @type {Record>} */ const boundaries = {}; @@ -115,8 +116,8 @@ export function add_owner(object, owner, global = false) { if (metadata && !has_owner(metadata, component)) { let original = get_owner(metadata); - if (owner.filename !== component.filename) { - w.ownership_invalid_binding(component.filename, owner.filename, original.filename); + if (owner[FILENAME] !== component[FILENAME]) { + w.ownership_invalid_binding(component[FILENAME], owner[FILENAME], original[FILENAME]); } } } @@ -236,9 +237,9 @@ export function check_ownership(metadata) { let original = get_owner(metadata); // @ts-expect-error - if (original.filename !== component.filename) { + if (original[FILENAME] !== component[FILENAME]) { // @ts-expect-error - w.ownership_invalid_mutation(component.filename, original.filename); + w.ownership_invalid_mutation(component[FILENAME], original[FILENAME]); } else { w.ownership_invalid_mutation(); } diff --git a/packages/svelte/src/internal/client/dom/blocks/html.js b/packages/svelte/src/internal/client/dom/blocks/html.js index 055d94a77a..3c4051261e 100644 --- a/packages/svelte/src/internal/client/dom/blocks/html.js +++ b/packages/svelte/src/internal/client/dom/blocks/html.js @@ -1,5 +1,5 @@ /** @import { Effect, TemplateNode } from '#client' */ -import { HYDRATION_ERROR } from '../../../../constants.js'; +import { FILENAME, HYDRATION_ERROR } from '../../../../constants.js'; import { block, branch, destroy_effect } from '../../reactivity/effects.js'; import { hydrate_next, hydrate_node, hydrating, set_hydrate_node } from '../hydration.js'; import { create_fragment_from_html } from '../reconciler.js'; @@ -23,8 +23,8 @@ function check_hash(element, server_hash, value) { const loc = element.__svelte_meta?.loc; if (loc) { location = `near ${loc.file}:${loc.line}:${loc.column}`; - } else if (dev_current_component_function?.filename) { - location = `in ${dev_current_component_function.filename}`; + } else if (dev_current_component_function?.[FILENAME]) { + location = `in ${dev_current_component_function[FILENAME]}`; } w.hydration_html_changed( diff --git a/packages/svelte/src/internal/client/dom/blocks/svelte-element.js b/packages/svelte/src/internal/client/dom/blocks/svelte-element.js index 1df6c8acab..e6886bb7fa 100644 --- a/packages/svelte/src/internal/client/dom/blocks/svelte-element.js +++ b/packages/svelte/src/internal/client/dom/blocks/svelte-element.js @@ -1,5 +1,5 @@ /** @import { Effect, EffectNodes, TemplateNode } from '#client' */ -import { namespace_svg } from '../../../../constants.js'; +import { FILENAME, namespace_svg } from '../../../../constants.js'; import { hydrate_next, hydrate_node, @@ -38,7 +38,7 @@ export function element(node, get_tag, is_svg, render_fn, get_namespace, locatio hydrate_next(); } - var filename = DEV && location && current_component_context?.function.filename; + var filename = DEV && location && current_component_context?.function[FILENAME]; /** @type {string | null} */ var tag; diff --git a/packages/svelte/src/internal/client/index.js b/packages/svelte/src/internal/client/index.js index e42efdcd11..60dd1d0aa2 100644 --- a/packages/svelte/src/internal/client/index.js +++ b/packages/svelte/src/internal/client/index.js @@ -1,3 +1,4 @@ +export { FILENAME, ORIGINAL } from '../../constants.js'; export { add_locations } from './dev/elements.js'; export { hmr } from './dev/hmr.js'; export { diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 78e0a7c8e0..922193f10e 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -29,6 +29,7 @@ import { mutate, set, source } from './reactivity/sources.js'; import { update_derived } from './reactivity/deriveds.js'; import * as e from './errors.js'; import { lifecycle_outside_component } from '../shared/errors.js'; +import { FILENAME } from '../../constants.js'; const FLUSH_MICROTASK = 0; const FLUSH_SYNC = 1; @@ -226,7 +227,7 @@ function handle_error(error, effect, component_context) { while (current_context !== null) { /** @type {string} */ - var filename = current_context.function?.filename; + var filename = current_context.function?.[FILENAME]; if (filename) { const file = filename.split('/').pop(); diff --git a/packages/svelte/src/internal/client/validate.js b/packages/svelte/src/internal/client/validate.js index 036936f9a8..5c6f6a6553 100644 --- a/packages/svelte/src/internal/client/validate.js +++ b/packages/svelte/src/internal/client/validate.js @@ -1,6 +1,7 @@ import { untrack } from './runtime.js'; import { get_descriptor, is_array } from '../shared/utils.js'; import * as e from './errors.js'; +import { FILENAME } from '../../constants.js'; /** regex of all html void element names */ const void_element_names = @@ -70,7 +71,7 @@ export function validate_each_keys(collection, key_fn) { * @param {Record} $$props * @param {string[]} bindable * @param {string[]} exports - * @param {Function & { filename: string }} component + * @param {Function & { [FILENAME]: string }} component */ export function validate_prop_bindings($$props, bindable, exports, component) { for (const key in $$props) { @@ -79,11 +80,11 @@ export function validate_prop_bindings($$props, bindable, exports, component) { if (setter) { if (exports.includes(key)) { - e.bind_invalid_export(component.filename, key, name); + e.bind_invalid_export(component[FILENAME], key, name); } if (!bindable.includes(key)) { - e.bind_not_bindable(key, component.filename, name); + e.bind_not_bindable(key, component[FILENAME], name); } } } diff --git a/packages/svelte/src/internal/server/dev.js b/packages/svelte/src/internal/server/dev.js index 870f9aa9d0..045dda5948 100644 --- a/packages/svelte/src/internal/server/dev.js +++ b/packages/svelte/src/internal/server/dev.js @@ -1,4 +1,5 @@ import { + FILENAME, disallowed_paragraph_contents, interactive_elements, is_tag_valid_with_parent @@ -56,7 +57,7 @@ function print_error(payload, parent, child) { * @param {number} column */ export function push_element(payload, tag, line, column) { - var filename = /** @type {import('#server').Component} */ (current_component).function.filename; + var filename = /** @type {import('#server').Component} */ (current_component).function[FILENAME]; var child = { tag, parent, filename, line, column }; if (parent !== null && !is_tag_valid_with_parent(tag, parent.tag)) { diff --git a/packages/svelte/src/internal/server/index.js b/packages/svelte/src/internal/server/index.js index 2cb741ad95..a1a2d3febc 100644 --- a/packages/svelte/src/internal/server/index.js +++ b/packages/svelte/src/internal/server/index.js @@ -1,5 +1,6 @@ /** @import { Component, Payload, RenderOutput } from '#server' */ /** @import { Store } from '#shared' */ +export { FILENAME, ORIGINAL } from '../../constants.js'; import { is_promise, noop } from '../shared/utils.js'; import { subscribe_to_store } from '../../store/utils.js'; import { diff --git a/packages/svelte/tests/snapshot/samples/hmr/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/hmr/_expected/client/index.svelte.js index 9037c5dd25..44600907c1 100644 --- a/packages/svelte/tests/snapshot/samples/hmr/_expected/client/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/hmr/_expected/client/index.svelte.js @@ -16,10 +16,10 @@ if (import.meta.hot) { Hmr = $.hmr(s); Hmr.filename = filename; - Hmr.original = $$original; + Hmr[$.ORIGINAL] = $$original; import.meta.hot.accept((module) => { - $.set(s, module.default.original); + $.set(s, module.default[$.ORIGINAL]); }); }