svelte: 3.44.2 to 3.44.3 Max call stack exceeded

Describe the bug

After version bumping I getting Maximum call stack size exceeded at random components:

Reproduction

The project has ~200k lines, it is difficult to share some code. Normally it happens during conditional rendering when some variable got changed and something appears in the viewport.

Logs

Uncaught (in promise) RangeError: Maximum call stack size exceeded
    at he (client.a36456a7.js:1)
    at new v (more.1e4136df.js:1)
    at Array.Re (card.901134b9.js:1)
    at d (client.a36456a7.js:1)
    at ul (client.a36456a7.js:1)
    at he (client.a36456a7.js:1)
    at new dl (client.a36456a7.js:1)
    at Je (card.901134b9.js:1)
    at he (client.a36456a7.js:1)
    at new We (card.901134b9.js:1)

System Info

System:
    OS: Windows 10 10.0.22000
    CPU: (8) x64 Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
    Memory: 3.86 GB / 15.87 GB
  Binaries:
    Node: 14.16.1 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.10 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 6.14.12 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Spartan (44.22000.120.0), Chromium (96.0.1054.62)
    Internet Explorer: 11.0.22000.120
  npmPackages:
    rollup: ^2.61.1 => 2.61.1 
    svelte: ^3.44.3 => 3.44.3

Severity

blocking all usage of svelte

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 2
  • Comments: 23 (15 by maintainers)

Commits related to this issue

Most upvoted comments

@dummdidumm Many thanks for the help! Your PR really works for our case. This fixes a rather old issue where we are still using Svelte version 3.44.2.

@bluwy @Conduitry @rmunn Can we accept this PR as soon as possible? This will help us a lot. [fix] don’t run binding init unnecessarily #7981

I’m talking about the rollup.config.js inside the Svelte repo, not inside your repo where you use Svelte.

Hey,

So I do not know too much about the lack of this logic is essentially the cause of this error: https://github.com/sveltejs/svelte/pull/6920/files#diff-c6bed9ce5fe6451fdfb396f59ca220e54863ca568f7a9b43b08ff17e23b3db60L37-L38

I am able to replicate this if I load/unload a component multiple times over. I believe it’s just non-stop attempting to flush even if another flush is still in progress.

This is definitely a bug that is still occurring. Happy to help someone who knows a bit more about the logic here. cc. @rmunn


Edit: Could we can still safely bring back the if (flushing) return statement while maintaining the fix that was implemented? The rest of the logic still stays the same - it just doesn’t get invoked endlessly and does the same work.

@bluwy

@ruslan-khomiak created a reproduction

https://svelte.dev/repl/86b8b83f2e2b475e8e92aaa4df9c7da2?version=3.44.2 - everything is good https://svelte.dev/repl/86b8b83f2e2b475e8e92aaa4df9c7da2?version=3.44.3 - maximum call stack size exceeded error

Looks like the problem appeared after the merge of this PR: https://github.com/sveltejs/svelte/pull/6920/files

Let us know if this is sufficient.

@Conduitry @rmunn I still can’t reproduce this error in REPL. But I know for sure that the problem is in this PR #6920

I reverted locally all the changes that were in this PR and the bug stopped reproducing. Maybe this information will be useful.

@Prinzhorn can you please specify relative paths for files that need to be tested with flush?

The file you’ll need to test will be node_modules/svelte/internal/index.js, or possibly index.mjs (I’m not yet clear on which file gets used when). In either case, search for function flush() which should be about halfway through the file. It would be most helpful, I think, to add console.log calls at the beginning and end of the function, like so:

function flush() {
  const saved_component = current_component;
  // Add a call here
  console.log('flush() starting with saved component', saved_component, 'and flushidx is', flushidx);
  // ... rest of function ...
  set_current_component(saved_component);
  // Add a call here
  console.log('flush() ending, having restored saved component', saved_component, 'and flushidx is now', flushidx);
}

You’ll end up with a LOT of noise in the browser console that way, but the most valuable will be the final parts of the log right before the call stack size is exceeded. Being able to see whether the saved component is undefined, or a different component each time, or the same component each time, will tell us something. And being able to watch the value of flushidx as flush() reenters (or doesn’t reenter) will also be useful information.