Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cannot export functions from custom elements in dev #8971

Closed
WickyNilliams opened this issue Jul 14, 2023 · 4 comments · Fixed by #8996
Closed

cannot export functions from custom elements in dev #8971

WickyNilliams opened this issue Jul 14, 2023 · 4 comments · Fixed by #8996

Comments

@WickyNilliams
Copy link

WickyNilliams commented Jul 14, 2023

Describe the bug

in dev, if you export a function from a svelte component that is a custom element, you receive an error in the console:

Uncaught TypeError: can't redefine non-configurable property "[function name]"

In the compiled code, the customElements.define call looks like this:

customElements.define("my-test", create_custom_element(Test, {}, [], ["[function name]", "[function name]"], true));

This does not seem to happen when building in non-dev mode.

Reproduction

Here is a basic example:

<svelte:options customElement="my-counter" />
<script>
  let count = 0;
  export function increment() {
    count += 1;
  }
</script>

<button on:click={increment}>
  count is {count}
</button>

And here is a REPL: https://svelte.dev/repl/c66893a2ff384eac854af6ec4bf10810?version=4.0.5

Please turn on customElements and dev in compiler options.

Logs

Uncaught TypeError: can't redefine non-configurable property "increment"

System Info

❯ npx envinfo --system --npmPackages svelte,rollup,webpack --binaries --browsers

  System:
    OS: macOS 13.4.1
    CPU: (10) arm64 Apple M1 Max
    Memory: 935.45 MB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.15.0 - ~/Library/Caches/fnm_multishells/35024_1689330689567/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 9.5.0 - ~/Library/Caches/fnm_multishells/35024_1689330689567/bin/npm
  Browsers:
    Chrome: 114.0.5735.198
    Firefox: 114.0.2
    Safari: 16.5.1
  npmPackages:
    svelte: ^4.0.3 => 4.0.5

Severity

annoyance

@dummdidumm
Copy link
Member

I can't reproduce this in the REPL. Are you using hot module reloading by any chance? That's known to cause issues with custom elements.

@WickyNilliams
Copy link
Author

WickyNilliams commented Jul 14, 2023

I don't think it's related to HMR, this happens on a fresh page load.

I think it's difficult to accurately reproduce in the repl, because App.svelte is rendered for you, so you can't actually use the component as a custom element via its tagname. But if you look at the generated code, you will see

customElements.define("my-counter", create_custom_element(App, {}, [], ["increment","increment"], true));

that then fails here, becuse "increment" is being defined twice:

accessors.forEach((accessor) => {
Object.defineProperty(Class.prototype, accessor, {
get() {
return this.$$c?.[accessor];
}
});
});

@WickyNilliams
Copy link
Author

Compare the code output in dev mode:

class App extends SvelteComponentDev {
	constructor(options) {
		super(options);
		init(this, options, instance, create_fragment, safe_not_equal, { increment: 0 });

		dispatch_dev("SvelteRegisterComponent", {
			component: this,
			tagName: "App",
			options,
			id: create_fragment.name
		});
	}

	get increment() {
		return this.$$.ctx[0];
	}

	set increment(value) {
		throw new Error("<my-counter>: Cannot set read-only property 'increment'");
	}
}

customElements.define("my-counter", create_custom_element(App, {}, [], ["increment","increment"], true));

to non-dev mode:

class App extends SvelteComponent {
	constructor(options) {
		super();
		init(this, options, instance, create_fragment, safe_not_equal, { increment: 0 });
	}

	get increment() {
		return this.$$.ctx[0];
	}
}

customElements.define("my-counter", create_custom_element(App, {}, [], ["increment"], true));

@dummdidumm
Copy link
Member

Ah I see, thanks for the clarification!

@dummdidumm dummdidumm added the bug label Jul 14, 2023
dummdidumm added a commit that referenced this issue Jul 18, 2023
In dev mode, Svelte creates a setter to throw an error noting that you can't set that readonly prop, which resulted in the accessor getting applied twice to the custom element wrapper, causing an error
fixes #8971
dummdidumm added a commit that referenced this issue Jul 19, 2023
In dev mode, Svelte creates a setter to throw an error noting that you can't set that readonly prop, which resulted in the accessor getting applied twice to the custom element wrapper, causing an error
fixes #8971
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants