fix hoisting of functions that reference imported values - fixes

pull/1936/head
Rich Harris 6 years ago committed by GitHub
parent cc9a172d7c
commit d6552025e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -683,7 +683,7 @@ export default class Component {
// reference instance variables other than other
// hoistable functions. TODO others?
const { hoistable_names, hoistable_nodes } = this;
const { hoistable_names, hoistable_nodes, imported_declarations } = this;
const top_level_function_declarations = new Map();
@ -738,6 +738,7 @@ export default class Component {
if (owner === instance_scope) {
if (name === fn_declaration.id.name) return;
if (hoistable_names.has(name)) return;
if (imported_declarations.has(name)) return;
if (top_level_function_declarations.has(name)) {
const other_declaration = top_level_function_declarations.get(name);

@ -1,12 +1,13 @@
import Node from './shared/Node';
import Expression from './shared/Expression';
import Component from '../Component';
export default class Animation extends Node {
type: 'Animation';
name: string;
expression: Expression;
constructor(component, parent, scope, info) {
constructor(component: Component, parent, scope, info) {
super(component, parent, scope, info);
component.warn_if_undefined(info, scope);

@ -264,17 +264,19 @@ export default class Expression {
code.overwrite(node.start, node.end, dirty.map(n => `$$invalidate('${n}', ${n})`).join('; '));
} else {
names.forEach(name => {
if (!scope.declarations.has(name)) {
pending_assignments.add(name);
}
if (scope.declarations.has(name)) return;
if (component.imported_declarations.has(name)) return;
pending_assignments.add(name);
});
}
} else if (node.type === 'UpdateExpression') {
const { name } = getObject(node.argument);
if (!scope.declarations.has(name)) {
pending_assignments.add(name);
}
if (scope.declarations.has(name)) return;
if (component.imported_declarations.has(name)) return;
pending_assignments.add(name);
}
} else {
if (node.type === 'AssignmentExpression') {

@ -174,10 +174,11 @@ export default function dom(
code.overwrite(node.start, node.end, dirty.map(n => `$$invalidate('${n}', ${n})`).join('; '));
} else {
names.forEach(name => {
if (scope.findOwner(name) === component.instance_scope) {
pending_assignments.add(name);
component.has_reactive_assignments = true;
}
if (component.imported_declarations.has(name)) return;
if (scope.findOwner(name) !== component.instance_scope) return;
pending_assignments.add(name);
component.has_reactive_assignments = true;
});
}
}
@ -185,10 +186,11 @@ export default function dom(
else if (node.type === 'UpdateExpression') {
const { name } = getObject(node.argument);
if (scope.findOwner(name) === component.instance_scope) {
pending_assignments.add(name);
component.has_reactive_assignments = true;
}
if (component.imported_declarations.has(name)) return;
if (scope.findOwner(name) !== component.instance_scope) return;
pending_assignments.add(name);
component.has_reactive_assignments = true;
}
if (pending_assignments.size > 0) {

@ -682,10 +682,7 @@ export default class ElementWrapper extends Wrapper {
const params = this.node.animation.expression ? this.node.animation.expression.render() : '{}';
let { name } = this.node.animation;
if (!component.hoistable_names.has(name) && !component.imported_declarations.has(name)) {
name = `ctx.${name}`;
}
const name = component.qualify(this.node.animation.name);
block.builders.animate.addBlock(deindent`
if (${animation}) ${animation}.stop();

@ -0,0 +1,56 @@
export default {
props: {
things: [
{ id: 1, name: 'a' },
{ id: 2, name: 'b' },
{ id: 3, name: 'c' },
{ id: 4, name: 'd' },
{ id: 5, name: 'e' }
]
},
html: `
<div>a</div>
<div>b</div>
<div>c</div>
<div>d</div>
<div>e</div>
`,
test({ assert, component, target, window, raf }) {
let divs = document.querySelectorAll('div');
divs.forEach(div => {
div.getBoundingClientRect = function() {
const index = [...this.parentNode.children].indexOf(this);
const top = index * 30;
return {
left: 0,
right: 100,
top,
bottom: top + 20
}
};
})
component.things = [
{ id: 5, name: 'e' },
{ id: 2, name: 'b' },
{ id: 3, name: 'c' },
{ id: 4, name: 'd' },
{ id: 1, name: 'a' }
];
divs = document.querySelectorAll('div');
assert.equal(divs[0].dy, 120);
assert.equal(divs[4].dy, -120);
raf.tick(50);
assert.equal(divs[0].dy, 60);
assert.equal(divs[4].dy, -60);
raf.tick(100);
assert.equal(divs[0].dy, 0);
assert.equal(divs[4].dy, 0);
}
};

@ -0,0 +1,3 @@
export function linear(t) {
return t;
}

@ -0,0 +1,22 @@
<script>
import { linear } from './easing.js';
export let things;
function flip(node, animation, params) {
const dx = animation.from.left - animation.to.left;
const dy = animation.from.top - animation.to.top;
return {
duration: 100,
easing: linear,
tick: (t, u) => {
node.dx = u * dx;
node.dy = u * dy;
}
};
}
</script>
{#each things as thing (thing.id)}
<div animate:flip>{thing.name}</div>
{/each}
Loading…
Cancel
Save