differentiate between mutated and reassigned

pull/2011/head
Richard Harris 7 years ago
parent 2431780851
commit b284458cdf

@ -99,7 +99,7 @@ export default class Stats {
return {
timings,
warnings: this.warnings,
vars: component.vars.filter(variable => !variable.global && !variable.implicit).map(variable => ({
vars: component.vars.filter(variable => !variable.global && !variable.implicit && !variable.internal).map(variable => ({
name: variable.name,
export_name: variable.export_name || null,
injected: variable.injected || false,

@ -429,28 +429,16 @@ export default class Component {
if (node.type === 'ExportNamedDeclaration') {
if (node.declaration) {
const { kind } = node.declaration;
if (node.declaration.type === 'VariableDeclaration') {
node.declaration.declarations.forEach(declarator => {
extractNames(declarator.id).forEach(name => {
const variable = this.var_lookup.get(name);
variable.export_name = name;
if (kind !== 'const') variable.mutated = true;
});
});
} else {
const { name } = node.declaration.id;
const kind = node.declaration.type === 'ClassDeclaration'
? 'class'
: node.declaration.type === 'FunctionDeclaration'
? 'function'
: null;
// sanity check
if (!kind) throw new Error(`Unknown declaration type ${node.declaration.type}`);
const variable = this.var_lookup.get(name);
variable.export_name = name;
}
@ -636,13 +624,17 @@ export default class Component {
walk(this.ast.instance.content, {
enter(node, parent) {
let names;
if (map.has(node)) {
scope = map.get(node);
}
let names;
let deep = false;
if (node.type === 'AssignmentExpression') {
names = node.left.type === 'MemberExpression'
deep = node.left.type === 'MemberExpression';
names = deep
? [getObject(node.left).name]
: extractNames(node.left);
} else if (node.type === 'UpdateExpression') {
@ -653,7 +645,7 @@ export default class Component {
names.forEach(name => {
if (scope.findOwner(name) === instance_scope) {
const variable = component.var_lookup.get(name);
variable.mutated = true;
variable[deep ? 'mutated' : 'reassigned'] = true;
}
});
}
@ -836,7 +828,7 @@ export default class Component {
this.ast.instance.content.body.forEach(node => {
if (node.type === 'VariableDeclaration') {
if (node.declarations.every(d => d.init && d.init.type === 'Literal' && !this.var_lookup.get(d.id.name).mutated)) {
if (node.declarations.every(d => d.init && d.init.type === 'Literal' && !this.var_lookup.get(d.id.name).reassigned)) {
node.declarations.forEach(d => {
const variable = this.var_lookup.get(d.id.name);
variable.hoistable = true;

@ -34,11 +34,11 @@ export default class Binding extends Node {
if (this.isContextual) {
scope.dependenciesForName.get(name).forEach(name => {
const variable = component.var_lookup.get(name);
variable.mutated = true;
variable[this.expression.node.type === 'MemberExpression' ? 'mutated' : 'reassigned'] = true;
});
} else {
const variable = component.var_lookup.get(name);
variable.mutated = true;
variable[this.expression.node.type === 'MemberExpression' ? 'mutated' : 'reassigned'] = true;
}
if (this.expression.node.type === 'MemberExpression') {

@ -44,7 +44,7 @@ export default class EventHandler extends Node {
component.add_var({
name,
injected: true,
internal: true,
referenced: true
});

@ -149,30 +149,33 @@ export default class Expression {
}
// track any assignments from template expressions as mutable
let mutated;
let names;
let deep = false;
if (function_expression) {
if (node.type === 'AssignmentExpression') {
mutated = node.left.type === 'MemberExpression'
deep = node.left.type === 'MemberExpression';
names = deep
? [getObject(node.left).name]
: extractNames(node.left);
} else if (node.type === 'UpdateExpression') {
const { name } = getObject(node.argument);
mutated = [name];
names = [name];
}
}
if (mutated) {
mutated.forEach(name => {
if (names) {
names.forEach(name => {
if (template_scope.names.has(name)) {
template_scope.dependenciesForName.get(name).forEach(name => {
const variable = component.var_lookup.get(name);
if (variable) variable.mutated = true;
if (variable) variable[deep ? 'mutated' : 'reassigned'] = true;
});
} else {
component.add_reference(name);
const variable = component.var_lookup.get(name);
if (variable) variable.mutated = true;
if (variable) variable[deep ? 'mutated' : 'reassigned'] = true;
}
});
}
@ -381,7 +384,7 @@ export default class Expression {
component.add_var({
name,
injected: true,
internal: true,
hoistable: true,
referenced: true
});
@ -394,7 +397,7 @@ export default class Expression {
component.add_var({
name,
injected: true,
internal: true,
referenced: true
});
}
@ -406,7 +409,7 @@ export default class Expression {
component.add_var({
name,
injected: true,
internal: true,
referenced: true
});

@ -181,9 +181,11 @@ export default class AwaitBlockWrapper extends Wrapper {
}
const conditions = [];
if (this.node.expression.dependencies.size > 0) {
const dependencies = this.node.expression.dynamic_dependencies();
if (dependencies.length > 0) {
conditions.push(
`(${[...this.node.expression.dependencies].map(dep => `'${dep}' in changed`).join(' || ')})`
`(${dependencies.map(dep => `'${dep}' in changed`).join(' || ')})`
);
}

@ -408,7 +408,7 @@ export default class ElementWrapper extends Wrapper {
renderer.component.add_var({
name: handler,
injected: true,
internal: true,
referenced: true
});
@ -513,7 +513,7 @@ export default class ElementWrapper extends Wrapper {
renderer.component.add_var({
name,
injected: true,
internal: true,
referenced: true
});

@ -147,14 +147,16 @@ export default class InlineComponentWrapper extends Wrapper {
}
const fragment_dependencies = new Set();
this.slots.forEach((slot, name) => {
this.slots.forEach(slot => {
slot.block.dependencies.forEach(name => {
const is_let = slot.scope.is_let(name);
const variable = renderer.component.var_lookup.get(name);
if (is_let || variable.mutated) {
fragment_dependencies.add(name);
}
if (is_let) fragment_dependencies.add(name);
if (!variable) return;
if (variable.mutated || variable.reassigned) fragment_dependencies.add(name);
if (!variable.module && variable.writable && variable.export_name) fragment_dependencies.add(name);
});
});
@ -241,7 +243,7 @@ export default class InlineComponentWrapper extends Wrapper {
component.add_var({
name: fn,
injected: true,
internal: true,
referenced: true
});
@ -276,7 +278,7 @@ export default class InlineComponentWrapper extends Wrapper {
component.add_var({
name,
injected: true,
internal: true,
referenced: true
});

@ -120,7 +120,7 @@ export default class WindowWrapper extends Wrapper {
component.add_var({
name: handler_name,
injected: true,
internal: true,
referenced: true
});

@ -91,7 +91,8 @@ export interface Var {
// used internally, but not exposed
global?: boolean;
implicit?: boolean;
implicit?: boolean; // logic-less template references
internal?: boolean; // event handlers, bindings
initialised?: boolean;
hoistable?: boolean;
}

@ -0,0 +1,26 @@
export default {
test(assert, stats) {
assert.deepEqual(stats.vars, [
{
name: 'count',
export_name: null,
injected: false,
module: false,
mutated: false,
reassigned: true,
referenced: true,
writable: true
},
{
name: 'user',
export_name: null,
injected: false,
module: false,
mutated: true,
reassigned: false,
referenced: true,
writable: false
}
]);
}
};

@ -0,0 +1,7 @@
<script>
let count;
const user = { name: 'world' };
</script>
<input bind:value={user.name}>
<input type=number bind:value={count}>

@ -0,0 +1,26 @@
export default {
test(assert, stats) {
assert.deepEqual(stats.vars, [
{
name: 'count',
export_name: null,
injected: false,
module: false,
mutated: false,
reassigned: true,
referenced: true,
writable: true
},
{
name: 'user',
export_name: null,
injected: false,
module: false,
mutated: true,
reassigned: false,
referenced: true,
writable: false
}
]);
}
};

@ -0,0 +1,7 @@
<script>
let count;
const user = { name: 'world' };
</script>
<input on:input="{e => user.name = e.value}">
<input type=number on:input="{e => count = +e.value}">

@ -6,7 +6,7 @@ export default {
export_name: 'name',
injected: false,
module: false,
mutated: true,
mutated: false,
reassigned: false,
referenced: true,
writable: true
@ -16,7 +16,7 @@ export default {
export_name: 'cats',
injected: false,
module: false,
mutated: true,
mutated: false,
reassigned: false,
referenced: true,
writable: true
@ -36,8 +36,8 @@ export default {
export_name: null,
injected: false,
module: false,
mutated: true,
reassigned: false,
mutated: false,
reassigned: true,
referenced: true,
writable: true
}

Loading…
Cancel
Save