Skip to content

use-directives are called multiple times when elements inside a keyed block are reordered #4693

Closed
@christianheine

Description

@christianheine

Description of the bug

  • When attaching "use" directives inside a keyed block, they are called again (without being destroyed) if the elements of the block are reordered.

To Reproduce

Expected behavior

  • Directives should be called only once when the component is mounted.
  • Alternatively, if the element is remounted, "destroy" should be called beforehand (e.g. to free previously created resources).

Information about the Svelte project:

  • Svelte version: 3.20.1 (bundled with Rollup)
  • Browser: (latest) Chrome on MacOS

Severity

  • Moderate to serious, since the application we are building is relying heavily on use-directives to leverage modularity. We noticed the issue when event listeners were mounted multiple times (leading to a memory leak as well as unexpected behavior and inconsistent internal state).

Additional context

  • The issue only happens with keyed each blocks.

Previous analysis

  • Here is where things break:
/* src/ListItem.svelte generated by Svelte v3.20.1 */
    function create_fragment(ctx) {
    	let div;
    	let t;
    	let directive_action;
    	let dispose;

    	return {
    		c() {
    			div = element("div");
    			t = text(/*id*/ ctx[0]);
    		},
    		m(target, anchor, remount) {
    			insert(target, div, anchor);
    			append(div, t);
    			if (remount) dispose(); // <-- remount is undefined
    			dispose = action_destroyer(directive_action = directive.call(null, div, { id: /*id*/ ctx[0] }));
    		},

It seems that remounting was considered, but the information (that the current operation is indeed a remount) gets lost due to an additional block in between. It's a bit hard to describe verbally. So here are the relevant parts of a debugger session (from the same app as in the example REPL):

image

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions