Skip to content

Commit

Permalink
[fix] static svelte:element not replaced with tag in production mode (#…
Browse files Browse the repository at this point in the history
…7938)

* [fix] static svelte:element not replaced with tag in production mode

* [fix] static svelte:element not replaced with tag in production mode

* add optimization of static <svelte:element> and fix a bug

Co-authored-by: Yuichiro Yamashita <xydybaseball@gmail.com>
  • Loading branch information
ramonsnir and baseballyama committed Jan 1, 2023
1 parent de6821a commit f84c00e
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 16 deletions.
1 change: 1 addition & 0 deletions src/compiler/compile/nodes/Element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ export default class Element extends Node {
this.tag_expr = new Expression(component, this, scope, info.tag);
} else {
this.tag_expr = new Expression(component, this, scope, string_literal(info.tag) as Literal);
this.name = info.tag;
}
} else {
this.tag_expr = new Expression(component, this, scope, string_literal(this.name) as Literal);
Expand Down
11 changes: 7 additions & 4 deletions src/compiler/compile/render_dom/wrappers/Element/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ export default class ElementWrapper extends Wrapper {
node.styles.length > 0 ||
this.node.name === 'option' ||
node.tag_expr.dynamic_dependencies().length ||
node.is_dynamic_element ||
renderer.options.dev
) {
this.parent.cannot_use_innerhtml(); // need to use add_location
Expand Down Expand Up @@ -1176,10 +1177,12 @@ function to_html(wrappers: Array<ElementWrapper | TextWrapper | MustacheTagWrapp
} else if (wrapper.node.name === 'noscript') {
// do nothing
} else {
const nodeName = wrapper.node.name;

// element
state.quasi.value.raw += `<${wrapper.node.name}`;
state.quasi.value.raw += `<${nodeName}`;

const is_empty_textarea = wrapper.node.name === 'textarea' && wrapper.fragment.nodes.length === 0;
const is_empty_textarea = nodeName === 'textarea' && wrapper.fragment.nodes.length === 0;

(wrapper as ElementWrapper).attributes.forEach((attr: AttributeWrapper) => {
if (is_empty_textarea && attr.node.name === 'value') {
Expand All @@ -1196,7 +1199,7 @@ function to_html(wrappers: Array<ElementWrapper | TextWrapper | MustacheTagWrapp
if (!wrapper.void) {
state.quasi.value.raw += '>';

if (wrapper.node.name === 'pre') {
if (nodeName === 'pre') {
// Two or more leading newlines are required to restore the leading newline immediately after `<pre>`.
// see https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element
const first = wrapper.fragment.nodes[0];
Expand All @@ -1221,7 +1224,7 @@ function to_html(wrappers: Array<ElementWrapper | TextWrapper | MustacheTagWrapp

to_html(wrapper.fragment.nodes as Array<ElementWrapper | TextWrapper>, block, literal, state);

state.quasi.value.raw += `</${wrapper.node.name}>`;
state.quasi.value.raw += `</${nodeName}>`;
} else {
state.quasi.value.raw += '/>';
}
Expand Down
23 changes: 14 additions & 9 deletions test/js/samples/svelte-element-svg/expected.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function create_dynamic_element_1(ctx) {
return { c: noop, m: noop, p: noop, d: noop };
}

// (1:0) <svelte:element this="svg" xmlns="http://www.w3.org/2000/svg">
// (5:0) <svelte:element this={tag.svg} xmlns="http://www.w3.org/2000/svg">
function create_dynamic_element(ctx) {
let svelte_element1;
let svelte_element0;
Expand All @@ -38,8 +38,8 @@ function create_dynamic_element(ctx) {

return {
c() {
svelte_element1 = svg_element("svg");
svelte_element0 = svg_element("path");
svelte_element1 = svg_element(/*tag*/ ctx[0].svg);
svelte_element0 = svg_element(/*tag*/ ctx[0].path);
set_svg_attributes(svelte_element0, svelte_element0_data);
set_svg_attributes(svelte_element1, svelte_element1_data);
},
Expand All @@ -60,9 +60,9 @@ function create_dynamic_element(ctx) {
}

function create_fragment(ctx) {
let previous_tag = "svg";
let previous_tag = /*tag*/ ctx[0].svg;
let svelte_element1_anchor;
let svelte_element1 = "svg" && create_dynamic_element(ctx);
let svelte_element1 = /*tag*/ ctx[0].svg && create_dynamic_element(ctx);

return {
c() {
Expand All @@ -74,12 +74,12 @@ function create_fragment(ctx) {
insert(target, svelte_element1_anchor, anchor);
},
p(ctx, [dirty]) {
if ("svg") {
if (/*tag*/ ctx[0].svg) {
if (!previous_tag) {
svelte_element1 = create_dynamic_element(ctx);
svelte_element1.c();
svelte_element1.m(svelte_element1_anchor.parentNode, svelte_element1_anchor);
} else if (safe_not_equal(previous_tag, "svg")) {
} else if (safe_not_equal(previous_tag, /*tag*/ ctx[0].svg)) {
svelte_element1.d(1);
svelte_element1 = create_dynamic_element(ctx);
svelte_element1.c();
Expand All @@ -92,7 +92,7 @@ function create_fragment(ctx) {
svelte_element1 = null;
}

previous_tag = "svg";
previous_tag = /*tag*/ ctx[0].svg;
},
i: noop,
o: noop,
Expand All @@ -103,10 +103,15 @@ function create_fragment(ctx) {
};
}

function instance($$self) {
const tag = { svg: 'svg', path: 'path' };
return [tag];
}

class Component extends SvelteComponent {
constructor(options) {
super();
init(this, options, null, create_fragment, safe_not_equal, {});
init(this, options, instance, create_fragment, safe_not_equal, {});
}
}

Expand Down
10 changes: 7 additions & 3 deletions test/js/samples/svelte-element-svg/input.svelte
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<svelte:element this="svg" xmlns="http://www.w3.org/2000/svg">
<svelte:element this="path" xmlns="http://www.w3.org/2000/svg"></svelte:element>
</svelte:element>
<script>
const tag = { svg: 'svg', path: 'path' };
</script>

<svelte:element this={tag.svg} xmlns="http://www.w3.org/2000/svg">
<svelte:element this={tag.path} xmlns="http://www.w3.org/2000/svg" />
</svelte:element>
13 changes: 13 additions & 0 deletions test/runtime/samples/static-svelte-element/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export default {
html: `
<div>
<p></p>
</div>
`,

test({ assert, target }) {
const p = target.querySelector('p');

assert.notEqual(p, undefined);
}
};
3 changes: 3 additions & 0 deletions test/runtime/samples/static-svelte-element/main.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div>
<svelte:element this="p" />
</div>
13 changes: 13 additions & 0 deletions test/runtime/samples/static-svelte-element2/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export default {
html: `
<div>
<p></p>
</div>
`,

test({ assert, target }) {
const p = target.querySelector('p');

assert.notEqual(p, undefined);
}
};
7 changes: 7 additions & 0 deletions test/runtime/samples/static-svelte-element2/main.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script>
const p = 'p';
</script>

<div>
<svelte:element this={p} />
</div>

0 comments on commit f84c00e

Please sign in to comment.