diff --git a/packages/svelte/src/compiler/compile/render_dom/index.js b/packages/svelte/src/compiler/compile/render_dom/index.js index 9a11013fc9..c8532624de 100644 --- a/packages/svelte/src/compiler/compile/render_dom/index.js +++ b/packages/svelte/src/compiler/compile/render_dom/index.js @@ -584,7 +584,11 @@ export default function dom(component, options) { const slots_str = [...component.slots.keys()].map((key) => `"${key}"`).join(','); const accessors_str = accessors .filter((accessor) => !writable_props.some((prop) => prop.export_name === accessor.key.name)) - .map((accessor) => `"${accessor.key.name}"`) + .map((accessor) => { + return `{ name: "${accessor.key.name}", can_proxy: ${ + accessor.value?.type === 'FunctionExpression' + } }`; + }) .join(','); const use_shadow_dom = component.component_options.customElement?.shadow !== 'none' ? 'true' : 'false'; diff --git a/packages/svelte/src/runtime/internal/Component.js b/packages/svelte/src/runtime/internal/Component.js index cc27547721..d66c046bd4 100644 --- a/packages/svelte/src/runtime/internal/Component.js +++ b/packages/svelte/src/runtime/internal/Component.js @@ -388,7 +388,7 @@ function get_custom_element_value(prop, value, props_definition, transform) { * @param {import('./public.js').ComponentType} Component A Svelte component constructor * @param {Record} props_definition The props to observe * @param {string[]} slots The slots to create - * @param {string[]} accessors Other accessors besides the ones for props the component has + * @param {Array<{name: string, can_proxy: boolean}>} accessors Other accessors besides the ones for props the component has * @param {boolean} use_shadow_dom Whether to use shadow DOM */ export function create_custom_element( @@ -423,18 +423,24 @@ export function create_custom_element( }); }); accessors.forEach((accessor) => { - Object.defineProperty(Class.prototype, accessor, { + Object.defineProperty(Class.prototype, accessor.name, { get() { if (this.$$c) { - return this.$$c[accessor]; + return this.$$c[accessor.name]; } else { // This is only an approximation of what's possible. // It only handles the case where the accessor is a function without a return value - return (...args) => { - this.$$b.push(() => { - this.$$c[accessor](...args); - }); - }; + if (accessor.can_proxy) { + return (...args) => { + this.$$b.push(() => { + this.$$c[accessor.name](...args); + }); + }; + } else { + throw new Error( + `Cannot call '${accessor.name}' before the component is connected to the DOM` + ); + } } } });