From 29ca451c9eebdfb761bed2fb9f79b045a94c463c Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 17 Jun 2024 09:10:34 -0700 Subject: [PATCH] chore: tidier generated message code (#12062) * chore: tidier generated message code * lint --- .../svelte/scripts/process-messages/index.js | 48 +++++++++++++++++++ packages/svelte/src/internal/client/errors.js | 36 +++++++------- .../svelte/src/internal/client/warnings.js | 12 ++--- packages/svelte/src/internal/server/errors.js | 2 +- packages/svelte/src/internal/shared/errors.js | 10 ++-- .../svelte/src/internal/shared/warnings.js | 2 +- 6 files changed, 79 insertions(+), 31 deletions(-) diff --git a/packages/svelte/scripts/process-messages/index.js b/packages/svelte/scripts/process-messages/index.js index 71a979d516..ea0a40c496 100644 --- a/packages/svelte/scripts/process-messages/index.js +++ b/packages/svelte/scripts/process-messages/index.js @@ -293,6 +293,54 @@ function transform(name, dest) { } }); }, + TemplateLiteral(node, context) { + /** @type {import('estree').TemplateElement} */ + let quasi = { + type: 'TemplateElement', + value: { + ...node.quasis[0].value + }, + tail: node.quasis[0].tail + }; + + /** @type {import('estree').TemplateLiteral} */ + let out = { + type: 'TemplateLiteral', + quasis: [quasi], + expressions: [] + }; + + for (let i = 0; i < node.expressions.length; i += 1) { + const q = node.quasis[i + 1]; + const e = node.expressions[i]; + + if (e.type === 'Literal' && e.value === 'CODE') { + quasi.value.raw += code + q.value.raw; + continue; + } + + if (e.type === 'Identifier' && e.name === 'MESSAGE') { + if (message.type === 'Literal') { + const str = /** @type {string} */ (message.value).replace(/(`|\${)/g, '\\$1'); + quasi.value.raw += str + q.value.raw; + continue; + } + + if (message.type === 'TemplateLiteral') { + quasi.value.raw += message.quasis[0].value.raw + q.value.raw; + out.quasis.push(...message.quasis.slice(1)); + out.expressions.push(...message.expressions); + quasi = message.quasis[message.quasis.length - 1]; + continue; + } + } + + out.quasis.push((quasi = q)); + out.expressions.push(/** @type {import('estree').Expression} */ (context.visit(e))); + } + + return out; + }, Literal(node) { if (node.value === 'CODE') { return { diff --git a/packages/svelte/src/internal/client/errors.js b/packages/svelte/src/internal/client/errors.js index e344c552da..ba41a560c3 100644 --- a/packages/svelte/src/internal/client/errors.js +++ b/packages/svelte/src/internal/client/errors.js @@ -8,7 +8,7 @@ import { DEV } from 'esm-env'; */ export function bind_invalid_checkbox_value() { if (DEV) { - const error = new Error(`${"bind_invalid_checkbox_value"}\n${"Using `bind:value` together with a checkbox input is not allowed. Use `bind:checked` instead"}`); + const error = new Error(`bind_invalid_checkbox_value\nUsing \`bind:value\` together with a checkbox input is not allowed. Use \`bind:checked\` instead`); error.name = 'Svelte error'; throw error; @@ -27,7 +27,7 @@ export function bind_invalid_checkbox_value() { */ export function bind_invalid_export(component, key, name) { if (DEV) { - const error = new Error(`${"bind_invalid_export"}\n${`Component ${component} has an export named \`${key}\` that a consumer component is trying to access using \`bind:${key}\`, which is disallowed. Instead, use \`bind:this\` (e.g. \`<${name} bind:this={component} />\`) and then access the property on the bound component instance (e.g. \`component.${key}\`)`}`); + const error = new Error(`bind_invalid_export\nComponent ${component} has an export named \`${key}\` that a consumer component is trying to access using \`bind:${key}\`, which is disallowed. Instead, use \`bind:this\` (e.g. \`<${name} bind:this={component} />\`) and then access the property on the bound component instance (e.g. \`component.${key}\`)`); error.name = 'Svelte error'; throw error; @@ -46,7 +46,7 @@ export function bind_invalid_export(component, key, name) { */ export function bind_not_bindable(key, component, name) { if (DEV) { - const error = new Error(`${"bind_not_bindable"}\n${`A component is attempting to bind to a non-bindable property \`${key}\` belonging to ${component} (i.e. \`<${name} bind:${key}={...}>\`). To mark a property as bindable: \`let { ${key} = $bindable() } = $props()\``}`); + const error = new Error(`bind_not_bindable\nA component is attempting to bind to a non-bindable property \`${key}\` belonging to ${component} (i.e. \`<${name} bind:${key}={...}>\`). To mark a property as bindable: \`let { ${key} = $bindable() } = $props()\``); error.name = 'Svelte error'; throw error; @@ -65,7 +65,7 @@ export function bind_not_bindable(key, component, name) { */ export function component_api_changed(parent, method, component) { if (DEV) { - const error = new Error(`${"component_api_changed"}\n${`${parent} called \`${method}\` on an instance of ${component}, which is no longer valid in Svelte 5. See https://svelte-5-preview.vercel.app/docs/breaking-changes#components-are-no-longer-classes for more information`}`); + const error = new Error(`component_api_changed\n${parent} called \`${method}\` on an instance of ${component}, which is no longer valid in Svelte 5. See https://svelte-5-preview.vercel.app/docs/breaking-changes#components-are-no-longer-classes for more information`); error.name = 'Svelte error'; throw error; @@ -83,7 +83,7 @@ export function component_api_changed(parent, method, component) { */ export function component_api_invalid_new(component, name) { if (DEV) { - const error = new Error(`${"component_api_invalid_new"}\n${`Attempted to instantiate ${component} with \`new ${name}\`, which is no longer valid in Svelte 5. If this component is not under your control, set the \`legacy.componentApi\` compiler option to keep it working. See https://svelte-5-preview.vercel.app/docs/breaking-changes#components-are-no-longer-classes for more information`}`); + const error = new Error(`component_api_invalid_new\nAttempted to instantiate ${component} with \`new ${name}\`, which is no longer valid in Svelte 5. If this component is not under your control, set the \`legacy.componentApi\` compiler option to keep it working. See https://svelte-5-preview.vercel.app/docs/breaking-changes#components-are-no-longer-classes for more information`); error.name = 'Svelte error'; throw error; @@ -102,7 +102,7 @@ export function component_api_invalid_new(component, name) { */ export function each_key_duplicate(a, b, value) { if (DEV) { - const error = new Error(`${"each_key_duplicate"}\n${value ? `Keyed each block has duplicate key \`${value}\` at indexes ${a} and ${b}` : `Keyed each block has duplicate key at indexes ${a} and ${b}`}`); + const error = new Error(`each_key_duplicate\n${value ? `Keyed each block has duplicate key \`${value}\` at indexes ${a} and ${b}` : `Keyed each block has duplicate key at indexes ${a} and ${b}`}`); error.name = 'Svelte error'; throw error; @@ -119,7 +119,7 @@ export function each_key_duplicate(a, b, value) { */ export function effect_in_teardown(rune) { if (DEV) { - const error = new Error(`${"effect_in_teardown"}\n${`\`${rune}\` cannot be used inside an effect cleanup function`}`); + const error = new Error(`effect_in_teardown\n\`${rune}\` cannot be used inside an effect cleanup function`); error.name = 'Svelte error'; throw error; @@ -135,7 +135,7 @@ export function effect_in_teardown(rune) { */ export function effect_in_unowned_derived() { if (DEV) { - const error = new Error(`${"effect_in_unowned_derived"}\n${"Effect cannot be created inside a `$derived` value that was not itself created inside an effect"}`); + const error = new Error(`effect_in_unowned_derived\nEffect cannot be created inside a \`$derived\` value that was not itself created inside an effect`); error.name = 'Svelte error'; throw error; @@ -152,7 +152,7 @@ export function effect_in_unowned_derived() { */ export function effect_orphan(rune) { if (DEV) { - const error = new Error(`${"effect_orphan"}\n${`\`${rune}\` can only be used inside an effect (e.g. during component initialisation)`}`); + const error = new Error(`effect_orphan\n\`${rune}\` can only be used inside an effect (e.g. during component initialisation)`); error.name = 'Svelte error'; throw error; @@ -168,7 +168,7 @@ export function effect_orphan(rune) { */ export function effect_update_depth_exceeded() { if (DEV) { - const error = new Error(`${"effect_update_depth_exceeded"}\n${"Maximum update depth exceeded. This can happen when a reactive block or effect repeatedly sets a new value. Svelte limits the number of nested updates to prevent infinite loops"}`); + const error = new Error(`effect_update_depth_exceeded\nMaximum update depth exceeded. This can happen when a reactive block or effect repeatedly sets a new value. Svelte limits the number of nested updates to prevent infinite loops`); error.name = 'Svelte error'; throw error; @@ -184,7 +184,7 @@ export function effect_update_depth_exceeded() { */ export function hydration_failed() { if (DEV) { - const error = new Error(`${"hydration_failed"}\n${"Failed to hydrate the application"}`); + const error = new Error(`hydration_failed\nFailed to hydrate the application`); error.name = 'Svelte error'; throw error; @@ -201,7 +201,7 @@ export function hydration_failed() { */ export function lifecycle_legacy_only(name) { if (DEV) { - const error = new Error(`${"lifecycle_legacy_only"}\n${`\`${name}(...)\` cannot be used in runes mode`}`); + const error = new Error(`lifecycle_legacy_only\n\`${name}(...)\` cannot be used in runes mode`); error.name = 'Svelte error'; throw error; @@ -218,7 +218,7 @@ export function lifecycle_legacy_only(name) { */ export function props_invalid_value(key) { if (DEV) { - const error = new Error(`${"props_invalid_value"}\n${`Cannot do \`bind:${key}={undefined}\` when \`${key}\` has a fallback value`}`); + const error = new Error(`props_invalid_value\nCannot do \`bind:${key}={undefined}\` when \`${key}\` has a fallback value`); error.name = 'Svelte error'; throw error; @@ -235,7 +235,7 @@ export function props_invalid_value(key) { */ export function props_rest_readonly(property) { if (DEV) { - const error = new Error(`${"props_rest_readonly"}\n${`Rest element properties of \`$props()\` such as \`${property}\` are readonly`}`); + const error = new Error(`props_rest_readonly\nRest element properties of \`$props()\` such as \`${property}\` are readonly`); error.name = 'Svelte error'; throw error; @@ -252,7 +252,7 @@ export function props_rest_readonly(property) { */ export function rune_outside_svelte(rune) { if (DEV) { - const error = new Error(`${"rune_outside_svelte"}\n${`The \`${rune}\` rune is only available inside \`.svelte\` and \`.svelte.js/ts\` files`}`); + const error = new Error(`rune_outside_svelte\nThe \`${rune}\` rune is only available inside \`.svelte\` and \`.svelte.js/ts\` files`); error.name = 'Svelte error'; throw error; @@ -268,7 +268,7 @@ export function rune_outside_svelte(rune) { */ export function state_prototype_fixed() { if (DEV) { - const error = new Error(`${"state_prototype_fixed"}\n${"Cannot set prototype of `$state` object"}`); + const error = new Error(`state_prototype_fixed\nCannot set prototype of \`$state\` object`); error.name = 'Svelte error'; throw error; @@ -284,7 +284,7 @@ export function state_prototype_fixed() { */ export function state_unsafe_mutation() { if (DEV) { - const error = new Error(`${"state_unsafe_mutation"}\n${"Updating state inside a derived is forbidden. If the value should not be reactive, declare it without `$state`"}`); + const error = new Error(`state_unsafe_mutation\nUpdating state inside a derived is forbidden. If the value should not be reactive, declare it without \`$state\``); error.name = 'Svelte error'; throw error; @@ -300,7 +300,7 @@ export function state_unsafe_mutation() { */ export function svelte_component_invalid_this_value() { if (DEV) { - const error = new Error(`${"svelte_component_invalid_this_value"}\n${"The `this={...}` property of a `` must be a Svelte component, if defined"}`); + const error = new Error(`svelte_component_invalid_this_value\nThe \`this={...}\` property of a \`\` must be a Svelte component, if defined`); error.name = 'Svelte error'; throw error; diff --git a/packages/svelte/src/internal/client/warnings.js b/packages/svelte/src/internal/client/warnings.js index e5befc8474..576453e525 100644 --- a/packages/svelte/src/internal/client/warnings.js +++ b/packages/svelte/src/internal/client/warnings.js @@ -13,7 +13,7 @@ var normal = 'font-weight: normal'; */ export function hydration_attribute_changed(attribute, html, value) { if (DEV) { - console.warn(`%c[svelte] ${"hydration_attribute_changed"}\n%c${`The \`${attribute}\` attribute on \`${html}\` changed its value between server and client renders. The client value, \`${value}\`, will be ignored in favour of the server value`}`, bold, normal); + console.warn(`%c[svelte] hydration_attribute_changed\n%cThe \`${attribute}\` attribute on \`${html}\` changed its value between server and client renders. The client value, \`${value}\`, will be ignored in favour of the server value`, bold, normal); } else { // TODO print a link to the documentation console.warn("hydration_attribute_changed"); @@ -26,7 +26,7 @@ export function hydration_attribute_changed(attribute, html, value) { */ export function hydration_mismatch(location) { if (DEV) { - console.warn(`%c[svelte] ${"hydration_mismatch"}\n%c${location ? `Hydration failed because the initial UI does not match what was rendered on the server. The error occurred near ${location}` : "Hydration failed because the initial UI does not match what was rendered on the server"}`, bold, normal); + console.warn(`%c[svelte] hydration_mismatch\n%c${location ? `Hydration failed because the initial UI does not match what was rendered on the server. The error occurred near ${location}` : "Hydration failed because the initial UI does not match what was rendered on the server"}`, bold, normal); } else { // TODO print a link to the documentation console.warn("hydration_mismatch"); @@ -38,7 +38,7 @@ export function hydration_mismatch(location) { */ export function lifecycle_double_unmount() { if (DEV) { - console.warn(`%c[svelte] ${"lifecycle_double_unmount"}\n%c${"Tried to unmount a component that was not mounted"}`, bold, normal); + console.warn(`%c[svelte] lifecycle_double_unmount\n%cTried to unmount a component that was not mounted`, bold, normal); } else { // TODO print a link to the documentation console.warn("lifecycle_double_unmount"); @@ -53,7 +53,7 @@ export function lifecycle_double_unmount() { */ export function ownership_invalid_binding(parent, child, owner) { if (DEV) { - console.warn(`%c[svelte] ${"ownership_invalid_binding"}\n%c${`${parent} passed a value to ${child} with \`bind:\`, but the value is owned by ${owner}. Consider creating a binding between ${owner} and ${parent}`}`, bold, normal); + console.warn(`%c[svelte] ownership_invalid_binding\n%c${parent} passed a value to ${child} with \`bind:\`, but the value is owned by ${owner}. Consider creating a binding between ${owner} and ${parent}`, bold, normal); } else { // TODO print a link to the documentation console.warn("ownership_invalid_binding"); @@ -67,7 +67,7 @@ export function ownership_invalid_binding(parent, child, owner) { */ export function ownership_invalid_mutation(component, owner) { if (DEV) { - console.warn(`%c[svelte] ${"ownership_invalid_mutation"}\n%c${component ? `${component} mutated a value owned by ${owner}. This is strongly discouraged. Consider passing values to child components with \`bind:\`, or use a callback instead` : "Mutating a value outside the component that created it is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead"}`, bold, normal); + console.warn(`%c[svelte] ownership_invalid_mutation\n%c${component ? `${component} mutated a value owned by ${owner}. This is strongly discouraged. Consider passing values to child components with \`bind:\`, or use a callback instead` : "Mutating a value outside the component that created it is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead"}`, bold, normal); } else { // TODO print a link to the documentation console.warn("ownership_invalid_mutation"); @@ -80,7 +80,7 @@ export function ownership_invalid_mutation(component, owner) { */ export function state_proxy_equality_mismatch(operator) { if (DEV) { - console.warn(`%c[svelte] ${"state_proxy_equality_mismatch"}\n%c${`Reactive \`$state(...)\` proxies and the values they proxy have different identities. Because of this, comparisons with \`${operator}\` will produce unexpected results. Consider using \`$state.is(a, b)\` instead`}`, bold, normal); + console.warn(`%c[svelte] state_proxy_equality_mismatch\n%cReactive \`$state(...)\` proxies and the values they proxy have different identities. Because of this, comparisons with \`${operator}\` will produce unexpected results. Consider using \`$state.is(a, b)\` instead`, bold, normal); } else { // TODO print a link to the documentation console.warn("state_proxy_equality_mismatch"); diff --git a/packages/svelte/src/internal/server/errors.js b/packages/svelte/src/internal/server/errors.js index 848e2e6e50..67f4a2dfc6 100644 --- a/packages/svelte/src/internal/server/errors.js +++ b/packages/svelte/src/internal/server/errors.js @@ -6,7 +6,7 @@ * @returns {never} */ export function lifecycle_function_unavailable(name) { - const error = new Error(`${"lifecycle_function_unavailable"}\n${`\`${name}(...)\` is not available on the server`}`); + const error = new Error(`lifecycle_function_unavailable\n\`${name}(...)\` is not available on the server`); error.name = 'Svelte error'; throw error; diff --git a/packages/svelte/src/internal/shared/errors.js b/packages/svelte/src/internal/shared/errors.js index 4bfc595fa2..984b86a54d 100644 --- a/packages/svelte/src/internal/shared/errors.js +++ b/packages/svelte/src/internal/shared/errors.js @@ -9,7 +9,7 @@ import { DEV } from 'esm-env'; */ export function lifecycle_outside_component(name) { if (DEV) { - const error = new Error(`${"lifecycle_outside_component"}\n${`\`${name}(...)\` can only be used during component initialisation`}`); + const error = new Error(`lifecycle_outside_component\n\`${name}(...)\` can only be used during component initialisation`); error.name = 'Svelte error'; throw error; @@ -25,7 +25,7 @@ export function lifecycle_outside_component(name) { */ export function render_tag_invalid_argument() { if (DEV) { - const error = new Error(`${"render_tag_invalid_argument"}\n${"The argument to `{@render ...}` must be a snippet function, not a component or some other kind of function. If you want to dynamically render one snippet or another, use `$derived` and pass its result to `{@render ...}`"}`); + const error = new Error(`render_tag_invalid_argument\nThe argument to \`{@render ...}\` must be a snippet function, not a component or some other kind of function. If you want to dynamically render one snippet or another, use \`$derived\` and pass its result to \`{@render ...}\``); error.name = 'Svelte error'; throw error; @@ -41,7 +41,7 @@ export function render_tag_invalid_argument() { */ export function snippet_used_as_component() { if (DEV) { - const error = new Error(`${"snippet_used_as_component"}\n${"A snippet must be rendered with `{@render ...}`"}`); + const error = new Error(`snippet_used_as_component\nA snippet must be rendered with \`{@render ...}\``); error.name = 'Svelte error'; throw error; @@ -58,7 +58,7 @@ export function snippet_used_as_component() { */ export function store_invalid_shape(name) { if (DEV) { - const error = new Error(`${"store_invalid_shape"}\n${`\`${name}\` is not a store with a \`subscribe\` method`}`); + const error = new Error(`store_invalid_shape\n\`${name}\` is not a store with a \`subscribe\` method`); error.name = 'Svelte error'; throw error; @@ -74,7 +74,7 @@ export function store_invalid_shape(name) { */ export function svelte_element_invalid_this_value() { if (DEV) { - const error = new Error(`${"svelte_element_invalid_this_value"}\n${"The `this` prop on `` must be a string, if defined"}`); + const error = new Error(`svelte_element_invalid_this_value\nThe \`this\` prop on \`\` must be a string, if defined`); error.name = 'Svelte error'; throw error; diff --git a/packages/svelte/src/internal/shared/warnings.js b/packages/svelte/src/internal/shared/warnings.js index effcd13c57..2fc1b6fdd2 100644 --- a/packages/svelte/src/internal/shared/warnings.js +++ b/packages/svelte/src/internal/shared/warnings.js @@ -11,7 +11,7 @@ var normal = 'font-weight: normal'; */ export function dynamic_void_element_content(tag) { if (DEV) { - console.warn(`%c[svelte] ${"dynamic_void_element_content"}\n%c${`\`\` is a void element — it cannot have content`}`, bold, normal); + console.warn(`%c[svelte] dynamic_void_element_content\n%c\`\` is a void element — it cannot have content`, bold, normal); } else { // TODO print a link to the documentation console.warn("dynamic_void_element_content");