From 5c1235aca3c4577bc2892d135a8da307a5fb9aee Mon Sep 17 00:00:00 2001 From: J Delaney Date: Sun, 24 Jan 2021 15:38:33 -0800 Subject: [PATCH 1/5] Don't create class update functions when dependencies aren't reactive --- .../render_dom/wrappers/Element/index.ts | 11 +- .../reactive-class-optimized/expected.js | 113 ++++++++++++++++++ .../reactive-class-optimized/input.svelte | 24 ++++ 3 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 test/js/samples/reactive-class-optimized/expected.js create mode 100644 test/js/samples/reactive-class-optimized/input.svelte diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts index 269edcfca86d..0acb89dd5848 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/index.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts @@ -26,6 +26,7 @@ import Action from '../../../nodes/Action'; import MustacheTagWrapper from '../MustacheTag'; import RawMustacheTagWrapper from '../RawMustacheTag'; import create_slot_block from './create_slot_block'; +import is_dynamic from '../shared/is_dynamic'; interface BindingGroup { events: string[]; @@ -898,10 +899,18 @@ export default class ElementWrapper extends Wrapper { const all_dependencies = this.class_dependencies.concat(...dependencies); const condition = block.renderer.dirty(all_dependencies); - block.chunks.update.push(b` + // If all of the dependencies are non-dynamic (don't get updated) then there is no reason + // to add an updater for this. + const any_dynamic_dependencies = all_dependencies.some((dep) => { + const v = this.renderer.component.var_lookup.get(dep); + return !v || is_dynamic(v); + }); + if (any_dynamic_dependencies) { + block.chunks.update.push(b` if (${condition}) { ${updater} }`); + } } }); } diff --git a/test/js/samples/reactive-class-optimized/expected.js b/test/js/samples/reactive-class-optimized/expected.js new file mode 100644 index 000000000000..ad6063e6ce42 --- /dev/null +++ b/test/js/samples/reactive-class-optimized/expected.js @@ -0,0 +1,113 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponent, + detach, + element, + init, + insert, + noop, + safe_not_equal, + space, + toggle_class +} from "svelte/internal"; + +function create_fragment(ctx) { + let div0; + let t0; + let div1; + let t1; + let div2; + let t2; + let div3; + let t3; + let div4; + let t4; + let div5; + + return { + c() { + div0 = element("div"); + t0 = space(); + div1 = element("div"); + t1 = space(); + div2 = element("div"); + t2 = space(); + div3 = element("div"); + t3 = space(); + div4 = element("div"); + t4 = space(); + div5 = element("div"); + toggle_class(div0, "update1", reactiveModuleVar); + toggle_class(div1, "update2", /*reactiveConst*/ ctx[0].x); + toggle_class(div2, "update3", nonReactiveGlobal && /*reactiveConst*/ ctx[0].x); + toggle_class(div3, "static1", nonReactiveModuleVar); + toggle_class(div4, "static1", nonReactiveGlobal); + toggle_class(div5, "static1", nonReactiveModuleVar && nonReactiveGlobal); + }, + m(target, anchor) { + insert(target, div0, anchor); + insert(target, t0, anchor); + insert(target, div1, anchor); + insert(target, t1, anchor); + insert(target, div2, anchor); + insert(target, t2, anchor); + insert(target, div3, anchor); + insert(target, t3, anchor); + insert(target, div4, anchor); + insert(target, t4, anchor); + insert(target, div5, anchor); + }, + p(ctx, [dirty]) { + if (dirty & /*reactiveModuleVar*/ 0) { + toggle_class(div0, "update1", reactiveModuleVar); + } + + if (dirty & /*reactiveConst*/ 1) { + toggle_class(div1, "update2", /*reactiveConst*/ ctx[0].x); + } + + if (dirty & /*nonReactiveGlobal, reactiveConst*/ 1) { + toggle_class(div2, "update3", nonReactiveGlobal && /*reactiveConst*/ ctx[0].x); + } + }, + i: noop, + o: noop, + d(detaching) { + if (detaching) detach(div0); + if (detaching) detach(t0); + if (detaching) detach(div1); + if (detaching) detach(t1); + if (detaching) detach(div2); + if (detaching) detach(t2); + if (detaching) detach(div3); + if (detaching) detach(t3); + if (detaching) detach(div4); + if (detaching) detach(t4); + if (detaching) detach(div5); + } + }; +} + +let nonReactiveModuleVar = Math.random(); +let reactiveModuleVar = Math.random(); + +function instance($$self, $$props, $$invalidate) { + nonReactiveGlobal = Math.random(); + const reactiveConst = { x: Math.random() }; + reactiveModuleVar += 1; + + if (Math.random()) { + reactiveConst.x += 1; + } + + return [reactiveConst]; +} + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, instance, create_fragment, safe_not_equal, {}); + } +} + +export default Component; diff --git a/test/js/samples/reactive-class-optimized/input.svelte b/test/js/samples/reactive-class-optimized/input.svelte new file mode 100644 index 000000000000..597314ed9461 --- /dev/null +++ b/test/js/samples/reactive-class-optimized/input.svelte @@ -0,0 +1,24 @@ + + + + + +
+
+
+ + +
+
+
From 4fd93a1094e361175877616e66a566c272072315 Mon Sep 17 00:00:00 2001 From: J Delaney Date: Mon, 25 Jan 2021 19:27:45 -0800 Subject: [PATCH 2/5] Better variable name --- src/compiler/compile/render_dom/wrappers/Element/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts index 0acb89dd5848..3defa4312af1 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/index.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts @@ -902,8 +902,8 @@ export default class ElementWrapper extends Wrapper { // If all of the dependencies are non-dynamic (don't get updated) then there is no reason // to add an updater for this. const any_dynamic_dependencies = all_dependencies.some((dep) => { - const v = this.renderer.component.var_lookup.get(dep); - return !v || is_dynamic(v); + const variable = this.renderer.component.var_lookup.get(dep); + return !variable || is_dynamic(variable); }); if (any_dynamic_dependencies) { block.chunks.update.push(b` From fd20fd5c4590c3672fbdb5d11ceb8b0a28697720 Mon Sep 17 00:00:00 2001 From: J Delaney Date: Tue, 26 Jan 2021 20:21:49 -0800 Subject: [PATCH 3/5] Add test for store val and exported unreactive val --- .../reactive-class-optimized/expected.js | 62 +++++++++++++++++-- .../reactive-class-optimized/input.svelte | 11 +++- .../samples/reactive-class-optimized/store.js | 4 ++ 3 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 test/js/samples/reactive-class-optimized/store.js diff --git a/test/js/samples/reactive-class-optimized/expected.js b/test/js/samples/reactive-class-optimized/expected.js index ad6063e6ce42..293249fd6214 100644 --- a/test/js/samples/reactive-class-optimized/expected.js +++ b/test/js/samples/reactive-class-optimized/expected.js @@ -1,6 +1,7 @@ /* generated by Svelte vX.Y.Z */ import { SvelteComponent, + component_subscribe, detach, element, init, @@ -8,9 +9,12 @@ import { noop, safe_not_equal, space, + subscribe, toggle_class } from "svelte/internal"; +import { reactiveStoreVal, unreactiveExport } from "./store"; + function create_fragment(ctx) { let div0; let t0; @@ -23,6 +27,12 @@ function create_fragment(ctx) { let div4; let t4; let div5; + let t5; + let div6; + let t6; + let div7; + let t7; + let div8; return { c() { @@ -37,12 +47,21 @@ function create_fragment(ctx) { div4 = element("div"); t4 = space(); div5 = element("div"); + t5 = space(); + div6 = element("div"); + t6 = space(); + div7 = element("div"); + t7 = space(); + div8 = element("div"); toggle_class(div0, "update1", reactiveModuleVar); toggle_class(div1, "update2", /*reactiveConst*/ ctx[0].x); toggle_class(div2, "update3", nonReactiveGlobal && /*reactiveConst*/ ctx[0].x); - toggle_class(div3, "static1", nonReactiveModuleVar); - toggle_class(div4, "static1", nonReactiveGlobal); - toggle_class(div5, "static1", nonReactiveModuleVar && nonReactiveGlobal); + toggle_class(div3, "update4", /*$reactiveStoreVal*/ ctx[2]); + toggle_class(div4, "update5", /*$reactiveDeclaration*/ ctx[3]); + toggle_class(div5, "static1", nonReactiveModuleVar); + toggle_class(div6, "static2", nonReactiveGlobal); + toggle_class(div7, "static3", nonReactiveModuleVar && nonReactiveGlobal); + toggle_class(div8, "static4", unreactiveExport); }, m(target, anchor) { insert(target, div0, anchor); @@ -56,6 +75,12 @@ function create_fragment(ctx) { insert(target, div4, anchor); insert(target, t4, anchor); insert(target, div5, anchor); + insert(target, t5, anchor); + insert(target, div6, anchor); + insert(target, t6, anchor); + insert(target, div7, anchor); + insert(target, t7, anchor); + insert(target, div8, anchor); }, p(ctx, [dirty]) { if (dirty & /*reactiveModuleVar*/ 0) { @@ -69,6 +94,14 @@ function create_fragment(ctx) { if (dirty & /*nonReactiveGlobal, reactiveConst*/ 1) { toggle_class(div2, "update3", nonReactiveGlobal && /*reactiveConst*/ ctx[0].x); } + + if (dirty & /*$reactiveStoreVal*/ 4) { + toggle_class(div3, "update4", /*$reactiveStoreVal*/ ctx[2]); + } + + if (dirty & /*$reactiveDeclaration*/ 8) { + toggle_class(div4, "update5", /*$reactiveDeclaration*/ ctx[3]); + } }, i: noop, o: noop, @@ -84,6 +117,12 @@ function create_fragment(ctx) { if (detaching) detach(div4); if (detaching) detach(t4); if (detaching) detach(div5); + if (detaching) detach(t5); + if (detaching) detach(div6); + if (detaching) detach(t6); + if (detaching) detach(div7); + if (detaching) detach(t7); + if (detaching) detach(div8); } }; } @@ -92,6 +131,15 @@ let nonReactiveModuleVar = Math.random(); let reactiveModuleVar = Math.random(); function instance($$self, $$props, $$invalidate) { + let reactiveDeclaration; + let $reactiveStoreVal; + + let $reactiveDeclaration, + $$unsubscribe_reactiveDeclaration = noop, + $$subscribe_reactiveDeclaration = () => ($$unsubscribe_reactiveDeclaration(), $$unsubscribe_reactiveDeclaration = subscribe(reactiveDeclaration, $$value => $$invalidate(3, $reactiveDeclaration = $$value)), reactiveDeclaration); + + component_subscribe($$self, reactiveStoreVal, $$value => $$invalidate(2, $reactiveStoreVal = $$value)); + $$self.$$.on_destroy.push(() => $$unsubscribe_reactiveDeclaration()); nonReactiveGlobal = Math.random(); const reactiveConst = { x: Math.random() }; reactiveModuleVar += 1; @@ -100,7 +148,13 @@ function instance($$self, $$props, $$invalidate) { reactiveConst.x += 1; } - return [reactiveConst]; + $$self.$$.update = () => { + if ($$self.$$.dirty & /*reactiveModuleVar*/ 0) { + $: $$subscribe_reactiveDeclaration($$invalidate(1, reactiveDeclaration = reactiveModuleVar * 2)); + } + }; + + return [reactiveConst, reactiveDeclaration, $reactiveStoreVal, $reactiveDeclaration]; } class Component extends SvelteComponent { diff --git a/test/js/samples/reactive-class-optimized/input.svelte b/test/js/samples/reactive-class-optimized/input.svelte index 597314ed9461..f10fd11290e8 100644 --- a/test/js/samples/reactive-class-optimized/input.svelte +++ b/test/js/samples/reactive-class-optimized/input.svelte @@ -4,9 +4,13 @@