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