Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/mighty-rabbits-teach.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: warn when using rest or identifier in custom elements without props option
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,12 @@ In some situations a selector may target an element that is not 'visible' to the
</style>
```

### custom_element_props_identifier

```
Using an identifier or a rest element as the declarator for `$props` when compiling to custom elements without declaring `props` in the component options means that Svelte can't know which props to expose as properties on the DOM element. Consider explicitly destructure all the props or add the `customElement.props` option.
```

### element_implicitly_closed

```
Expand Down
4 changes: 4 additions & 0 deletions packages/svelte/messages/compile-warnings/script.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## custom_element_props_identifier

> Using an identifier or a rest element as the declarator for `$props` when compiling to custom elements without declaring `props` in the component options means that Svelte can't know which props to expose as properties on the DOM element. Consider explicitly destructure all the props or add the `customElement.props` option.
## export_let_unused

> Component has unused export property '%name%'. If it is for external reference only, please consider using `export const %name%`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { get_rune } from '../../scope.js';
import { ensure_no_module_import_conflict, validate_identifier_name } from './shared/utils.js';
import * as e from '../../../errors.js';
import * as w from '../../../warnings.js';
import { extract_paths } from '../../../utils/ast.js';
import { equal } from '../../../utils/assert.js';

Expand Down Expand Up @@ -52,6 +53,19 @@ export function VariableDeclarator(node, context) {
e.props_invalid_identifier(node);
}

if (
context.state.analysis.custom_element &&
context.state.options.customElementOptions?.props == null
) {
let warn_on;
if (
node.id.type === 'Identifier' ||
(warn_on = node.id.properties.find((p) => p.type === 'RestElement')) != null
) {
w.custom_element_props_identifier(warn_on ?? node.id);
}
}

context.state.analysis.needs_props = true;

if (node.id.type === 'Identifier') {
Expand Down
9 changes: 9 additions & 0 deletions packages/svelte/src/compiler/warnings.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export const codes = [
'options_removed_hydratable',
'options_removed_loop_guard_timeout',
'options_renamed_ssr_dom',
'custom_element_props_identifier',
'export_let_unused',
'legacy_component_creation',
'non_reactive_update',
Expand Down Expand Up @@ -592,6 +593,14 @@ export function options_renamed_ssr_dom(node) {
w(node, 'options_renamed_ssr_dom', `\`generate: "dom"\` and \`generate: "ssr"\` options have been renamed to "client" and "server" respectively\nhttps://svelte.dev/e/options_renamed_ssr_dom`);
}

/**
* Using an identifier or a rest element as the declarator for `$props` when compiling to custom elements without declaring `props` in the component options means that Svelte can't know which props to expose as properties on the DOM element. Consider explicitly destructure all the props or add the `customElement.props` option.
* @param {null | NodeLike} node
*/
export function custom_element_props_identifier(node) {
w(node, 'custom_element_props_identifier', `Using an identifier or a rest element as the declarator for \`$props\` when compiling to custom elements without declaring \`props\` in the component options means that Svelte can't know which props to expose as properties on the DOM element. Consider explicitly destructure all the props or add the \`customElement.props\` option.\nhttps://svelte.dev/e/custom_element_props_identifier`);
}

/**
* Component has unused export property '%name%'. If it is for external reference only, please consider using `export const %name%`
* @param {null | NodeLike} node
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<svelte:options customElement={{
props: {}
}} />

<script>
let props = $props();
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
{
"code": "options_missing_custom_element",
"end": {
"column": 2,
"line": 3
},
"message": "The `customElement` option is used when generating a custom element. Did you forget the `customElement: true` compile option?",
"start": {
"column": 16,
"line": 1
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<svelte:options customElement={{}} />

<script>
let { ...props } = $props();
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[
{
"code": "options_missing_custom_element",
"end": {
"column": 34,
"line": 1
},
"message": "The `customElement` option is used when generating a custom element. Did you forget the `customElement: true` compile option?",
"start": {
"column": 16,
"line": 1
}
},
{
"code": "custom_element_props_identifier",
"end": {
"column": 15,
"line": 4
},
"message": "Using an identifier or a rest element as the declarator for `$props` when compiling to custom elements without declaring `props` in the component options means that Svelte can't know which props to expose as properties on the DOM element. Consider explicitly destructure all the props or add the `customElement.props` option.",
"start": {
"column": 7,
"line": 4
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<svelte:options customElement={{}} />

<script>
let props = $props();
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[
{
"code": "options_missing_custom_element",
"end": {
"column": 34,
"line": 1
},
"message": "The `customElement` option is used when generating a custom element. Did you forget the `customElement: true` compile option?",
"start": {
"column": 16,
"line": 1
}
},
{
"code": "custom_element_props_identifier",
"end": {
"column": 10,
"line": 4
},
"message": "Using an identifier or a rest element as the declarator for `$props` when compiling to custom elements without declaring `props` in the component options means that Svelte can't know which props to expose as properties on the DOM element. Consider explicitly destructure all the props or add the `customElement.props` option.",
"start": {
"column": 5,
"line": 4
}
}
]