Skip to content

Commit 67bcc05

Browse files
authored
Merge pull request sveltejs#3808 from tanhauhau/tanhauhau/mustache-tag-can-use-inner-html
feat: allow innerHtml if no dynamic dependencies
2 parents 7c44509 + 464868b commit 67bcc05

File tree

10 files changed

+162
-50
lines changed

10 files changed

+162
-50
lines changed

src/compiler/compile/render_dom/wrappers/Element/index.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { is_void, sanitize } from '../../../../utils/names';
66
import FragmentWrapper from '../Fragment';
77
import { escape_html, string_literal } from '../../../utils/stringify';
88
import TextWrapper from '../Text';
9+
import TagWrapper from '../shared/Tag';
910
import fix_attribute_casing from './fix_attribute_casing';
1011
import { b, x, p } from 'code-red';
1112
import { namespaces } from '../../../../utils/namespaces';
@@ -849,7 +850,7 @@ export default class ElementWrapper extends Wrapper {
849850
}
850851
}
851852

852-
function to_html(wrappers: Array<ElementWrapper | TextWrapper>, block: Block, literal: any, state: any) {
853+
function to_html(wrappers: Array<ElementWrapper | TextWrapper | TagWrapper>, block: Block, literal: any, state: any) {
853854
wrappers.forEach(wrapper => {
854855
if (wrapper.node.type === 'Text') {
855856
if ((wrapper as TextWrapper).use_space()) state.quasi.value.raw += ' ';
@@ -867,6 +868,15 @@ function to_html(wrappers: Array<ElementWrapper | TextWrapper>, block: Block, li
867868
.replace(/\$/g, '\\$');
868869
}
869870

871+
else if (wrapper.node.type === 'MustacheTag' || wrapper.node.type === 'RawMustacheTag' ) {
872+
literal.quasis.push(state.quasi);
873+
literal.expressions.push(wrapper.node.expression.manipulate(block));
874+
state.quasi = {
875+
type: 'TemplateElement',
876+
value: { raw: '' }
877+
};
878+
}
879+
870880
else if (wrapper.node.name === 'noscript') {
871881
// do nothing
872882
}

src/compiler/compile/render_dom/wrappers/MustacheTag.ts

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ export default class MustacheTagWrapper extends Tag {
1212

1313
constructor(renderer: Renderer, block: Block, parent: Wrapper, node: MustacheTag | RawMustacheTag) {
1414
super(renderer, block, parent, node);
15-
this.cannot_use_innerhtml();
1615
}
1716

1817
render(block: Block, parent_node: Identifier, parent_nodes: Identifier) {

src/compiler/compile/render_dom/wrappers/shared/Tag.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,17 @@ export default class Tag extends Wrapper {
1111

1212
constructor(renderer: Renderer, block: Block, parent: Wrapper, node: MustacheTag | RawMustacheTag) {
1313
super(renderer, block, parent, node);
14-
this.cannot_use_innerhtml();
14+
if (!this.is_dependencies_static()) {
15+
this.cannot_use_innerhtml();
16+
}
1517

1618
block.add_dependencies(node.expression.dependencies);
1719
}
1820

21+
is_dependencies_static() {
22+
return this.node.expression.contextual_dependencies.size === 0 && this.node.expression.dynamic_dependencies().length === 0;
23+
}
24+
1925
rename_this_method(
2026
block: Block,
2127
update: ((value: Node) => (Node | Node[]))

test/js/samples/hoisted-const/expected.js

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,23 @@
11
import {
22
SvelteComponent,
3-
append,
43
detach,
54
element,
65
init,
76
insert,
87
noop,
9-
safe_not_equal,
10-
text
8+
safe_not_equal
119
} from "svelte/internal";
1210

1311
function create_fragment(ctx) {
1412
let b;
15-
let t_value = get_answer() + "";
16-
let t;
1713

1814
return {
1915
c() {
2016
b = element("b");
21-
t = text(t_value);
17+
b.innerHTML = `${get_answer()}`;
2218
},
2319
m(target, anchor) {
2420
insert(target, b, anchor);
25-
append(b, t);
2621
},
2722
p: noop,
2823
i: noop,

test/js/samples/hoisted-let/expected.js

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,23 @@
11
import {
22
SvelteComponent,
3-
append,
43
detach,
54
element,
65
init,
76
insert,
87
noop,
9-
safe_not_equal,
10-
text
8+
safe_not_equal
119
} from "svelte/internal";
1210

1311
function create_fragment(ctx) {
1412
let b;
15-
let t_value = get_answer() + "";
16-
let t;
1713

1814
return {
1915
c() {
2016
b = element("b");
21-
t = text(t_value);
17+
b.innerHTML = `${get_answer()}`;
2218
},
2319
m(target, anchor) {
2420
insert(target, b, anchor);
25-
append(b, t);
2621
},
2722
p: noop,
2823
i: noop,

test/js/samples/non-mutable-reference/expected.js

+2-12
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,23 @@
11
import {
22
SvelteComponent,
3-
append,
43
detach,
54
element,
65
init,
76
insert,
87
noop,
9-
safe_not_equal,
10-
text
8+
safe_not_equal
119
} from "svelte/internal";
1210

1311
function create_fragment(ctx) {
1412
let h1;
15-
let t0;
16-
let t1;
17-
let t2;
1813

1914
return {
2015
c() {
2116
h1 = element("h1");
22-
t0 = text("Hello ");
23-
t1 = text(name);
24-
t2 = text("!");
17+
h1.innerHTML = `Hello ${name}!`;
2518
},
2619
m(target, anchor) {
2720
insert(target, h1, anchor);
28-
append(h1, t0);
29-
append(h1, t1);
30-
append(h1, t2);
3121
},
3222
p: noop,
3323
i: noop,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import {
2+
SvelteComponent,
3+
append,
4+
detach,
5+
element,
6+
init,
7+
insert,
8+
noop,
9+
safe_not_equal,
10+
set_data,
11+
space,
12+
text
13+
} from "svelte/internal";
14+
15+
function create_fragment(ctx) {
16+
let div0;
17+
let t7;
18+
let div1;
19+
let p3;
20+
let t8;
21+
let t9;
22+
23+
return {
24+
c() {
25+
div0 = element("div");
26+
27+
div0.innerHTML = `<p>Hello world</p>
28+
<p>Hello ${world1}</p>
29+
<p>Hello ${world2}</p>`;
30+
31+
t7 = space();
32+
div1 = element("div");
33+
p3 = element("p");
34+
t8 = text("Hello ");
35+
t9 = text(ctx.world3);
36+
},
37+
m(target, anchor) {
38+
insert(target, div0, anchor);
39+
insert(target, t7, anchor);
40+
insert(target, div1, anchor);
41+
append(div1, p3);
42+
append(p3, t8);
43+
append(p3, t9);
44+
},
45+
p(changed, ctx) {
46+
if (changed.world3) set_data(t9, ctx.world3);
47+
},
48+
i: noop,
49+
o: noop,
50+
d(detaching) {
51+
if (detaching) detach(div0);
52+
if (detaching) detach(t7);
53+
if (detaching) detach(div1);
54+
}
55+
};
56+
}
57+
58+
let world1 = "world";
59+
let world2 = "world";
60+
61+
function instance($$self, $$props, $$invalidate) {
62+
const world3 = "world";
63+
64+
function foo() {
65+
$$invalidate("world3", world3 = "svelte");
66+
}
67+
68+
return { world3 };
69+
}
70+
71+
class Component extends SvelteComponent {
72+
constructor(options) {
73+
super();
74+
init(this, options, instance, create_fragment, safe_not_equal, []);
75+
}
76+
}
77+
78+
export default Component;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<script>
2+
let world1 = 'world';
3+
let world2 = 'world';
4+
const world3 = 'world';
5+
function foo() {
6+
world3 = 'svelte';
7+
}
8+
9+
</script>
10+
<div>
11+
<p>Hello world</p>
12+
<p>Hello {world1}</p>
13+
<p>Hello {world2}</p>
14+
</div>
15+
<div>
16+
<p>Hello {world3}</p>
17+
</div>

test/runtime/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ describe("runtime", () => {
166166
mod,
167167
target,
168168
window,
169-
raf
169+
raf,
170+
compileOptions
170171
})).then(() => {
171172
component.$destroy();
172173

test/runtime/samples/lifecycle-render-order-for-children/_config.js

+41-20
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,47 @@ import order from './order.js';
33
export default {
44
skip_if_ssr: true,
55

6-
test({ assert, component, target }) {
7-
assert.deepEqual(order, [
8-
'0: beforeUpdate',
9-
'0: render',
10-
'1: beforeUpdate',
11-
'1: render',
12-
'2: beforeUpdate',
13-
'2: render',
14-
'3: beforeUpdate',
15-
'3: render',
16-
'1: onMount',
17-
'1: afterUpdate',
18-
'2: onMount',
19-
'2: afterUpdate',
20-
'3: onMount',
21-
'3: afterUpdate',
22-
'0: onMount',
23-
'0: afterUpdate'
24-
]);
6+
test({ assert, component, target, compileOptions }) {
7+
if (compileOptions.hydratable) {
8+
assert.deepEqual(order, [
9+
'0: beforeUpdate',
10+
'0: render',
11+
'1: beforeUpdate',
12+
'1: render',
13+
'2: beforeUpdate',
14+
'2: render',
15+
'3: beforeUpdate',
16+
'3: render',
17+
'1: onMount',
18+
'1: afterUpdate',
19+
'2: onMount',
20+
'2: afterUpdate',
21+
'3: onMount',
22+
'3: afterUpdate',
23+
'0: onMount',
24+
'0: afterUpdate',
25+
]);
26+
} else {
27+
assert.deepEqual(order, [
28+
'0: beforeUpdate',
29+
'0: render',
30+
'1: beforeUpdate',
31+
'2: beforeUpdate',
32+
'3: beforeUpdate',
33+
'1: render',
34+
'2: render',
35+
'3: render',
36+
'1: onMount',
37+
'1: afterUpdate',
38+
'2: onMount',
39+
'2: afterUpdate',
40+
'3: onMount',
41+
'3: afterUpdate',
42+
'0: onMount',
43+
'0: afterUpdate',
44+
]);
45+
}
2546

2647
order.length = 0;
27-
}
48+
},
2849
};

0 commit comments

Comments
 (0)