From 5c1235aca3c4577bc2892d135a8da307a5fb9aee Mon Sep 17 00:00:00 2001 From: J Delaney Date: Sun, 24 Jan 2021 15:38:33 -0800 Subject: [PATCH] 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 269edcfca8..0acb89dd58 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 0000000000..ad6063e6ce --- /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 0000000000..597314ed94 --- /dev/null +++ b/test/js/samples/reactive-class-optimized/input.svelte @@ -0,0 +1,24 @@ + + + + + +
+
+
+ + +
+
+