Skip to content

Commit 96e3fb6

Browse files
committed
tweak error message for readonly rest props
1 parent 7992ef8 commit 96e3fb6

File tree

2 files changed

+18
-11
lines changed

2 files changed

+18
-11
lines changed

packages/svelte/src/compiler/phases/3-transform/client/visitors/javascript-runes.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,9 @@ export const javascript_visitors_runes = {
211211
property.value.type === 'AssignmentPattern' ? property.value.left : property.value;
212212
assert.equal(id.type, 'Identifier');
213213
const binding = /** @type {import('#compiler').Binding} */ (state.scope.get(id.name));
214-
let initial = /** @type {import('estree').Expression | null} */ (binding.initial);
215-
if (initial) {
216-
initial = /** @type {import('estree').Expression} */ (visit(initial));
217-
}
214+
const initial =
215+
binding.initial &&
216+
/** @type {import('estree').Expression} */ (visit(binding.initial));
218217

219218
if (binding.reassigned || state.analysis.accessors || initial) {
220219
declarations.push(b.declarator(id, get_prop_source(binding, state, name, initial)));
@@ -223,6 +222,14 @@ export const javascript_visitors_runes = {
223222
// RestElement
224223
/** @type {import('estree').Expression[]} */
225224
const args = [b.id('$$props'), b.array(seen.map((name) => b.literal(name)))];
225+
226+
if (state.options.dev) {
227+
// include rest name, so we can provide informative error messages
228+
args.push(
229+
b.literal(/** @type {import('estree').Identifier} */ (property.argument).name)
230+
);
231+
}
232+
226233
declarations.push(b.declarator(property.argument, b.call('$.rest_props', ...args)));
227234
}
228235
}

packages/svelte/src/internal/client/reactivity/props.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,18 @@ export function update_pre_prop(fn, d = 1) {
3636
/**
3737
* The proxy handler for rest props (i.e. `const { x, ...rest } = $props()`).
3838
* Is passed the full `$$props` object and excludes the named props.
39-
* @type {ProxyHandler<{ props: Record<string | symbol, unknown>, exclude: Array<string | symbol> }>}}
39+
* @type {ProxyHandler<{ props: Record<string | symbol, unknown>, exclude: Array<string | symbol>, name: string }>}}
4040
*/
4141
const rest_props_handler = {
4242
get(target, key) {
4343
if (target.exclude.includes(key)) return;
4444
return target.props[key];
4545
},
46-
set(_, key) {
46+
set(target, key) {
4747
if (DEV) {
48-
throw new Error(
49-
`Cannot write to property '${String(key)}' of rest element of $props(). It is always readonly.`
50-
);
48+
throw new Error(`${target.name}.${String(key)} is readonly`);
5149
}
50+
5251
return false;
5352
},
5453
getOwnPropertyDescriptor(target, key) {
@@ -73,10 +72,11 @@ const rest_props_handler = {
7372
/**
7473
* @param {Record<string, unknown>} props
7574
* @param {string[]} rest
75+
* @param {string} [name]
7676
* @returns {Record<string, unknown>}
7777
*/
78-
export function rest_props(props, rest) {
79-
return new Proxy({ props, exclude: rest }, rest_props_handler);
78+
export function rest_props(props, rest, name) {
79+
return new Proxy({ props, exclude: rest, name }, rest_props_handler);
8080
}
8181

8282
/**

0 commit comments

Comments
 (0)