defer hoisting until after the template is walked - fixes #2005

pull/2007/head
Chris Reeves 6 years ago
parent 82f4ae6643
commit c9301dc9f7

@ -160,9 +160,12 @@ export default class Component {
: this.name; : this.name;
this.walk_module_js(); this.walk_module_js();
this.walk_instance_js(); this.walk_instance_js_pre_template();
this.fragment = new Fragment(this, ast.html); this.fragment = new Fragment(this, ast.html);
this.walk_instance_js_post_template();
if (!options.customElement) this.stylesheet.reify(); if (!options.customElement) this.stylesheet.reify();
this.stylesheet.warnOnUnusedSelectors(stats); this.stylesheet.warnOnUnusedSelectors(stats);
@ -510,7 +513,7 @@ export default class Component {
this.module_javascript = this.extract_javascript(script); this.module_javascript = this.extract_javascript(script);
} }
walk_instance_js() { walk_instance_js_pre_template() {
const script = this.instance_script; const script = this.instance_script;
if (!script) return; if (!script) return;
@ -545,6 +548,12 @@ export default class Component {
this.track_mutations(); this.track_mutations();
this.extract_imports_and_exports(script.content, this.imports, this.props); this.extract_imports_and_exports(script.content, this.imports, this.props);
}
walk_instance_js_post_template() {
const script = this.instance_script;
if (!script) return;
this.hoist_instance_declarations(); this.hoist_instance_declarations();
this.extract_reactive_declarations(); this.extract_reactive_declarations();
this.extract_reactive_store_references(); this.extract_reactive_store_references();
@ -756,12 +765,13 @@ export default class Component {
// hoistable functions. TODO others? // hoistable functions. TODO others?
const { hoistable_names, hoistable_nodes, imported_declarations, instance_scope: scope } = this; const { hoistable_names, hoistable_nodes, imported_declarations, instance_scope: scope } = this;
const template_scope = this.fragment.scope;
const top_level_function_declarations = new Map(); const top_level_function_declarations = new Map();
this.instance_script.content.body.forEach(node => { this.instance_script.content.body.forEach(node => {
if (node.type === 'VariableDeclaration') { if (node.type === 'VariableDeclaration') {
if (node.declarations.every(d => d.init && d.init.type === 'Literal' && !this.mutable_props.has(d.id.name))) { if (node.declarations.every(d => d.init && d.init.type === 'Literal' && !this.mutable_props.has(d.id.name) && !template_scope.containsMutable([d.id.name]))) {
node.declarations.forEach(d => { node.declarations.forEach(d => {
hoistable_names.add(d.id.name); hoistable_names.add(d.id.name);
}); });

@ -11,7 +11,7 @@ function create_fragment($$, ctx) {
text1 = createText("\n\n"); text1 = createText("\n\n");
p = createElement("p"); p = createElement("p");
text2 = createText("x: "); text2 = createText("x: ");
text3 = createText(x); text3 = createText(ctx.x);
dispose = addListener(button, "click", ctx.click_handler); dispose = addListener(button, "click", ctx.click_handler);
}, },
@ -25,7 +25,7 @@ function create_fragment($$, ctx) {
p(changed, ctx) { p(changed, ctx) {
if (changed.x) { if (changed.x) {
setData(text3, x); setData(text3, ctx.x);
} }
}, },
@ -44,15 +44,14 @@ function create_fragment($$, ctx) {
}; };
} }
let x = 0;
function instance($$self, $$props, $$invalidate) { function instance($$self, $$props, $$invalidate) {
let x = 0;
function click_handler() { function click_handler() {
if (true) { x += 1; $$invalidate('x', x); } if (true) { x += 1; $$invalidate('x', x); }
} }
return { click_handler }; return { x, click_handler };
} }
class SvelteComponent extends SvelteComponent_1 { class SvelteComponent extends SvelteComponent_1 {

@ -0,0 +1,5 @@
<script>
let count = 0;
</script>
<button on:click="{() => count += 1}">{count}</button>

@ -0,0 +1,14 @@
export default {
async test({ assert, target }) {
const btns = target.querySelectorAll('button');
const event = new window.MouseEvent('click');
await btns[0].dispatchEvent(event);
await btns[0].dispatchEvent(event);
await btns[1].dispatchEvent(event);
await btns[1].dispatchEvent(event);
await btns[1].dispatchEvent(event);
assert.equal(btns[1].innerHTML, '3');
}
};

@ -0,0 +1,6 @@
<script>
import Widget from './Widget.html';
</script>
<Widget />
<Widget />
Loading…
Cancel
Save