diff --git a/packages/svelte/src/compiler/index.js b/packages/svelte/src/compiler/index.js
index 1d822514b9..f1a15f2ebf 100644
--- a/packages/svelte/src/compiler/index.js
+++ b/packages/svelte/src/compiler/index.js
@@ -28,7 +28,11 @@ export function compile(source, options) {
let parsed = _parse(source);
- const { customElement: customElementOptions, ...parsed_options } = parsed.options || {};
+ const {
+ customElement: customElementOptions,
+ customRenderer,
+ ...parsed_options
+ } = parsed.options || {};
/** @type {ValidatedCompileOptions} */
const combined_options = {
@@ -36,7 +40,11 @@ export function compile(source, options) {
...parsed_options,
customElementOptions,
css: 'css' in parsed_options ? () => parsed_options.css ?? 'external' : validated.css,
- runes: 'runes' in parsed_options ? () => parsed_options.runes : validated.runes
+ runes: 'runes' in parsed_options ? () => parsed_options.runes : validated.runes,
+ experimental: {
+ ...validated.experimental,
+ ...(customRenderer !== undefined ? { customRenderer } : {})
+ }
};
if (parsed.metadata.ts) {
diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/Attribute.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/Attribute.js
index 838cbf0413..320760235f 100644
--- a/packages/svelte/src/compiler/phases/2-analyze/visitors/Attribute.js
+++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/Attribute.js
@@ -60,7 +60,7 @@ export function Attribute(node, context) {
}
// we can't delegate event handlers in a non dom environment
- if (!context.state.options.customRenderer) {
+ if (!context.state.options.experimental.customRenderer) {
node.metadata.delegated =
parent?.type === 'RegularElement' && can_delegate_event(node.name.slice(2));
}
diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js
index 448013cbb6..e447507fbe 100644
--- a/packages/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js
+++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js
@@ -112,7 +112,7 @@ export function RegularElement(node, context) {
// We mark the subtree as dynamic so parent elements properly include the child init code
if (
(is_customizable_select_element(node) || node.name === 'selectedcontent') &&
- !context.state.options.customRenderer
+ !context.state.options.experimental.customRenderer
) {
// Mark the element's own fragment as dynamic so it's not treated as static
node.fragment.metadata.dynamic = true;
diff --git a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js
index 162b979e4c..fb467403be 100644
--- a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js
+++ b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js
@@ -139,13 +139,11 @@ const visitors = {
};
/**
- * @param {string} custom_renderer_module
+ * @param {string | undefined} custom_renderer_module
*/
function custom_renderer_imports(custom_renderer_module) {
- const imports = [
- b.import_all('$', 'svelte/internal/client'),
- ]
- if(custom_renderer_module){
+ const imports = [b.import_all('$', 'svelte/internal/client')];
+ if (custom_renderer_module) {
imports.push(b.imports([['$renderer', '$renderer', true]], custom_renderer_module));
}
return imports;
@@ -165,7 +163,8 @@ export function client_component(analysis, options) {
scopes: analysis.module.scopes,
is_instance: false,
hoisted: [
- ...custom_renderer_imports(options.customRenderer), ...analysis.instance_body.hoisted
+ ...custom_renderer_imports(options.experimental.customRenderer),
+ ...analysis.instance_body.hoisted
],
node: /** @type {any} */ (null), // populated by the root node
legacy_reactive_imports: [],
@@ -407,7 +406,7 @@ export function client_component(analysis, options) {
);
}
- if (options.customRenderer) {
+ if (options.experimental.customRenderer) {
component_block.body.unshift(
b.var('$$pop_renderer', b.call('$.push_renderer', b.id('$renderer')))
);
@@ -586,7 +585,7 @@ export function client_component(analysis, options) {
// disclose version attach the svelte version to `window` which is not guaranteed
// to be a thing in custom renderers environments
- if (options.discloseVersion && !options.customRenderer) {
+ if (options.discloseVersion && !options.experimental.customRenderer) {
body.unshift(b.imports([], 'svelte/internal/disclose-version'));
}
diff --git a/packages/svelte/src/compiler/phases/3-transform/client/transform-template/index.js b/packages/svelte/src/compiler/phases/3-transform/client/transform-template/index.js
index e34bfc0123..cae9c94f4d 100644
--- a/packages/svelte/src/compiler/phases/3-transform/client/transform-template/index.js
+++ b/packages/svelte/src/compiler/phases/3-transform/client/transform-template/index.js
@@ -36,7 +36,7 @@ function build_locations(nodes) {
*/
export function transform_template(state, namespace, flags = 0) {
// custom renderers needs a tree to work because there's no template element we can use
- const tree = state.options.fragments === 'tree' || !!state.options.customRenderer;
+ const tree = state.options.fragments === 'tree' || !!state.options.experimental.customRenderer;
const expression = tree ? state.template.as_tree() : state.template.as_html();
diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js
index a649d87726..76152b28ed 100644
--- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js
+++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js
@@ -41,7 +41,7 @@ export function RegularElement(node, context) {
const is_html =
context.state.metadata.namespace === 'html' &&
node.name !== 'svg' &&
- !context.state.options.customRenderer;
+ !context.state.options.experimental.customRenderer;
const name = is_html ? node.name.toLowerCase() : node.name;
context.state.template.push_element(name, node.start, is_html);
@@ -51,7 +51,8 @@ export function RegularElement(node, context) {
}
// we never treat elements as custom element in custom renderers, since we don't want to apply special handling to them (e.g. class merging)
- const is_custom_element = is_custom_element_node(node) && !context.state.options.customRenderer;
+ const is_custom_element =
+ is_custom_element_node(node) && !context.state.options.experimental.customRenderer;
// cloneNode is faster, but it does not instantiate the underlying class of the
// custom element until the template is connected to the dom, which would
@@ -257,7 +258,7 @@ export function RegularElement(node, context) {
if (name !== 'class' || value) {
context.state.template.set_prop(attribute.name, value === true ? '' : value);
}
- } else if (name === 'autofocus' && !context.state.options.customRenderer) {
+ } else if (name === 'autofocus' && !context.state.options.experimental.customRenderer) {
let { value } = build_attribute_value(attribute.value, context);
context.state.init.push(b.stmt(b.call('$.autofocus', node_id, value)));
} else if (name === 'class') {
@@ -279,7 +280,7 @@ export function RegularElement(node, context) {
name,
value,
attributes,
- !!context.state.options.customRenderer
+ !!context.state.options.experimental.customRenderer
);
(has_state ? context.state.update : context.state.init).push(b.stmt(update));
@@ -356,7 +357,7 @@ export function RegularElement(node, context) {
const empty_string = value.type === 'Literal' && value.value === '';
if (!empty_string) {
- if (context.state.options.customRenderer) {
+ if (context.state.options.experimental.customRenderer) {
// custom renderers need to use the method to invoke the renderer
context.state.template.push_text([
{
@@ -376,7 +377,10 @@ export function RegularElement(node, context) {
);
}
}
- } else if (is_customizable_select_element(node) && !context.state.options.customRenderer) {
+ } else if (
+ is_customizable_select_element(node) &&
+ !context.state.options.experimental.customRenderer
+ ) {
// For