fix instrumentation

pull/1839/head
Rich Harris 7 years ago
parent aa528e5dba
commit a852760308

@ -19,8 +19,9 @@ import addToSet from '../utils/addToSet';
import isReference from 'is-reference';
import TemplateScope from './nodes/shared/TemplateScope';
import fuzzymatch from '../utils/fuzzymatch';
import { remove_indentation } from '../utils/remove_indentation';
import { remove_indentation, add_indentation } from '../utils/indentation';
import getObject from '../utils/getObject';
import deindent from '../utils/deindent';
type Meta = {
namespace?: string;
@ -614,34 +615,36 @@ export default class Component {
coalesced_declarations.forEach(group => {
const kind = group[0].kind;
let replacement = '';
let c = 0;
let combining = false;
group.forEach(node => {
node.declarations.forEach(({ id, init }) => {
node.declarations.forEach(declarator => {
const { id, init } = declarator;
if (id.type === 'Identifier') {
const value = init
? this.code.slice(id.start, init.end)
: this.code.slice(id.start, id.end);
if (combining) {
replacement += `, ${value}`;
code.overwrite(c, id.start, ', ');
} else {
replacement += `${kind} { ${value}`;
code.appendLeft(id.start, '{ ');
combining = true;
}
} else {
throw new Error('TODO destructured declarations');
}
c = declarator.end;
});
});
if (combining) {
replacement += ' } = $$props;';
code.prependRight(c, ' } = $$props');
}
this.code.overwrite(group[0].start, group[group.length - 1].end, replacement);
});
}
@ -796,13 +799,18 @@ export default class Component {
}
});
add_indentation(this.code, node.body, 2);
unsorted_reactive_declarations.push({
assignees,
dependencies,
node,
snippet: node.body.type === 'BlockStatement'
? `[✂${node.body.start}-${node.end}✂]`
: `{ [✂${node.body.start}-${node.end}✂] }`
: deindent`
{
[${node.body.start}-${node.end}]
}`
});
}
});

@ -4,12 +4,12 @@ import isReference from 'is-reference';
import flattenReference from '../../../utils/flattenReference';
import { createScopes, Scope } from '../../../utils/annotateWithScopes';
import { Node } from '../../../interfaces';
import addToSet from '../../../utils/addToSet';
import globalWhitelist from '../../../utils/globalWhitelist';
import deindent from '../../../utils/deindent';
import Wrapper from '../../render-dom/wrappers/shared/Wrapper';
import sanitize from '../../../utils/sanitize';
import TemplateScope from './TemplateScope';
import getObject from '../../../utils/getObject';
const binaryOperators: Record<string, number> = {
'**': 15,
@ -248,7 +248,7 @@ export default class Expression {
if (function_expression) {
if (node.type === 'AssignmentExpression') {
// TODO handle destructuring assignments
const { name } = flattenReference(node.left);
const { name } = getObject(node.left);
pending_assignments.add(name);
}
} else {
@ -296,7 +296,7 @@ export default class Expression {
let body = code.slice(node.body.start, node.body.end).trim();
if (node.body.type !== 'BlockStatement') {
if (pending_assignments.size > 0) {
const insert = [...pending_assignments].map(name => `$$make_dirty('${name}');`);
const insert = [...pending_assignments].map(name => `$$make_dirty('${name}')`).join('; ');
pending_assignments = new Set();
component.has_reactive_assignments = true;

@ -13,7 +13,7 @@ export default function dom(
component: Component,
options: CompileOptions
) {
const { name } = component;
const { name, code } = component;
const renderer = new Renderer(component, options);
const { block } = renderer;
@ -153,27 +153,63 @@ export default function dom(
let scope = component.instance_scope;
let map = component.instance_scope_map;
let pending_assignments = new Set();
walk(component.instance_script.content, {
enter: (node, parent) => {
if (map.has(node)) {
scope = map.get(node);
}
},
leave(node) {
if (map.has(node)) {
scope = scope.parent;
}
if (node.type === 'AssignmentExpression') {
const { name } = getObject(node.left);
if (scope.findOwner(name) === component.instance_scope) {
component.instrument(node, parent, name, false);
pending_assignments.add(name);
component.has_reactive_assignments = true;
}
}
},
leave(node) {
if (map.has(node)) {
scope = scope.parent;
if (pending_assignments.size > 0) {
if (node.type === 'ArrowFunctionExpression') {
const insert = [...pending_assignments].map(name => `$$make_dirty('${name}')`).join(';');
pending_assignments = new Set();
code.prependRight(node.body.start, `{ const $$result = `);
code.appendLeft(node.body.end, `; ${insert}; return $$result; }`);
pending_assignments = new Set();
}
else if (/Statement/.test(node.type)) {
const insert = [...pending_assignments].map(name => `$$make_dirty('${name}')`).join('; ');
if (/^(Break|Continue|Return)Statement/.test(node.type)) {
if (node.argument) {
code.overwrite(node.start, node.argument.start, `var $$result = `);
code.appendLeft(node.argument.end, `; ${insert}; return $$result`);
} else {
code.prependRight(node.start, `${insert}; `);
}
} else {
code.appendLeft(node.end, `${code.original[node.end - 1] === ';' ? '' : ';'} ${insert};`);
}
pending_assignments = new Set();
}
}
}
});
if (pending_assignments.size > 0) {
throw new Error(`TODO this should not happen!`);
}
}
const args = ['$$self'];
@ -237,8 +273,7 @@ export default function dom(
${component.reactive_declarations.length > 0 && deindent`
$$self.$$.update = ($$dirty = { ${Array.from(all_reactive_dependencies).map(n => `${n}: 1`).join(', ')} }) => {
${component.reactive_declarations.map(d => deindent`
if (${Array.from(d.dependencies).map(n => `$$dirty.${n}`).join(' || ')}) ${d.snippet}
`)}
if (${Array.from(d.dependencies).map(n => `$$dirty.${n}`).join(' || ')}) ${d.snippet}`)}
};
`}

@ -1,6 +1,7 @@
import MagicString from 'magic-string';
import { Node } from '../interfaces';
import { walk } from 'estree-walker';
import repeat from './repeat';
export function remove_indentation(code: MagicString, node: Node) {
const indent = code.getIndentString();
@ -26,4 +27,31 @@ export function remove_indentation(code: MagicString, node: Node) {
code.remove(index, index + indent.length);
}
}
export function add_indentation(code: MagicString, node: Node, levels = 1) {
const base_indent = code.getIndentString();
const indent = repeat(base_indent, levels);
const pattern = /\n/gm;
const excluded = [];
walk(node, {
enter(node) {
if (node.type === 'TemplateElement') {
excluded.push(node);
}
}
});
const str = code.original.slice(node.start, node.end);
let match;
while (match = pattern.exec(str)) {
const index = node.start + match.index;
while (excluded[0] && excluded[0].end < index) excluded.shift();
if (excluded[0] && excluded[0].start < index) continue;
code.appendLeft(index + 1, indent);
}
}

@ -64,7 +64,9 @@ function define($$self, $$props, $$make_dirty) {
};
$$self.$$.update = ($$dirty = { foo: 1 }) => {
if ($$dirty.foo) { bar = foo * 2; $$make_dirty('bar'); }
if ($$dirty.foo) {
bar = foo * 2; $$make_dirty('bar');
}
};
}

@ -0,0 +1,6 @@
export default {
test({ assert, component }) {
assert.equal(component.get_foo(), 1);
assert.equal(component.get_bar(), 2);
}
};

@ -0,0 +1,7 @@
<script>
let foo;
let bar = (foo = 1) * 2;
export const get_foo = () => foo;
export const get_bar = () => bar;
</script>

@ -2,8 +2,10 @@ export default {
html: '<p>50</p>',
test({ assert, component, target }) {
console.group('range [50,100]');
component.range = [50, 100];
assert.htmlEqual(target.innerHTML, '<p>75</p>');
console.groupEnd();
component.range = [50, 60];
assert.htmlEqual(target.innerHTML, '<p>55</p>');

Loading…
Cancel
Save