diff --git a/src/compiler/compile/nodes/EventHandler.ts b/src/compiler/compile/nodes/EventHandler.ts
index 20e662a22bea..f2c48c316999 100644
--- a/src/compiler/compile/nodes/EventHandler.ts
+++ b/src/compiler/compile/nodes/EventHandler.ts
@@ -3,6 +3,7 @@ import Expression from './shared/Expression';
import Component from '../Component';
import deindent from '../utils/deindent';
import Block from '../render_dom/Block';
+import { sanitize } from '../../utils/names';
export default class EventHandler extends Node {
type: 'EventHandler';
@@ -41,7 +42,7 @@ export default class EventHandler extends Node {
}
}
} else {
- const name = component.get_unique_name(`${this.name}_handler`);
+ const name = component.get_unique_name(`${sanitize(this.name)}_handler`);
component.add_var({
name,
diff --git a/src/compiler/compile/render_dom/wrappers/EachBlock.ts b/src/compiler/compile/render_dom/wrappers/EachBlock.ts
index 0a4051115020..ca93e61d62d8 100644
--- a/src/compiler/compile/render_dom/wrappers/EachBlock.ts
+++ b/src/compiler/compile/render_dom/wrappers/EachBlock.ts
@@ -466,14 +466,26 @@ export default class EachBlockWrapper extends Wrapper {
${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
}
`
- : deindent`
- ${iterations}[#i] = ${create_each_block}(child_ctx);
- ${iterations}[#i].c();
- ${has_transitions && `@transition_in(${this.vars.iterations}[#i], 1);`}
- ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
- `;
+ : has_transitions
+ ? deindent`
+ if (${iterations}[#i]) {
+ @transition_in(${this.vars.iterations}[#i], 1);
+ } else {
+ ${iterations}[#i] = ${create_each_block}(child_ctx);
+ ${iterations}[#i].c();
+ @transition_in(${this.vars.iterations}[#i], 1);
+ ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
+ }
+ `
+ : deindent`
+ if (!${iterations}[#i]) {
+ ${iterations}[#i] = ${create_each_block}(child_ctx);
+ ${iterations}[#i].c();
+ ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
+ }
+ `;
- const start = this.block.has_update_method ? '0' : `${view_length}`;
+ const start = this.block.has_update_method ? '0' : `#old_length`;
let remove_old_blocks;
@@ -487,12 +499,12 @@ export default class EachBlockWrapper extends Wrapper {
`);
remove_old_blocks = deindent`
@group_outros();
- for (; #i < ${view_length}; #i += 1) ${out}(#i);
+ for (#i = ${this.vars.each_block_value}.${length}; #i < ${view_length}; #i += 1) ${out}(#i);
@check_outros();
`;
} else {
remove_old_blocks = deindent`
- for (${this.block.has_update_method ? `` : `#i = ${this.vars.each_block_value}.${length}`}; #i < ${view_length}; #i += 1) {
+ for (${this.block.has_update_method ? `` : `#i = ${this.vars.each_block_value}.${length}`}; #i < ${this.block.has_update_method ? view_length : '#old_length'}; #i += 1) {
${iterations}[#i].d(1);
}
${!fixed_length && `${view_length} = ${this.vars.each_block_value}.${length};`}
@@ -500,6 +512,7 @@ export default class EachBlockWrapper extends Wrapper {
}
const update = deindent`
+ ${!this.block.has_update_method && `const #old_length = ${this.vars.each_block_value}.length;`}
${this.vars.each_block_value} = ${snippet};
for (var #i = ${start}; #i < ${this.vars.each_block_value}.${length}; #i += 1) {
diff --git a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts
index 46b3df4c31fd..6045daaf36dd 100644
--- a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts
+++ b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts
@@ -447,7 +447,7 @@ export default class InlineComponentWrapper extends Wrapper {
`);
block.builders.intro.add_block(deindent`
- @transition_in(${name}.$$.fragment, #local);
+ if (${name}) @transition_in(${name}.$$.fragment, #local);
`);
if (updates.length) {
diff --git a/src/compiler/utils/names.ts b/src/compiler/utils/names.ts
index 9805c92b917b..c5a67a651be7 100644
--- a/src/compiler/utils/names.ts
+++ b/src/compiler/utils/names.ts
@@ -14,7 +14,9 @@ export const globals = new Set([
'encodeURI',
'encodeURIComponent',
'Error',
+ 'EvalError',
'Infinity',
+ 'InternalError',
'Intl',
'isFinite',
'isNaN',
@@ -29,11 +31,16 @@ export const globals = new Set([
'process',
'Promise',
'prompt',
+ 'RangeError',
+ 'ReferenceError',
'RegExp',
'Set',
'String',
+ 'SyntaxError',
+ 'TypeError',
'undefined',
- 'window',
+ 'URIError',
+ 'window'
]);
export const reserved = new Set([
diff --git a/test/runtime/samples/dynamic-component-nulled-out-intro/_config.js b/test/runtime/samples/dynamic-component-nulled-out-intro/_config.js
new file mode 100644
index 000000000000..9759ada538d2
--- /dev/null
+++ b/test/runtime/samples/dynamic-component-nulled-out-intro/_config.js
@@ -0,0 +1,5 @@
+export default {
+ test({ component }) {
+ component.visible = true;
+ }
+};
\ No newline at end of file
diff --git a/test/runtime/samples/dynamic-component-nulled-out-intro/main.svelte b/test/runtime/samples/dynamic-component-nulled-out-intro/main.svelte
new file mode 100644
index 000000000000..eac72cf694a6
--- /dev/null
+++ b/test/runtime/samples/dynamic-component-nulled-out-intro/main.svelte
@@ -0,0 +1,7 @@
+
+
+{#if visible}
+
+{/if}
\ No newline at end of file
diff --git a/test/runtime/samples/each-block-component-no-props/Child.svelte b/test/runtime/samples/each-block-component-no-props/Child.svelte
new file mode 100644
index 000000000000..86ef4f3319bc
--- /dev/null
+++ b/test/runtime/samples/each-block-component-no-props/Child.svelte
@@ -0,0 +1 @@
+hello
\ No newline at end of file
diff --git a/test/runtime/samples/each-block-component-no-props/_config.js b/test/runtime/samples/each-block-component-no-props/_config.js
new file mode 100644
index 000000000000..e8344496ca6f
--- /dev/null
+++ b/test/runtime/samples/each-block-component-no-props/_config.js
@@ -0,0 +1,16 @@
+export default {
+ html: `
+ hello
+ `,
+
+ async test({ assert, component, target }) {
+ await component.remove();
+ assert.htmlEqual(target.innerHTML, ``);
+
+ await component.add();
+ assert.htmlEqual(target.innerHTML, `hello
`);
+
+ await component.remove();
+ assert.htmlEqual(target.innerHTML, ``);
+ }
+};
diff --git a/test/runtime/samples/each-block-component-no-props/main.svelte b/test/runtime/samples/each-block-component-no-props/main.svelte
new file mode 100644
index 000000000000..01299fe31418
--- /dev/null
+++ b/test/runtime/samples/each-block-component-no-props/main.svelte
@@ -0,0 +1,17 @@
+
+
+{#each items as item}
+
+{/each}
diff --git a/test/runtime/samples/event-handler-shorthand-sanitized/_config.js b/test/runtime/samples/event-handler-shorthand-sanitized/_config.js
new file mode 100644
index 000000000000..030e27ad1a12
--- /dev/null
+++ b/test/runtime/samples/event-handler-shorthand-sanitized/_config.js
@@ -0,0 +1,18 @@
+export default {
+ html: `
+
+ `,
+
+ test({ assert, component, target, window }) {
+ const button = target.querySelector('button');
+ const event = new window.Event('click-now');
+
+ let clicked;
+ component.$on('click-now', () => {
+ clicked = true;
+ });
+
+ button.dispatchEvent(event);
+ assert.ok(clicked);
+ }
+};
diff --git a/test/runtime/samples/event-handler-shorthand-sanitized/main.svelte b/test/runtime/samples/event-handler-shorthand-sanitized/main.svelte
new file mode 100644
index 000000000000..05de1316efae
--- /dev/null
+++ b/test/runtime/samples/event-handler-shorthand-sanitized/main.svelte
@@ -0,0 +1 @@
+
\ No newline at end of file