Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Component fails to mount with error Uncaught TypeError: Cannot read properties of undefined (reading 'context') #7847

Closed
sohaibalam67 opened this issue Sep 9, 2022 · 8 comments

Comments

@sohaibalam67
Copy link

sohaibalam67 commented Sep 9, 2022

Describe the bug

Note: Issue only reproducible with prod build

Bug introduced in version: 3.40.0

Trying to mount first component with a target that is not present in DOM. So, this should fail to mount and throw an error (and this behaviour is correct).
Ex: An element with id #first-field is not present in the DOM. And we try to mount the component like this:

new FirstComponent({target: document.querySelector('#first-field')});

this fails with error Uncaught TypeError: Cannot read properties of undefined (reading '$$') (this is correct and expected)

But when we try to mount component with a valid target, right after the first component, this second component fails to mount too.
Ex: An element with id #second-field is present in the DOM. And we try to mount the component like this:

new SecondComponent({target: document.querySelector('#second-field')});

this fails with error This fails to load too with error Uncaught TypeError: Cannot read properties of undefined (reading 'context') (this is not expected)

Reproduction

Clone: https://github.com/sohaibalam67/svelte-bug-component-mount

  1. run npm run build && npm run start

  2. Click on 'mount component without target' button
    this fails with error Uncaught TypeError: Cannot read properties of undefined (reading '$$')

  3. Click on 'mount component with target' button
    This fails to load too with error Uncaught TypeError: Cannot read properties of undefined (reading 'context')

The issue is only reproducible in prod build and not in dev build

Logs

index.mjs:1887 Uncaught TypeError: Cannot read properties of undefined (reading '$$')
    at T (index.mjs:1887:50)
    at new N (First.svelte:1:29)
    at HTMLButtonElement.<anonymous> (App.svelte:22:40)
T @ index.mjs:1887
N @ First.svelte:1
(anonymous) @ App.svelte:22
index.mjs:1882 Uncaught TypeError: Cannot read properties of undefined (reading 'context')
    at T (index.mjs:1882:85)
    at new j (Second.svelte:1:25)
    at HTMLButtonElement.<anonymous> (App.svelte:6:45)
T @ index.mjs:1882
j @ Second.svelte:1
(anonymous) @ App.svelte:6

System Info

System:
    OS: macOS 12.5.1
    CPU: (8) x64 Intel(R) Core(TM) i5-1038NG7 CPU @ 2.00GHz
    Memory: 76.25 MB / 16.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 16.13.1 - /var/folders/r9/8gk4cg212kq6sdl5qhf2nvlc0000gq/T/fnm_multishells/47526_1662704664893/bin/node
    Yarn: 1.22.17 - /var/folders/r9/8gk4cg212kq6sdl5qhf2nvlc0000gq/T/fnm_multishells/47526_1662704664893/bin/yarn
    npm: 8.1.2 - /var/folders/r9/8gk4cg212kq6sdl5qhf2nvlc0000gq/T/fnm_multishells/47526_1662704664893/bin/npm
  Browsers:
    Brave Browser: 105.1.43.89
    Chrome: 104.0.5112.101
    Firefox: 103.0.1
    Safari: 15.6.1
    Safari Technology Preview: 16.0
  npmPackages:
    rollup: ^2.3.4 => 2.79.0 
    svelte: ^3.50.1 => 3.50.1

Severity

blocking an upgrade

@sohaibalam67
Copy link
Author

sohaibalam67 commented Sep 9, 2022

related: #6584, #6871

@sohaibalam67
Copy link
Author

The reason that it is working fine in dev mode is because the program is terminating here for the FirstComponent:

throw new Error("'target' is a required option");

But in prod build, this is removed and the FirstComponent init is attempted which sets the current_component to FirstComponent here:

set_current_component(component);

Next time when SecondComponent is initialised, parent_component is already set to FirstComponent here:

const parent_component = current_component;

But the $$ property wasn't set on FirstComponent because it failed mid-way.
So for SecondComponent, parent_component exists, but doesn't contain the $$ property, that breaks here:

context: new Map(options.context || (parent_component ? parent_component.$$.context : [])),

@oyzhen
Copy link

oyzhen commented Dec 8, 2022

Any progress or workaround?

@baseballyama
Copy link
Member

This is intentional.
dev mode checks many possible programming errors but first priority of production mode is performance.
And we can simply do like this.

function mountFirstComponent() {
  const target = document.querySelector('#first-field');
  if (!target) throw Error('target is not exists!')
  new First({target: document.querySelector('#first-field')}); 
}

@Abban-Fahim
Copy link

@baseballyama How do i implement you solution into a bog-standard svelte app cuz im also getting this error. Here's the entry point main.js file:

import './style.css'
import App from './App.svelte'

const app = new App({
    target: document.getElementById('app'),
})

export default app 

Note that I'm not using ANY extra libraries, just svelte, vite and vite-plugin-svelte.

@baseballyama
Copy link
Member

I think HTML doesn't have #app element.
But you need to provide REPL for getting a proper answer because we can not know what happens from your information.

@sohaibalam67
Copy link
Author

sohaibalam67 commented Jun 5, 2023

This is intentional. dev mode checks many possible programming errors but first priority of production mode is performance. And we can simply do like this.

function mountFirstComponent() {
  const target = document.querySelector('#first-field');
  if (!target) throw Error('target is not exists!')
  new First({target: document.querySelector('#first-field')}); 
}

Although this issue was closed from dev mode perspective, but the issue is present in prod build as well. In dev mode it early exits from the error, but in prod build it fails to mount the component and any component after that.

I believe this should be internally handled by svelte where it should not fail to mount the second component (even if target was present in the DOM) when first component fails to mount (because target was not present in DOM).

@lalilaloe
Copy link

For future reference, I got this error when enableSourcemap value was set to undefined in the following config:

    svelte({
      emitCss: false,
      compilerOptions: {
        dev: !production,
        enableSourcemap: process.env.DEV_MODE
      },

In this setup DEV_MODE was not present in .env, thus leading to this difficult to debug error. Silly me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants