Svelte: Loop protect guard issue in REPL

Created on 2 Dec 2019  路  5Comments  路  Source: sveltejs/svelte

Describe the bug
The bind this example doesn't work in 3.16.0 (it does in 3.15.0)

To Reproduce (minimal example)

<script>
  let node;
  (function () {
    while(false) ;
  }());
</script>
<div bind:this={node}></div>

Produces guard is not defined.
See REPL (it does work on 3.15.0).
Note that the bind:this is actually needed to trigger this. It's probably a visibility issue with the guard and an anonymous function?

bug

Most helpful comment

Fixed in 3.16.1 - https://svelte.dev/repl/bind-this?version=3.16.1 - and will work again on the main examples page once unpkg's cache is refreshed.

All 5 comments

In the generated code:

    function instance($$self, $$props, $$invalidate) {
        let node;

        (function () {
            const guard = loop_guard(100);

            while (false) {

                guard();
            }
        })();

        function div_binding($$value) {
            binding_callbacks[$$value ? "unshift" : "push"](() => {
                $$invalidate(0, node = $$value);
            });
        }

        $$self.$capture_state = () => {
            return {};
        };

        $$self.$inject_state = $$props => {
            if ("node" in $$props) $$invalidate(0, node = $$props.node);
        };

        return [node, guard, div_binding];
    }

guard is being included in the ctx array, and it should not. It seems to happen with any kind of bind:, not just bind:this.

@Conduitry: I couldn't get a setup outside of the REPL that generated a guard, what's the trick? (I tried with svelte({dev: true}))

You also need to pass a non-zero loopGuardTimeout option to the compiler.

The problem seems to be the this.add_var() call in Component#loop_protect(). We don't want to use add_var() because that adds it to the context, and the guard function should not be part of the component's context. Simply removing that, though, breaks the loop-protect tests - there's a failure in Component#rewrite_props() because we can't find the guard variable in var_lookup so something else needs to happen. Why the walker is even getting to this node, which shouldn't be in the top-level scope, I do not know.

Edit: Ohhhh. In the example in this issue, it's in a deeper scope. But in the loop-protect test, the loop is at the top level. Duh. I think we can just wrap the whole loop in a { } scope so that the guard variable doesn't leak out.

cc @tanhauhau

Fixed in 3.16.1 - https://svelte.dev/repl/bind-this?version=3.16.1 - and will work again on the main examples page once unpkg's cache is refreshed.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ricardobeat picture ricardobeat  路  3Comments

1u0n picture 1u0n  路  3Comments

lnryan picture lnryan  路  3Comments

Rich-Harris picture Rich-Harris  路  3Comments

davidcallanan picture davidcallanan  路  3Comments