sveltejs / svelte

web development for the rest of us
https://svelte.dev
MIT License
80.02k stars 4.26k forks source link

effects.js causes Fatal Error #14296

Open tk-90-github opened 4 days ago

tk-90-github commented 4 days ago

Describe the bug

Push to 'null' causes total crash of project.

The error causing line is at src/internal/client/reactivity/effect.js:270 context.l.r1.push(token);

Error message:

Uncaught (in promise) TypeError: Cannot read properties of null (reading 'r1')

Reproduction

In a seperate project, which I created by the template doesn't show that effect. Sorry, I'm not so deep into svelte-internals to know how this bug can be reproduced

External libs that caused this error: "svelte-fa" "svelte-file-dropzone"

I tried to add some icons with Fa in the basic example but it doesn't show the effect I face in production.

Logs

Uncaught (in promise) TypeError: Cannot read properties of null (reading 'r1')

System Info

System:
    OS: Windows 11 10.0.22631
    CPU: (20) x64 12th Gen Intel(R) Core(TM) i9-12900HK
    Memory: 6.86 GB / 31.68 GB
  Binaries:
    Node: 22.11.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.22 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 9.6.4 - C:\Program Files\nodejs\npm.CMD
    pnpm: 9.7.0 - ~\scoop\shims\pnpm.EXE
  Browsers:
    Edge: Chromium (130.0.2849.46)
    Internet Explorer: 11.0.22621.3527
  npmPackages:
    svelte: ^5.1.9 => 5.1.16
    webpack: ^5.96.1 => 5.96.1

Severity

blocking all usage of svelte

tk-90-github commented 4 days ago

I manually edit the node modules in my project and came up with following solution:

/**
 * Internal representation of `$: ..`
 * @param {() => any} deps
 * @param {() => void | (() => void)} fn
 */
export function legacy_pre_effect(deps, fn) {
    var context = /** @type {ComponentContextLegacy} */ (component_context);

    /** @type {{ effect: null | Effect, ran: boolean }} */
    var token = { effect: null, ran: false };

    if(context.l !=null &&context.l.r1 !=null ){
        context.l.r1.push(token);
    }

    token.effect = render_effect(() => {
        deps();

        // If this legacy pre effect has already run before the end of the reset, then
        // bail out to emulate the same behavior.
        if (token.ran) return;

        token.ran = true;

        if(context.l!=null && context.l.r2 !=null){
              set(context.l.r2, true);
        }
        untrack(fn);
    });
}

Edit: Watch out for the line set(context.l.r2, true); which was unprotected, too.

dummdidumm commented 4 days ago

Please provide a reproduction repository. You can use stackblitz or push a github repository.