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

const demoted to var #3680

Closed
alecmocatta opened this issue Sep 9, 2020 · 1 comment
Closed

const demoted to var #3680

alecmocatta opened this issue Sep 9, 2020 · 1 comment

Comments

@alecmocatta
Copy link

const variable declarations are sometimes demoted to var declarations. See for example:

window['foo'] = function () {
    const a = window['a'],
        b = window['b'];
    let c = window['c'];
    while (a < b[c]) c--;
    for (let i = 0; i < window['d'].length; i++) {}
};

which with compiler --compilation_level ADVANCED --language_in ECMASCRIPT_NEXT --strict_mode_input --language_out ECMASCRIPT_2017 --assume_function_wrapper --use_types_for_optimization compiles to:

'use strict';
window.foo = function() {
    var a = window.a;
    const c = window.b;
    let b = window.c;
    for (; a < c[b];) b--;
    for (a = 0; a < window.d.length; a++);
};

I'm not sure if this is ever incorrect, but this seems surprising? In this instance it's more characters, plus it's (slightly) increasing the work for the ultimate interpreter/compiler who'll now have to deduce that a is const rather than verifying it's const to perform optimisations. Admittedly that won't make a difference in this snippet but I noticed this in a hot loop in my code while profiling and trying to optimize.

@brad4d
Copy link
Contributor

brad4d commented Sep 10, 2020

What's happening here is due to an optimization called variable coalescing.
Basically, the compiler realizes that it can have fewer variables (and, thus variable declaration statements) by using a single variable to do what was done with multiple variables in the original code.

The compiler recognized that a was unused after the while loop and i was never used before it, so it combined them into one variable, which also ended up having the name a. Since the value of the variable must change, it couldn't be const anymore.

Why did the compiler use var, instead of let? There are a few reasons.

  1. The bulk of the compiler was written long before let and const existed. As a result a lot of the transformations it performs just always use var.
  2. We also favor using the oldest-possible feature in many of our transformations, because it avoids us having to make all of the optimizations smart enough to pay attention to what language features are allowed in the output.

It would be pretty bad if we transpiled away all of the instances of let only to have a newly-written optimization end up putting one back in. Sure we could check the language output level in every place where we create a variable declaration, but that's adding even more logic that could potentially break.

We did recently have to fix a case where putting in var actually broke the code.
If you find one of those, please file a new issue.

Thanks.

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

No branches or pull requests

2 participants