Skip to content

Commit 6448e07

Browse files
authored
breaking: remove foreign namespace (#12869)
* breaking: remove foreign namespace * regenerate
1 parent c8f963a commit 6448e07

File tree

27 files changed

+52
-222
lines changed

27 files changed

+52
-222
lines changed

.changeset/gorgeous-coats-jog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
breaking: remove foreign namespace

packages/svelte/src/compiler/phases/1-parse/read/options.js

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -157,18 +157,10 @@ export default function read_options(node) {
157157
component_options.namespace = 'svg';
158158
} else if (value === NAMESPACE_MATHML) {
159159
component_options.namespace = 'mathml';
160-
} else if (
161-
value === 'html' ||
162-
value === 'mathml' ||
163-
value === 'svg' ||
164-
value === 'foreign'
165-
) {
160+
} else if (value === 'html' || value === 'mathml' || value === 'svg') {
166161
component_options.namespace = value;
167162
} else {
168-
e.svelte_options_invalid_attribute_value(
169-
attribute,
170-
`"html", "mathml", "svg" or "foreign"`
171-
);
163+
e.svelte_options_invalid_attribute_value(attribute, `"html", "mathml" or "svg"`);
172164
}
173165

174166
break;

packages/svelte/src/compiler/phases/2-analyze/visitors/BindDirective.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,6 @@ export function BindDirective(node, context) {
126126
parent?.type === 'SvelteDocument' ||
127127
parent?.type === 'SvelteBody'
128128
) {
129-
if (context.state.options.namespace === 'foreign' && node.name !== 'this') {
130-
e.bind_invalid_name(node, node.name, 'Foreign elements only support `bind:this`');
131-
}
132-
133129
if (node.name in binding_properties) {
134130
const property = binding_properties[node.name];
135131
if (property.valid_elements && !property.valid_elements.includes(parent.name)) {

packages/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,7 @@ export function RegularElement(node, context) {
2424
context.state.analysis.elements.push(node);
2525

2626
// Special case: Move the children of <textarea> into a value attribute if they are dynamic
27-
if (
28-
context.state.options.namespace !== 'foreign' &&
29-
node.name === 'textarea' &&
30-
node.fragment.nodes.length > 0
31-
) {
27+
if (node.name === 'textarea' && node.fragment.nodes.length > 0) {
3228
for (const attribute of node.attributes) {
3329
if (attribute.type === 'Attribute' && attribute.name === 'value') {
3430
e.textarea_invalid_content(node);
@@ -65,7 +61,6 @@ export function RegularElement(node, context) {
6561
// Special case: single expression tag child of option element -> add "fake" attribute
6662
// to ensure that value types are the same (else for example numbers would be strings)
6763
if (
68-
context.state.options.namespace !== 'foreign' &&
6964
node.name === 'option' &&
7065
node.fragment.nodes?.length === 1 &&
7166
node.fragment.nodes[0].type === 'ExpressionTag' &&
@@ -90,10 +85,8 @@ export function RegularElement(node, context) {
9085
(attribute) => attribute.type === 'SpreadAttribute'
9186
);
9287

93-
if (context.state.options.namespace !== 'foreign') {
94-
node.metadata.svg = is_svg(node.name);
95-
node.metadata.mathml = is_mathml(node.name);
96-
}
88+
node.metadata.svg = is_svg(node.name);
89+
node.metadata.mathml = is_mathml(node.name);
9790

9891
if (context.state.parent_element) {
9992
let past_parent = false;
@@ -156,7 +149,6 @@ export function RegularElement(node, context) {
156149

157150
if (
158151
context.state.analysis.source[node.end - 2] === '/' &&
159-
context.state.options.namespace !== 'foreign' &&
160152
!is_void(node_name) &&
161153
!is_svg(node_name)
162154
) {

packages/svelte/src/compiler/phases/2-analyze/visitors/shared/a11y.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -687,9 +687,6 @@ function get_static_text_value(attribute) {
687687
* @param {AnalysisState} state
688688
*/
689689
export function check_element(node, state) {
690-
// foreign namespace means elements can have completely different meanings, therefore we don't check them
691-
if (state.options.namespace === 'foreign') return;
692-
693690
/** @type {Map<string, Attribute>} */
694691
const attribute_map = new Map();
695692

packages/svelte/src/compiler/phases/2-analyze/visitors/shared/element.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export function validate_element(node, context) {
7979
validate_slot_attribute(context, attribute);
8080
}
8181

82-
if (attribute.name === 'is' && context.state.options.namespace !== 'foreign') {
82+
if (attribute.name === 'is') {
8383
w.attribute_avoid_is(attribute);
8484
}
8585

packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js

Lines changed: 5 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -178,14 +178,6 @@ export function RegularElement(node, context) {
178178
}
179179
}
180180

181-
if (child_metadata.namespace === 'foreign') {
182-
// input/select etc could mean something completely different in foreign namespace, so don't special-case them
183-
needs_content_reset = false;
184-
needs_input_reset = false;
185-
needs_special_value_handling = false;
186-
value_binding = null;
187-
}
188-
189181
if (is_content_editable && has_content_editable_binding) {
190182
child_metadata.bound_contenteditable = true;
191183
}
@@ -219,7 +211,7 @@ export function RegularElement(node, context) {
219211
node,
220212
node_id,
221213
// If value binding exists, that one takes care of calling $.init_select
222-
value_binding === null && node.name === 'select' && child_metadata.namespace !== 'foreign'
214+
value_binding === null && node.name === 'select'
223215
);
224216
is_attributes_reactive = true;
225217
} else {
@@ -249,8 +241,6 @@ export function RegularElement(node, context) {
249241
const value = is_text_attribute(attribute) ? attribute.value[0].data : true;
250242

251243
if (name !== 'class' || value) {
252-
// TODO namespace=foreign probably doesn't want to do template stuff at all and instead use programmatic methods
253-
// to create the elements it needs.
254244
context.state.template.push(
255245
` ${attribute.name}${
256246
is_boolean_attribute(name) && value === true
@@ -262,10 +252,9 @@ export function RegularElement(node, context) {
262252
}
263253
}
264254

265-
const is =
266-
is_custom_element && child_metadata.namespace !== 'foreign'
267-
? build_custom_element_attribute_update_assignment(node_id, attribute, context)
268-
: build_element_attribute_update_assignment(node, node_id, attribute, context);
255+
const is = is_custom_element
256+
? build_custom_element_attribute_update_assignment(node_id, attribute, context)
257+
: build_element_attribute_update_assignment(node, node_id, attribute, context);
269258
if (is) is_attributes_reactive = true;
270259
}
271260
}
@@ -301,8 +290,7 @@ export function RegularElement(node, context) {
301290
locations: child_locations,
302291
scope: /** @type {Scope} */ (context.state.scopes.get(node.fragment)),
303292
preserve_whitespace:
304-
context.state.preserve_whitespace ||
305-
((node.name === 'pre' || node.name === 'textarea') && child_metadata.namespace !== 'foreign')
293+
context.state.preserve_whitespace || node.name === 'pre' || node.name === 'textarea'
306294
};
307295

308296
const { hoisted, trimmed } = clean_nodes(
@@ -587,28 +575,6 @@ function build_element_attribute_update_assignment(element, node_id, attribute,
587575
const is_mathml = context.state.metadata.namespace === 'mathml';
588576
let { has_call, value } = build_attribute_value(attribute.value, context);
589577

590-
// The foreign namespace doesn't have any special handling, everything goes through the attr function
591-
if (context.state.metadata.namespace === 'foreign') {
592-
const statement = b.stmt(
593-
b.call(
594-
'$.set_attribute',
595-
node_id,
596-
b.literal(name),
597-
value,
598-
is_ignored(element, 'hydration_attribute_changed') && b.true
599-
)
600-
);
601-
602-
if (attribute.metadata.expression.has_state) {
603-
const id = state.scope.generate(`${node_id.name}_${name}`);
604-
build_update_assignment(state, id, undefined, value, statement);
605-
return true;
606-
} else {
607-
state.init.push(statement);
608-
return false;
609-
}
610-
}
611-
612578
if (name === 'autofocus') {
613579
state.init.push(b.stmt(b.call('$.autofocus', node_id, value)));
614580
return false;

packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteElement.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export function SvelteElement(node, context) {
9494

9595
const get_tag = b.thunk(/** @type {Expression} */ (context.visit(node.tag)));
9696

97-
if (dev && context.state.metadata.namespace !== 'foreign') {
97+
if (dev) {
9898
if (node.fragment.nodes.length > 0) {
9999
context.state.init.push(b.stmt(b.call('$.validate_void_dynamic_element', get_tag)));
100100
}

packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/element.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,7 @@ export function build_attribute_value(value, context) {
116116
* @param {{ state: { metadata: { namespace: Namespace }}}} context
117117
*/
118118
export function get_attribute_name(element, attribute, context) {
119-
if (
120-
!element.metadata.svg &&
121-
!element.metadata.mathml &&
122-
context.state.metadata.namespace !== 'foreign'
123-
) {
119+
if (!element.metadata.svg && !element.metadata.mathml) {
124120
return normalize_attribute(attribute.name);
125121
}
126122

packages/svelte/src/compiler/phases/3-transform/server/visitors/RegularElement.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ export function RegularElement(node, context) {
2121
...context.state,
2222
namespace,
2323
preserve_whitespace:
24-
context.state.preserve_whitespace ||
25-
((node.name === 'pre' || node.name === 'textarea') && namespace !== 'foreign')
24+
context.state.preserve_whitespace || node.name === 'pre' || node.name === 'textarea'
2625
};
2726

2827
context.state.template.push(b.literal(`<${node.name}`));
@@ -95,7 +94,7 @@ export function RegularElement(node, context) {
9594
);
9695
}
9796

98-
if (!is_void(node.name) || namespace === 'foreign') {
97+
if (!is_void(node.name)) {
9998
state.template.push(b.literal(`</${node.name}>`));
10099
}
101100

packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/element.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ export function build_element_attributes(node, context) {
268268
*/
269269
function get_attribute_name(element, attribute, context) {
270270
let name = attribute.name;
271-
if (!element.metadata.svg && !element.metadata.mathml && context.state.namespace !== 'foreign') {
271+
if (!element.metadata.svg && !element.metadata.mathml) {
272272
name = name.toLowerCase();
273273
// don't lookup boolean aliases here, the server runtime function does only
274274
// check for the lowercase variants of boolean attributes

packages/svelte/src/compiler/phases/3-transform/utils.js

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -306,32 +306,30 @@ export function clean_nodes(
306306
* @param {Compiler.SvelteNode[]} nodes
307307
*/
308308
export function infer_namespace(namespace, parent, nodes) {
309-
if (namespace !== 'foreign') {
310-
if (parent.type === 'RegularElement' && parent.name === 'foreignObject') {
311-
return 'html';
312-
}
309+
if (parent.type === 'RegularElement' && parent.name === 'foreignObject') {
310+
return 'html';
311+
}
313312

314-
if (parent.type === 'RegularElement' || parent.type === 'SvelteElement') {
315-
if (parent.metadata.svg) {
316-
return 'svg';
317-
}
318-
return parent.metadata.mathml ? 'mathml' : 'html';
313+
if (parent.type === 'RegularElement' || parent.type === 'SvelteElement') {
314+
if (parent.metadata.svg) {
315+
return 'svg';
319316
}
317+
return parent.metadata.mathml ? 'mathml' : 'html';
318+
}
320319

321-
// Re-evaluate the namespace inside slot nodes that reset the namespace
322-
if (
323-
parent.type === 'Fragment' ||
324-
parent.type === 'Root' ||
325-
parent.type === 'Component' ||
326-
parent.type === 'SvelteComponent' ||
327-
parent.type === 'SvelteFragment' ||
328-
parent.type === 'SnippetBlock' ||
329-
parent.type === 'SlotElement'
330-
) {
331-
const new_namespace = check_nodes_for_namespace(nodes, 'keep');
332-
if (new_namespace !== 'keep' && new_namespace !== 'maybe_html') {
333-
return new_namespace;
334-
}
320+
// Re-evaluate the namespace inside slot nodes that reset the namespace
321+
if (
322+
parent.type === 'Fragment' ||
323+
parent.type === 'Root' ||
324+
parent.type === 'Component' ||
325+
parent.type === 'SvelteComponent' ||
326+
parent.type === 'SvelteFragment' ||
327+
parent.type === 'SnippetBlock' ||
328+
parent.type === 'SlotElement'
329+
) {
330+
const new_namespace = check_nodes_for_namespace(nodes, 'keep');
331+
if (new_namespace !== 'keep' && new_namespace !== 'maybe_html') {
332+
return new_namespace;
335333
}
336334
}
337335

@@ -401,10 +399,6 @@ function check_nodes_for_namespace(nodes, namespace) {
401399
* @returns {Compiler.Namespace}
402400
*/
403401
export function determine_namespace_for_children(node, namespace) {
404-
if (namespace === 'foreign') {
405-
return namespace;
406-
}
407-
408402
if (node.name === 'foreignObject') {
409403
return 'html';
410404
}

packages/svelte/src/compiler/types/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export interface CompileOptions extends ModuleCompileOptions {
8585
*/
8686
accessors?: boolean;
8787
/**
88-
* The namespace of the element; e.g., `"html"`, `"svg"`, `"foreign"`.
88+
* The namespace of the element; e.g., `"html"`, `"svg"`, `"mathml"`.
8989
*
9090
* @default 'html'
9191
*/

packages/svelte/src/compiler/types/template.d.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,8 @@ export interface Fragment {
4747
* - `html` — the default, for e.g. `<div>` or `<span>`
4848
* - `svg` — for e.g. `<svg>` or `<g>`
4949
* - `mathml` — for e.g. `<math>` or `<mrow>`
50-
* - `foreign` — for other compilation targets than the web, e.g. Svelte Native.
51-
* Disallows bindings other than bind:this, disables a11y checks, disables any special attribute handling
52-
* (also see https://github.com/sveltejs/svelte/pull/5652)
5350
*/
54-
export type Namespace = 'html' | 'svg' | 'mathml' | 'foreign';
51+
export type Namespace = 'html' | 'svg' | 'mathml';
5552

5653
export interface Root extends BaseNode {
5754
type: 'Root';

packages/svelte/src/compiler/validate-options.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export const validate_component_options =
9090

9191
name: string(undefined),
9292

93-
namespace: list(['html', 'svg', 'foreign']),
93+
namespace: list(['html', 'mathml', 'svg']),
9494

9595
modernAst: boolean(false),
9696

packages/svelte/tests/runtime-legacy/samples/attribute-casing-foreign-namespace-compiler-option/_config.js

Lines changed: 0 additions & 26 deletions
This file was deleted.

packages/svelte/tests/runtime-legacy/samples/attribute-casing-foreign-namespace-compiler-option/main.svelte

Lines changed: 0 additions & 4 deletions
This file was deleted.

packages/svelte/tests/runtime-legacy/samples/attribute-casing-foreign-namespace/_config.js

Lines changed: 0 additions & 20 deletions
This file was deleted.

packages/svelte/tests/runtime-legacy/samples/attribute-casing-foreign-namespace/main.svelte

Lines changed: 0 additions & 4 deletions
This file was deleted.

packages/svelte/tests/validator/samples/a11y-in-foreign-namespace/input.svelte

Lines changed: 0 additions & 7 deletions
This file was deleted.

packages/svelte/tests/validator/samples/a11y-in-foreign-namespace/warnings.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)