Skip to content

Commit

Permalink
chore: custom elements validation
Browse files Browse the repository at this point in the history
- add "missing customElement option" warning
- add backwards compat support for customElement={null}
  • Loading branch information
dummdidumm committed Mar 7, 2024
1 parent 6a01f48 commit 23ccb37
Show file tree
Hide file tree
Showing 14 changed files with 40 additions and 36 deletions.
5 changes: 5 additions & 0 deletions .changeset/kind-spoons-return.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"svelte": patch
---

chore: custom elements validation
10 changes: 7 additions & 3 deletions packages/svelte/src/compiler/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@ export function compile(source, options) {
const validated = validate_component_options(options, '');
let parsed = _parse(source);

const combined_options = /** @type {import('#compiler').ValidatedCompileOptions} */ ({
const { customElement: customElementOptions, ...parsed_options } = parsed.options || {};

/** @type {import('#compiler').ValidatedCompileOptions} */
const combined_options = {
...validated,
...parsed.options
});
...parsed_options,
customElementOptions
};

if (parsed.metadata.ts) {
parsed = {
Expand Down
5 changes: 5 additions & 0 deletions packages/svelte/src/compiler/phases/1-parse/read/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ export default function read_options(node) {
component_options.customElement = ce;
break;
} else if (value[0].expression.type !== 'ObjectExpression') {
// Before Svelte 4 it was necessary to explicitly set customElement to null or else you'd get a warning.
// This is no longer necessary, but for backwards compat just skip in this case now.
if (value[0].expression.type === 'Literal' && value[0].expression.value === null) {
break;
}
error(attribute, 'invalid-svelte-option-customElement');
}

Expand Down
8 changes: 6 additions & 2 deletions packages/svelte/src/compiler/phases/2-analyze/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,8 @@ export function analyze_component(root, options) {
uses_rest_props: false,
uses_slots: false,
uses_component_bindings: false,
custom_element: options.customElement,
inject_styles: options.css === 'injected' || !!options.customElement,
custom_element: options.customElementOptions ?? options.customElement,
inject_styles: options.css === 'injected' || options.customElement,
accessors: options.customElement
? true
: !!options.accessors ||
Expand All @@ -399,6 +399,10 @@ export function analyze_component(root, options) {
}
};

if (!options.customElement && root.options?.customElement) {
warn(analysis.warnings, root.options, [], 'missing-custom-element-compile-option');
}

if (analysis.runes) {
const props_refs = module.scope.references.get('$$props');
if (props_refs) {
Expand Down
3 changes: 2 additions & 1 deletion packages/svelte/src/compiler/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type { SourceMap } from 'magic-string';
import type { Context } from 'zimmerframe';
import type { Scope } from '../phases/scope.js';
import * as Css from './css.js';
import type { EachBlock, Namespace, SvelteNode } from './template.js';
import type { EachBlock, Namespace, SvelteNode, SvelteOptions } from './template.js';

/** The return value of `compile` from `svelte/compiler` */
export interface CompileResult {
Expand Down Expand Up @@ -224,6 +224,7 @@ export type ValidatedCompileOptions = ValidatedModuleCompileOptions &
sourcemap: CompileOptions['sourcemap'];
legacy: Required<Required<CompileOptions>['legacy']>;
runes: CompileOptions['runes'];
customElementOptions: SvelteOptions['customElement'];
};

export type DeclarationKind =
Expand Down
2 changes: 1 addition & 1 deletion packages/svelte/src/compiler/types/template.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export interface Root extends BaseNode {
}

export interface SvelteOptions {
// start/end info (needed for Prettier, when someone wants to keep the options where they are)
// start/end info (needed for warnings and for our Prettier plugin)
start: number;
end: number;
// options
Expand Down
8 changes: 7 additions & 1 deletion packages/svelte/src/compiler/warnings.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,11 @@ const block = {
'empty-block': () => 'Empty block'
};

const options = {
'missing-custom-element-compile-option': () =>
"The 'customElement' option is used when generating a custom element. Did you forget the 'customElement: true' compile option?"
};

/** @satisfies {Warnings} */
const warnings = {
...css,
Expand All @@ -247,7 +252,8 @@ const warnings = {
...state,
...components,
...legacy,
...block
...block,
...options
};

/** @typedef {typeof warnings} AllWarnings */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { test } from '../../assert';
import { mount } from 'svelte';
const tick = () => Promise.resolve();

export default test({
skip: true, // TODO: decide if we want to keep the customElement={null} behavior (warning about not having set the tag when in ce mode, and disabling that this way)

async test({ assert, target, component: Component }) {
const component = new Component({ target, props: { name: 'slot' } });
async test({ assert, target, componentCtor: Component }) {
const component = mount(Component, { target, props: { name: 'slot' } });
await tick();
await tick();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<!-- before Svelte 4 it was necessary to explicitly set customElement to null or else you'd get a warning. Keep this around for backwards compat -->
<svelte:options customElement={null} />

<script>
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
[
{
"code": "missing-custom-element-compile-options",
"code": "missing-custom-element-compile-option",
"message": "The 'customElement' option is used when generating a custom element. Did you forget the 'customElement: true' compile option?",
"start": {
"line": 1,
"column": 16
"column": 0
},
"end": {
"line": 1,
"column": 46
"column": 49
}
}
]

0 comments on commit 23ccb37

Please sign in to comment.