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 isReference from 'is-reference';
import TemplateScope from './nodes/shared/TemplateScope'; import TemplateScope from './nodes/shared/TemplateScope';
import fuzzymatch from '../utils/fuzzymatch'; 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 getObject from '../utils/getObject';
import deindent from '../utils/deindent';
type Meta = { type Meta = {
namespace?: string; namespace?: string;
@ -614,34 +615,36 @@ export default class Component {
coalesced_declarations.forEach(group => { coalesced_declarations.forEach(group => {
const kind = group[0].kind; const kind = group[0].kind;
let replacement = ''; let c = 0;
let combining = false; let combining = false;
group.forEach(node => { group.forEach(node => {
node.declarations.forEach(({ id, init }) => { node.declarations.forEach(declarator => {
const { id, init } = declarator;
if (id.type === 'Identifier') { if (id.type === 'Identifier') {
const value = init const value = init
? this.code.slice(id.start, init.end) ? this.code.slice(id.start, init.end)
: this.code.slice(id.start, id.end); : this.code.slice(id.start, id.end);
if (combining) { if (combining) {
replacement += `, ${value}`; code.overwrite(c, id.start, ', ');
} else { } else {
replacement += `${kind} { ${value}`; code.appendLeft(id.start, '{ ');
combining = true; combining = true;
} }
} else { } else {
throw new Error('TODO destructured declarations'); throw new Error('TODO destructured declarations');
} }
c = declarator.end;
}); });
}); });
if (combining) { 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({ unsorted_reactive_declarations.push({
assignees, assignees,
dependencies, dependencies,
node, node,
snippet: node.body.type === 'BlockStatement' snippet: node.body.type === 'BlockStatement'
? `[✂${node.body.start}-${node.end}✂]` ? `[✂${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 flattenReference from '../../../utils/flattenReference';
import { createScopes, Scope } from '../../../utils/annotateWithScopes'; import { createScopes, Scope } from '../../../utils/annotateWithScopes';
import { Node } from '../../../interfaces'; import { Node } from '../../../interfaces';
import addToSet from '../../../utils/addToSet';
import globalWhitelist from '../../../utils/globalWhitelist'; import globalWhitelist from '../../../utils/globalWhitelist';
import deindent from '../../../utils/deindent'; import deindent from '../../../utils/deindent';
import Wrapper from '../../render-dom/wrappers/shared/Wrapper'; import Wrapper from '../../render-dom/wrappers/shared/Wrapper';
import sanitize from '../../../utils/sanitize'; import sanitize from '../../../utils/sanitize';
import TemplateScope from './TemplateScope'; import TemplateScope from './TemplateScope';
import getObject from '../../../utils/getObject';
const binaryOperators: Record<string, number> = { const binaryOperators: Record<string, number> = {
'**': 15, '**': 15,
@ -248,7 +248,7 @@ export default class Expression {
if (function_expression) { if (function_expression) {
if (node.type === 'AssignmentExpression') { if (node.type === 'AssignmentExpression') {
// TODO handle destructuring assignments // TODO handle destructuring assignments
const { name } = flattenReference(node.left); const { name } = getObject(node.left);
pending_assignments.add(name); pending_assignments.add(name);
} }
} else { } else {
@ -296,7 +296,7 @@ export default class Expression {
let body = code.slice(node.body.start, node.body.end).trim(); let body = code.slice(node.body.start, node.body.end).trim();
if (node.body.type !== 'BlockStatement') { if (node.body.type !== 'BlockStatement') {
if (pending_assignments.size > 0) { 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(); pending_assignments = new Set();
component.has_reactive_assignments = true; component.has_reactive_assignments = true;

@ -13,7 +13,7 @@ export default function dom(
component: Component, component: Component,
options: CompileOptions options: CompileOptions
) { ) {
const { name } = component; const { name, code } = component;
const renderer = new Renderer(component, options); const renderer = new Renderer(component, options);
const { block } = renderer; const { block } = renderer;
@ -153,27 +153,63 @@ export default function dom(
let scope = component.instance_scope; let scope = component.instance_scope;
let map = component.instance_scope_map; let map = component.instance_scope_map;
let pending_assignments = new Set();
walk(component.instance_script.content, { walk(component.instance_script.content, {
enter: (node, parent) => { enter: (node, parent) => {
if (map.has(node)) { if (map.has(node)) {
scope = map.get(node); scope = map.get(node);
} }
},
leave(node) {
if (map.has(node)) {
scope = scope.parent;
}
if (node.type === 'AssignmentExpression') { if (node.type === 'AssignmentExpression') {
const { name } = getObject(node.left); const { name } = getObject(node.left);
if (scope.findOwner(name) === component.instance_scope) { 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 (pending_assignments.size > 0) {
if (map.has(node)) { if (node.type === 'ArrowFunctionExpression') {
scope = scope.parent; 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']; const args = ['$$self'];
@ -237,8 +273,7 @@ export default function dom(
${component.reactive_declarations.length > 0 && deindent` ${component.reactive_declarations.length > 0 && deindent`
$$self.$$.update = ($$dirty = { ${Array.from(all_reactive_dependencies).map(n => `${n}: 1`).join(', ')} }) => { $$self.$$.update = ($$dirty = { ${Array.from(all_reactive_dependencies).map(n => `${n}: 1`).join(', ')} }) => {
${component.reactive_declarations.map(d => deindent` ${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 MagicString from 'magic-string';
import { Node } from '../interfaces'; import { Node } from '../interfaces';
import { walk } from 'estree-walker'; import { walk } from 'estree-walker';
import repeat from './repeat';
export function remove_indentation(code: MagicString, node: Node) { export function remove_indentation(code: MagicString, node: Node) {
const indent = code.getIndentString(); const indent = code.getIndentString();
@ -26,4 +27,31 @@ export function remove_indentation(code: MagicString, node: Node) {
code.remove(index, index + indent.length); 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 }) => { $$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>', html: '<p>50</p>',
test({ assert, component, target }) { test({ assert, component, target }) {
console.group('range [50,100]');
component.range = [50, 100]; component.range = [50, 100];
assert.htmlEqual(target.innerHTML, '<p>75</p>'); assert.htmlEqual(target.innerHTML, '<p>75</p>');
console.groupEnd();
component.range = [50, 60]; component.range = [50, 60];
assert.htmlEqual(target.innerHTML, '<p>55</p>'); assert.htmlEqual(target.innerHTML, '<p>55</p>');

Loading…
Cancel
Save