From b1fdcbf5760a732239d06cddc805dd1c99797f1a Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 25 Jun 2019 11:46:30 -0400 Subject: [PATCH 1/6] fix placement of each-else block, and clarify node references in source - fixes #2917 --- .../compile/render_dom/wrappers/EachBlock.ts | 102 +++++++++++------- .../samples/each-block-else-in-if/_config.js | 17 +++ .../samples/each-block-else-in-if/main.svelte | 14 +++ 3 files changed, 93 insertions(+), 40 deletions(-) create mode 100644 test/runtime/samples/each-block-else-in-if/_config.js create mode 100644 test/runtime/samples/each-block-else-in-if/main.svelte diff --git a/src/compiler/compile/render_dom/wrappers/EachBlock.ts b/src/compiler/compile/render_dom/wrappers/EachBlock.ts index 9e4f0689fa..0a40511150 100644 --- a/src/compiler/compile/render_dom/wrappers/EachBlock.ts +++ b/src/compiler/compile/render_dom/wrappers/EachBlock.ts @@ -50,7 +50,6 @@ export default class EachBlockWrapper extends Wrapper { fragment: FragmentWrapper; else?: ElseBlockWrapper; vars: { - anchor: string; create_each_block: string; each_block_value: string; get_each_context: string; @@ -119,10 +118,7 @@ export default class EachBlockWrapper extends Wrapper { // optimisation for array literal fixed_length, data_length: fixed_length === null ? `${each_block_value}.[✂${c}-${c+4}✂]` : fixed_length, - view_length: fixed_length === null ? `${iterations}.[✂${c}-${c+4}✂]` : fixed_length, - - // filled out later - anchor: null + view_length: fixed_length === null ? `${iterations}.[✂${c}-${c+4}✂]` : fixed_length }; node.contexts.forEach(prop => { @@ -175,10 +171,6 @@ export default class EachBlockWrapper extends Wrapper { ? !this.next.is_dom_node() : !parent_node || !this.parent.is_dom_node(); - this.vars.anchor = needs_anchor - ? block.get_unique_name(`${this.var}_anchor`) - : (this.next && this.next.var) || 'null'; - this.context_props = this.node.contexts.map(prop => `child_ctx.${prop.key.name} = ${attach_head('list[i]', prop.tail)};`); if (this.node.has_binding) this.context_props.push(`child_ctx.${this.vars.each_block_value} = list;`); @@ -196,10 +188,28 @@ export default class EachBlockWrapper extends Wrapper { } `); + const initial_anchor_node = parent_node ? 'null' : 'anchor'; + const initial_mount_node = parent_node || '#target'; + const update_anchor_node = needs_anchor + ? block.get_unique_name(`${this.var}_anchor`) + : (this.next && this.next.var) || 'null'; + const update_mount_node = this.get_update_mount_node(update_anchor_node); + + const args = { + block, + parent_node, + parent_nodes, + snippet, + initial_anchor_node, + initial_mount_node, + update_anchor_node, + update_mount_node + }; + if (this.node.key) { - this.render_keyed(block, parent_node, parent_nodes, snippet); + this.render_keyed(args); } else { - this.render_unkeyed(block, parent_node, parent_nodes, snippet); + this.render_unkeyed(args); } if (this.block.has_intro_method || this.block.has_outro_method) { @@ -210,7 +220,7 @@ export default class EachBlockWrapper extends Wrapper { if (needs_anchor) { block.add_element( - this.vars.anchor, + update_anchor_node, `@empty()`, parent_nodes && `@empty()`, parent_node @@ -232,12 +242,10 @@ export default class EachBlockWrapper extends Wrapper { block.builders.mount.add_block(deindent` if (${each_block_else}) { - ${each_block_else}.m(${parent_node || '#target'}, null); + ${each_block_else}.m(${initial_mount_node}, ${initial_anchor_node}); } `); - const initial_mount_node = parent_node || `${this.vars.anchor}.parentNode`; - if (this.else.block.has_update_method) { block.builders.update.add_block(deindent` if (!${this.vars.data_length} && ${each_block_else}) { @@ -245,7 +253,7 @@ export default class EachBlockWrapper extends Wrapper { } else if (!${this.vars.data_length}) { ${each_block_else} = ${this.else.block.name}(ctx); ${each_block_else}.c(); - ${each_block_else}.m(${initial_mount_node}, ${this.vars.anchor}); + ${each_block_else}.m(${update_mount_node}, ${update_anchor_node}); } else if (${each_block_else}) { ${each_block_else}.d(1); ${each_block_else} = null; @@ -261,7 +269,7 @@ export default class EachBlockWrapper extends Wrapper { } else if (!${each_block_else}) { ${each_block_else} = ${this.else.block.name}(ctx); ${each_block_else}.c(); - ${each_block_else}.m(${initial_mount_node}, ${this.vars.anchor}); + ${each_block_else}.m(${update_mount_node}, ${update_anchor_node}); } `); } @@ -278,16 +286,28 @@ export default class EachBlockWrapper extends Wrapper { } } - render_keyed( + render_keyed({ + block, + parent_node, + parent_nodes, + snippet, + initial_anchor_node, + initial_mount_node, + update_anchor_node, + update_mount_node + }: { block: Block, parent_node: string, parent_nodes: string, - snippet: string - ) { + snippet: string, + initial_anchor_node: string, + initial_mount_node: string, + update_anchor_node: string, + update_mount_node: string + }) { const { create_each_block, length, - anchor, iterations, view_length } = this.vars; @@ -322,10 +342,6 @@ export default class EachBlockWrapper extends Wrapper { } `); - const initial_mount_node = parent_node || '#target'; - const update_mount_node = this.get_update_mount_node(anchor); - const anchor_node = parent_node ? 'null' : 'anchor'; - block.builders.create.add_block(deindent` for (#i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].c(); `); @@ -337,7 +353,7 @@ export default class EachBlockWrapper extends Wrapper { } block.builders.mount.add_block(deindent` - for (#i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].m(${initial_mount_node}, ${anchor_node}); + for (#i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node}); `); const dynamic = this.block.has_update_method; @@ -355,7 +371,7 @@ export default class EachBlockWrapper extends Wrapper { ${this.block.has_outros && `@group_outros();`} ${this.node.has_animation && `for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].r();`} - ${iterations} = @update_keyed_each(${iterations}, changed, ${get_key}, ${dynamic ? '1' : '0'}, ctx, ${this.vars.each_block_value}, ${lookup}, ${update_mount_node}, ${destroy}, ${create_each_block}, ${anchor}, ${this.vars.get_each_context}); + ${iterations} = @update_keyed_each(${iterations}, changed, ${get_key}, ${dynamic ? '1' : '0'}, ctx, ${this.vars.each_block_value}, ${lookup}, ${update_mount_node}, ${destroy}, ${create_each_block}, ${update_anchor_node}, ${this.vars.get_each_context}); ${this.node.has_animation && `for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].a();`} ${this.block.has_outros && `@check_outros();`} `); @@ -371,20 +387,30 @@ export default class EachBlockWrapper extends Wrapper { `); } - render_unkeyed( + render_unkeyed({ + block, + parent_nodes, + snippet, + initial_anchor_node, + initial_mount_node, + update_anchor_node, + update_mount_node + }: { block: Block, - parent_node: string, parent_nodes: string, - snippet: string - ) { + snippet: string, + initial_anchor_node: string, + initial_mount_node: string, + update_anchor_node: string, + update_mount_node: string + }) { const { create_each_block, length, iterations, fixed_length, data_length, - view_length, - anchor + view_length } = this.vars; block.builders.init.add_block(deindent` @@ -395,10 +421,6 @@ export default class EachBlockWrapper extends Wrapper { } `); - const initial_mount_node = parent_node || '#target'; - const update_mount_node = this.get_update_mount_node(anchor); - const anchor_node = parent_node ? 'null' : 'anchor'; - block.builders.create.add_block(deindent` for (var #i = 0; #i < ${view_length}; #i += 1) { ${iterations}[#i].c(); @@ -415,7 +437,7 @@ export default class EachBlockWrapper extends Wrapper { block.builders.mount.add_block(deindent` for (var #i = 0; #i < ${view_length}; #i += 1) { - ${iterations}[#i].m(${initial_mount_node}, ${anchor_node}); + ${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node}); } `); @@ -441,14 +463,14 @@ export default class EachBlockWrapper extends Wrapper { ${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}, ${anchor}); + ${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}, ${anchor}); + ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node}); `; const start = this.block.has_update_method ? '0' : `${view_length}`; diff --git a/test/runtime/samples/each-block-else-in-if/_config.js b/test/runtime/samples/each-block-else-in-if/_config.js new file mode 100644 index 0000000000..c800ee8a30 --- /dev/null +++ b/test/runtime/samples/each-block-else-in-if/_config.js @@ -0,0 +1,17 @@ +export default { + html: ` +

nothing

+

after

+ `, + + test({ assert, component, target }) { + component.visible = false; + assert.htmlEqual(target.innerHTML, ``); + + component.visible = true; + assert.htmlEqual(target.innerHTML, ` +

nothing

+

after

+ `); + } +}; diff --git a/test/runtime/samples/each-block-else-in-if/main.svelte b/test/runtime/samples/each-block-else-in-if/main.svelte new file mode 100644 index 0000000000..d89f645d7f --- /dev/null +++ b/test/runtime/samples/each-block-else-in-if/main.svelte @@ -0,0 +1,14 @@ + + +{#if visible} + {#each empty as item} +

{item}

+ {:else} +

nothing

+ {/each} + +

after

+{/if} \ No newline at end of file From 39760b70f8004383b1bcca53f711bb416b6ce455 Mon Sep 17 00:00:00 2001 From: mellisdesigns Date: Wed, 26 Jun 2019 16:50:31 +1000 Subject: [PATCH 2/6] documentation - binding this remove 256 canvas size --- site/content/tutorial/06-bindings/12-bind-this/text.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/content/tutorial/06-bindings/12-bind-this/text.md b/site/content/tutorial/06-bindings/12-bind-this/text.md index e53b624057..4784b6b13f 100644 --- a/site/content/tutorial/06-bindings/12-bind-this/text.md +++ b/site/content/tutorial/06-bindings/12-bind-this/text.md @@ -7,8 +7,8 @@ The readonly `this` binding applies to every element (and component) and allows ```html ``` From b9cdadcd22ab1693d1f225cd55c1bd38e17da5d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=BC=8E?= Date: Thu, 27 Jun 2019 02:01:43 +0800 Subject: [PATCH 3/6] change "item" to "thing" The text in the button is "Remove first thing". --- site/content/tutorial/04-logic/05-keyed-each-blocks/text.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/content/tutorial/04-logic/05-keyed-each-blocks/text.md b/site/content/tutorial/04-logic/05-keyed-each-blocks/text.md index e8bac7d8df..3c204d1413 100644 --- a/site/content/tutorial/04-logic/05-keyed-each-blocks/text.md +++ b/site/content/tutorial/04-logic/05-keyed-each-blocks/text.md @@ -4,7 +4,7 @@ title: Keyed each blocks By default, when you modify the value of an `each` block, it will add and remove items at the *end* of the block, and update any values that have changed. That might not be what you want. -It's easier to show why than to explain. Click the 'Remove first item' button a few times, and notice that it's removing `` components from the end and updating the `value` for those that remain. Instead, we'd like to remove the first `` component and leave the rest unaffected. +It's easier to show why than to explain. Click the 'Remove first thing' button a few times, and notice that it's removing `` components from the end and updating the `value` for those that remain. Instead, we'd like to remove the first `` component and leave the rest unaffected. To do that, we specify a unique identifier for the `each` block: @@ -16,4 +16,4 @@ To do that, we specify a unique identifier for the `each` block: The `(thing.id)` tells Svelte how to figure out what changed. -> You can use any object as the key, as Svelte uses a `Map` internally — in other words you could do `(thing)` instead of `(thing.id)`. Using a string or number is generally safer, however, since it means identity persists without referential equality, for example when updating with fresh data from an API server. \ No newline at end of file +> You can use any object as the key, as Svelte uses a `Map` internally — in other words you could do `(thing)` instead of `(thing.id)`. Using a string or number is generally safer, however, since it means identity persists without referential equality, for example when updating with fresh data from an API server. From d5add38145a92ed4d03aef10a74b56520f136c3b Mon Sep 17 00:00:00 2001 From: Volkov Sergey Date: Wed, 26 Jun 2019 23:24:34 +0300 Subject: [PATCH 4/6] fix: added output files to eslint ignore --- .eslintignore | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.eslintignore b/.eslintignore index 4a113378ce..023e6d045b 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,4 +4,15 @@ store.js test/test.js test/setup.js **/_actual.js -**/expected.js \ No newline at end of file +**/expected.js + + +# output files +animate.js +compiler.js +esing.js +index.js +internal.js +motion.js +store.js +transition.js From b4db5dbbe8df90f680022bf03e151b94d1593240 Mon Sep 17 00:00:00 2001 From: Volkov Sergey Date: Thu, 27 Jun 2019 00:31:23 +0300 Subject: [PATCH 5/6] fix: update eslint ignore for build files --- .eslintignore | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.eslintignore b/.eslintignore index e6f44fbdd8..04940e2f7d 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,11 +3,11 @@ test/*/samples/*/output.js # output files -animate.js -compiler.js -esing.js +animate/*.js +esing/*.js +internal/*.js +motion/*.js +store/*.js +transition/*.js index.js -internal.js -motion.js -store.js -transition.js +compiler.js From 6af23ba88c0a0e8bc83bd4393a2f96b705667533 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 27 Jun 2019 19:59:11 -0400 Subject: [PATCH 6/6] Fix contextual bind:this (#2806) --- .../render_dom/wrappers/Element/index.ts | 34 +------- .../wrappers/InlineComponent/index.ts | 38 +-------- .../render_dom/wrappers/shared/bind_this.ts | 80 +++++++++++++++++++ src/runtime/internal/scheduler.ts | 2 +- .../Foo.svelte | 7 ++ .../_config.js | 12 +++ .../main.svelte | 13 +++ .../_config.js | 12 +++ .../main.svelte | 11 +++ 9 files changed, 141 insertions(+), 68 deletions(-) create mode 100644 src/compiler/compile/render_dom/wrappers/shared/bind_this.ts create mode 100644 test/runtime/samples/binding-this-each-block-property-component/Foo.svelte create mode 100644 test/runtime/samples/binding-this-each-block-property-component/_config.js create mode 100644 test/runtime/samples/binding-this-each-block-property-component/main.svelte create mode 100644 test/runtime/samples/binding-this-each-block-property/_config.js create mode 100644 test/runtime/samples/binding-this-each-block-property/main.svelte diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts index 9179225e29..9b14d1cd6c 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/index.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts @@ -19,6 +19,7 @@ import add_event_handlers from '../shared/add_event_handlers'; import add_actions from '../shared/add_actions'; import create_debugging_comment from '../shared/create_debugging_comment'; import { get_context_merger } from '../shared/get_context_merger'; +import bind_this from '../shared/bind_this'; const events = [ { @@ -540,38 +541,9 @@ export default class ElementWrapper extends Wrapper { const this_binding = this.bindings.find(b => b.node.name === 'this'); if (this_binding) { - const name = renderer.component.get_unique_name(`${this.var}_binding`); + const binding_callback = bind_this(renderer.component, block, this_binding.node, this.var); - renderer.component.add_var({ - name, - internal: true, - referenced: true - }); - - const { handler, object } = this_binding; - - const args = []; - for (const arg of handler.contextual_dependencies) { - args.push(arg); - block.add_variable(arg, `ctx.${arg}`); - } - - renderer.component.partly_hoisted.push(deindent` - function ${name}(${['$$node', 'check'].concat(args).join(', ')}) { - ${handler.snippet ? `if ($$node || (!$$node && ${handler.snippet} === check)) ` : ''}${handler.mutation} - ${renderer.component.invalidate(object)}; - } - `); - - block.builders.mount.add_line(`@add_binding_callback(() => ctx.${name}(${[this.var, 'null'].concat(args).join(', ')}));`); - block.builders.destroy.add_line(`ctx.${name}(${['null', this.var].concat(args).join(', ')});`); - block.builders.update.add_line(deindent` - if (changed.items) { - ctx.${name}(${['null', this.var].concat(args).join(', ')}); - ${args.map(a => `${a} = ctx.${a}`).join(', ')}; - ctx.${name}(${[this.var, 'null'].concat(args).join(', ')}); - }` - ); + block.builders.mount.add_line(binding_callback); } } diff --git a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts index 6045daaf36..ece8abf3b0 100644 --- a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts +++ b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts @@ -9,11 +9,11 @@ import add_to_set from '../../../utils/add_to_set'; import deindent from '../../../utils/deindent'; import Attribute from '../../../nodes/Attribute'; import get_object from '../../../utils/get_object'; -import flatten_reference from '../../../utils/flatten_reference'; import create_debugging_comment from '../shared/create_debugging_comment'; import { get_context_merger } from '../shared/get_context_merger'; import EachBlock from '../../../nodes/EachBlock'; import TemplateScope from '../../../nodes/shared/TemplateScope'; +import bind_this from '../shared/bind_this'; export default class InlineComponentWrapper extends Wrapper { var: string; @@ -252,41 +252,7 @@ export default class InlineComponentWrapper extends Wrapper { component.has_reactive_assignments = true; if (binding.name === 'this') { - const fn = component.get_unique_name(`${this.var}_binding`); - - component.add_var({ - name: fn, - internal: true, - referenced: true - }); - - let lhs; - let object; - - if (binding.is_contextual && binding.expression.node.type === 'Identifier') { - // bind:x={y} — we can't just do `y = x`, we need to - // to `array[index] = x; - const { name } = binding.expression.node; - const { snippet } = block.bindings.get(name); - lhs = snippet; - - // TODO we need to invalidate... something - } else { - object = flatten_reference(binding.expression.node).name; - lhs = component.source.slice(binding.expression.node.start, binding.expression.node.end).trim(); - } - - const contextual_dependencies = [...binding.expression.contextual_dependencies]; - - component.partly_hoisted.push(deindent` - function ${fn}(${['$$component', ...contextual_dependencies].join(', ')}) { - ${lhs} = $$component; - ${object && component.invalidate(object)} - } - `); - - block.builders.destroy.add_line(`ctx.${fn}(null);`); - return `@add_binding_callback(() => ctx.${fn}(${[this.var, ...contextual_dependencies.map(name => `ctx.${name}`)].join(', ')}));`; + return bind_this(component, block, binding, this.var); } const name = component.get_unique_name(`${this.var}_${binding.name}_binding`); diff --git a/src/compiler/compile/render_dom/wrappers/shared/bind_this.ts b/src/compiler/compile/render_dom/wrappers/shared/bind_this.ts new file mode 100644 index 0000000000..3d08cfaff5 --- /dev/null +++ b/src/compiler/compile/render_dom/wrappers/shared/bind_this.ts @@ -0,0 +1,80 @@ +import flatten_reference from '../../../utils/flatten_reference'; +import deindent from '../../../utils/deindent'; +import Component from '../../../Component'; +import Block from '../../Block'; +import Binding from '../../../nodes/Binding'; + +export default function bind_this(component: Component, block: Block, binding: Binding, variable: string) { + const fn = component.get_unique_name(`${variable}_binding`); + + component.add_var({ + name: fn, + internal: true, + referenced: true + }); + + let lhs; + let object; + + if (binding.is_contextual && binding.expression.node.type === 'Identifier') { + // bind:x={y} — we can't just do `y = x`, we need to + // to `array[index] = x; + const { name } = binding.expression.node; + const { snippet } = block.bindings.get(name); + lhs = snippet; + + // TODO we need to invalidate... something + } else { + object = flatten_reference(binding.expression.node).name; + lhs = component.source.slice(binding.expression.node.start, binding.expression.node.end).trim(); + } + + const contextual_dependencies = Array.from(binding.expression.contextual_dependencies); + + if (contextual_dependencies.length) { + component.partly_hoisted.push(deindent` + function ${fn}(${['$$value', ...contextual_dependencies].join(', ')}) { + if (${lhs} === $$value) return; + ${lhs} = $$value; + ${object && component.invalidate(object)} + } + `); + + const args = []; + for (const arg of contextual_dependencies) { + args.push(arg); + block.add_variable(arg, `ctx.${arg}`); + } + + const assign = block.get_unique_name(`assign_${variable}`); + const unassign = block.get_unique_name(`unassign_${variable}`); + + block.builders.init.add_block(deindent` + const ${assign} = () => ctx.${fn}(${[variable].concat(args).join(', ')}); + const ${unassign} = () => ctx.${fn}(${['null'].concat(args).join(', ')}); + `); + + const condition = Array.from(contextual_dependencies).map(name => `${name} !== ctx.${name}`).join(' || '); + + block.builders.update.add_line(deindent` + if (${condition}) { + ${unassign}(); + ${args.map(a => `${a} = ctx.${a}`).join(', ')}; + @add_binding_callback(${assign}); + }` + ); + + block.builders.destroy.add_line(`${unassign}();`); + return `@add_binding_callback(${assign});`; + } + + component.partly_hoisted.push(deindent` + function ${fn}($$value) { + ${lhs} = $$value; + ${object && component.invalidate(object)} + } + `); + + block.builders.destroy.add_line(`ctx.${fn}(null);`); + return `@add_binding_callback(() => ctx.${fn}(${variable}));`; +} \ No newline at end of file diff --git a/src/runtime/internal/scheduler.ts b/src/runtime/internal/scheduler.ts index a26a4f8c33..9e1b4280bf 100644 --- a/src/runtime/internal/scheduler.ts +++ b/src/runtime/internal/scheduler.ts @@ -46,7 +46,7 @@ export function flush() { update(component.$$); } - while (binding_callbacks.length) binding_callbacks.shift()(); + while (binding_callbacks.length) binding_callbacks.pop()(); // then, once components are updated, call // afterUpdate functions. This may cause diff --git a/test/runtime/samples/binding-this-each-block-property-component/Foo.svelte b/test/runtime/samples/binding-this-each-block-property-component/Foo.svelte new file mode 100644 index 0000000000..dc8b5f206c --- /dev/null +++ b/test/runtime/samples/binding-this-each-block-property-component/Foo.svelte @@ -0,0 +1,7 @@ + + +

\ No newline at end of file diff --git a/test/runtime/samples/binding-this-each-block-property-component/_config.js b/test/runtime/samples/binding-this-each-block-property-component/_config.js new file mode 100644 index 0000000000..947ec17929 --- /dev/null +++ b/test/runtime/samples/binding-this-each-block-property-component/_config.js @@ -0,0 +1,12 @@ +export default { + html: ``, + + async test({ assert, component, target }) { + component.visible = true; + assert.htmlEqual(target.innerHTML, ` +

a

+ `); + + assert.ok(component.items[0].ref.isFoo()); + } +}; diff --git a/test/runtime/samples/binding-this-each-block-property-component/main.svelte b/test/runtime/samples/binding-this-each-block-property-component/main.svelte new file mode 100644 index 0000000000..257aa18a91 --- /dev/null +++ b/test/runtime/samples/binding-this-each-block-property-component/main.svelte @@ -0,0 +1,13 @@ + + +{#if visible} + {#each items as item} + {item.value} + {/each} +{/if} diff --git a/test/runtime/samples/binding-this-each-block-property/_config.js b/test/runtime/samples/binding-this-each-block-property/_config.js new file mode 100644 index 0000000000..15ad4be5db --- /dev/null +++ b/test/runtime/samples/binding-this-each-block-property/_config.js @@ -0,0 +1,12 @@ +export default { + html: ``, + + async test({ assert, component, target }) { + component.visible = true; + assert.htmlEqual(target.innerHTML, ` +
a
+ `); + + assert.equal(component.items[0].ref, target.querySelector('div')); + } +}; diff --git a/test/runtime/samples/binding-this-each-block-property/main.svelte b/test/runtime/samples/binding-this-each-block-property/main.svelte new file mode 100644 index 0000000000..73ede7ab75 --- /dev/null +++ b/test/runtime/samples/binding-this-each-block-property/main.svelte @@ -0,0 +1,11 @@ + + +{#if visible} + {#each items as item} +
{item.value}
+ {/each} +{/if}