tweak error message for readonly rest props

pull/10868/head
Rich Harris 2 years ago
parent 7992ef84be
commit 96e3fb61c9

@ -211,10 +211,9 @@ export const javascript_visitors_runes = {
property.value.type === 'AssignmentPattern' ? property.value.left : property.value; property.value.type === 'AssignmentPattern' ? property.value.left : property.value;
assert.equal(id.type, 'Identifier'); assert.equal(id.type, 'Identifier');
const binding = /** @type {import('#compiler').Binding} */ (state.scope.get(id.name)); const binding = /** @type {import('#compiler').Binding} */ (state.scope.get(id.name));
let initial = /** @type {import('estree').Expression | null} */ (binding.initial); const initial =
if (initial) { binding.initial &&
initial = /** @type {import('estree').Expression} */ (visit(initial)); /** @type {import('estree').Expression} */ (visit(binding.initial));
}
if (binding.reassigned || state.analysis.accessors || initial) { if (binding.reassigned || state.analysis.accessors || initial) {
declarations.push(b.declarator(id, get_prop_source(binding, state, name, initial))); declarations.push(b.declarator(id, get_prop_source(binding, state, name, initial)));
@ -223,6 +222,14 @@ export const javascript_visitors_runes = {
// RestElement // RestElement
/** @type {import('estree').Expression[]} */ /** @type {import('estree').Expression[]} */
const args = [b.id('$$props'), b.array(seen.map((name) => b.literal(name)))]; const args = [b.id('$$props'), b.array(seen.map((name) => b.literal(name)))];
if (state.options.dev) {
// include rest name, so we can provide informative error messages
args.push(
b.literal(/** @type {import('estree').Identifier} */ (property.argument).name)
);
}
declarations.push(b.declarator(property.argument, b.call('$.rest_props', ...args))); declarations.push(b.declarator(property.argument, b.call('$.rest_props', ...args)));
} }
} }

@ -36,19 +36,18 @@ export function update_pre_prop(fn, d = 1) {
/** /**
* The proxy handler for rest props (i.e. `const { x, ...rest } = $props()`). * The proxy handler for rest props (i.e. `const { x, ...rest } = $props()`).
* Is passed the full `$$props` object and excludes the named props. * Is passed the full `$$props` object and excludes the named props.
* @type {ProxyHandler<{ props: Record<string | symbol, unknown>, exclude: Array<string | symbol> }>}} * @type {ProxyHandler<{ props: Record<string | symbol, unknown>, exclude: Array<string | symbol>, name: string }>}}
*/ */
const rest_props_handler = { const rest_props_handler = {
get(target, key) { get(target, key) {
if (target.exclude.includes(key)) return; if (target.exclude.includes(key)) return;
return target.props[key]; return target.props[key];
}, },
set(_, key) { set(target, key) {
if (DEV) { if (DEV) {
throw new Error( throw new Error(`${target.name}.${String(key)} is readonly`);
`Cannot write to property '${String(key)}' of rest element of $props(). It is always readonly.`
);
} }
return false; return false;
}, },
getOwnPropertyDescriptor(target, key) { getOwnPropertyDescriptor(target, key) {
@ -73,10 +72,11 @@ const rest_props_handler = {
/** /**
* @param {Record<string, unknown>} props * @param {Record<string, unknown>} props
* @param {string[]} rest * @param {string[]} rest
* @param {string} [name]
* @returns {Record<string, unknown>} * @returns {Record<string, unknown>}
*/ */
export function rest_props(props, rest) { export function rest_props(props, rest, name) {
return new Proxy({ props, exclude: rest }, rest_props_handler); return new Proxy({ props, exclude: rest, name }, rest_props_handler);
} }
/** /**

Loading…
Cancel
Save