Skip to content

Commit

Permalink
feat no invalidate reactive vars if dependencies are all static
Browse files Browse the repository at this point in the history
  • Loading branch information
tanhauhau committed Dec 7, 2019
1 parent 6a4956b commit aaceaf9
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 5 deletions.
21 changes: 16 additions & 5 deletions src/compiler/compile/Component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { Node, ImportDeclaration, Identifier, Program, ExpressionStatement, Assi
import add_to_set from './utils/add_to_set';
import check_graph_for_cycles from './utils/check_graph_for_cycles';
import { print, x, b } from 'code-red';
import is_dynamic from './render_dom/wrappers/shared/is_dynamic';

interface ComponentOptions {
namespace?: string;
Expand Down Expand Up @@ -1144,9 +1145,9 @@ export default class Component {
if (node.type === 'LabeledStatement' && node.label.name === '$') {
this.reactive_declaration_nodes.add(node);

const assignees = new Set();
const assignees = new Set<string>();
const assignee_nodes = new Set();
const dependencies = new Set();
const dependencies = new Set<string>();

let scope = this.instance_scope;
const map = this.instance_scope_map;
Expand Down Expand Up @@ -1178,11 +1179,10 @@ export default class Component {
const owner = scope.find_owner(name);
const variable = component.var_lookup.get(name);
if (variable) variable.is_reactive_dependency = true;
const is_writable_or_mutated =
variable && (variable.writable || variable.mutated);

if (
(!owner || owner === component.instance_scope) &&
(name[0] === '$' || is_writable_or_mutated)
(name[0] === '$' || variable)
) {
dependencies.add(name);
}
Expand All @@ -1202,6 +1202,17 @@ export default class Component {
const { expression } = node.body as ExpressionStatement;
const declaration = expression && (expression as AssignmentExpression).left;

const is_dependency_static = Array.from(dependencies).every(dependency => dependency !== '$$props' && !is_dynamic(this.var_lookup.get(dependency)));

if (is_dependency_static) {
assignees.forEach(assignee => {
const variable = component.var_lookup.get(assignee);
if (variable) {
variable.is_reactive_static = true;
}
});
}

unsorted_reactive_declarations.push({
assignees,
dependencies,
Expand Down
1 change: 1 addition & 0 deletions src/compiler/compile/render_dom/invalidate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export function invalidate(renderer: Renderer, scope: Scope, node: Node, names:
!variable.hoistable &&
!variable.global &&
!variable.module &&
!variable.is_reactive_static &&
(
variable.referenced ||
variable.subscribable ||
Expand Down
1 change: 1 addition & 0 deletions src/compiler/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,5 @@ export interface Var {
hoistable?: boolean;
subscribable?: boolean;
is_reactive_dependency?: boolean;
is_reactive_static?: boolean;
}
60 changes: 60 additions & 0 deletions test/js/samples/reactive-values/expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/* generated by Svelte vX.Y.Z */
import {
SvelteComponent,
detach,
element,
init,
insert,
noop,
safe_not_equal,
set_data,
space,
text
} from "svelte/internal";

function create_fragment(ctx) {
let h1;
let t3;
let t4;

return {
c() {
h1 = element("h1");
h1.textContent = `Hello ${name}!`;
t3 = space();
t4 = text(/*foo*/ ctx[0]);
},
m(target, anchor) {
insert(target, h1, anchor);
insert(target, t3, anchor);
insert(target, t4, anchor);
},
p(ctx, [dirty]) {
if (dirty & /*foo*/ 1) set_data(t4, /*foo*/ ctx[0]);
},
i: noop,
o: noop,
d(detaching) {
if (detaching) detach(h1);
if (detaching) detach(t3);
if (detaching) detach(t4);
}
};
}

let name = "world";

function instance($$self) {
let foo;
$: foo = name + name;
return [foo];
}

class Component extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, create_fragment, safe_not_equal, {});
}
}

export default Component;
7 changes: 7 additions & 0 deletions test/js/samples/reactive-values/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script>
let name = 'world';
$: foo = name + name;
</script>

<h1>Hello {name}!</h1>
{foo}

0 comments on commit aaceaf9

Please sign in to comment.