qwik icon indicating copy to clipboard operation
qwik copied to clipboard

Variables are not correctly hoisted in Qwik's lexical scope

Open dario-piotrowicz opened this issue 3 years ago • 7 comments

Qwik Version

0.11.1

Which component is affected?

Qwik Optimizer (rust) (I think)

Expected Behaviour

In javascripts variables get hoisted, so in my components I would expect to be able to access variables in any part of the code as long as they belong to the same scope, see this simple react example.

There the decreaseCounter function can access the counter (and also the setCounter) variable because it is being hoisted.

Actual Behaviour

It seems like Qwik doesn't apply such hoisting causing runtime errors, for example see this analogous qwik example

Here the decreaseCounter function fails to recognize the state reference causing a runtime error: Screenshot 2022-10-19 at 22 11 12

Additional Information

I am not sure if this is a bug or a feature request, sorry if I picked the wrong option for the issue

Anyways I think that javascript developers are very used and familiar with the hoisting of variables and that if possible Qwik should provide the same sort of behaviour.

This also generates contraints/hinderances to the developers which are forced to order their code in a particular way in order to have it correctly working.

dario-piotrowicz avatar Oct 19 '22 21:10 dario-piotrowicz

The code you passes it is using the variable before it's declared / initialized

manucorporat avatar Oct 20 '22 15:10 manucorporat

Hi @manucorporat , the variable is being referenced before it's declaration/initialization, but it is not being used right away (so it's not in the temporal dead zone) so I would expect it to being hoisted in the same way standard javascript does.

Please check out the react example to see what I mean, there the counter variable is also being referenced before it's declaration, but there everything works totally fine.

And I find this a to be a valuable behaviour which allows me to order my code in any logical way I want instead of having to carefully move code around so that the order follows the various code dependencies.

dario-piotrowicz avatar Oct 20 '22 16:10 dario-piotrowicz

I am not sure we will be able to support this, since there is an actual evaluation of the passed variable, there is some transformation involved here to allow the serialization of closures, i dont think how this could possible work without having the optimizer to reorder your code, which can cause other issues

manucorporat avatar Oct 20 '22 19:10 manucorporat

I see, that's too bad 😢

Thank you very much for the explanation 🙂

Let me know if we should just close this issue, keep it for reference or also add something regarding this in the docs.

dario-piotrowicz avatar Oct 20 '22 20:10 dario-piotrowicz

yeah, i will keep it open, i think it's good to document this

manucorporat avatar Oct 20 '22 20:10 manucorporat

@manucorporat - one option would be to move the dependency array into a function that is called later. I.e. instead of:

const increaseCounter = qrlDEV(
  () => import('./app_component_increasecounter_ho3zdspwjzs.js'),
  "App_component_increaseCounter_Ho3zDspwJzs",
  {...},
  [ state ]
);

it could be

const increaseCounter = qrlDEV(
  () => import('./app_component_increasecounter_ho3zdspwjzs.js'),
  "App_component_increaseCounter_Ho3zDspwJzs",
  {...},
  () => [ state ]
);

Note the last parameter.

petebacondarwin avatar Oct 20 '22 20:10 petebacondarwin

@manucorporat - was this closed as resolved or not planned?

petebacondarwin avatar Dec 04 '22 15:12 petebacondarwin