node icon indicating copy to clipboard operation
node copied to clipboard

Lexical variable declarations (`let`, `const`) unusable in repl if error thrown during declaration/first assignment

Open polybuildr opened this issue 8 years ago • 26 comments

  • Version: v.6.3.1
  • Platform: Linux (Ubuntu 14.04)
  • Subsystem: repl (I think)
let s = Set();

gives TypeError: Constructor Set requires 'new'.

However, after this:

s

gives ReferenceError: s is not defined

and

let s = new Set();

gives TypeError: Identifier 's' has already been declared.

I'm not sure whether this is a real bug or it's expected behaviour, but it sure does seem unusual that s becomes unusable from this point in in the repl.

This isn't a problem when running node on a js file because the TypeError simply terminates execution.

polybuildr avatar Aug 28 '16 12:08 polybuildr

Different with var:

> var  s = Set();
TypeError: Constructor Set requires 'new'
> s
undefined
> var  s = new Set();
undefined
> s
Set {}

vsemozhetbyt avatar Aug 28 '16 12:08 vsemozhetbyt

Yep, works fine with var.

polybuildr avatar Aug 28 '16 12:08 polybuildr

Here is simplified test case:

var vm = require('vm');

try {
  vm.runInThisContext('let x = f');
} catch (e) {}

vm.runInThisContext('x = 1');

vkurchatkin avatar Aug 28 '16 12:08 vkurchatkin

This is very déjà-vu-ish to me, although I can’t find another issue for this bug… /cc @nodejs/v8?

addaleax avatar Aug 28 '16 12:08 addaleax

This error also occurs in the Chrome browser, so it's probably a v8 thing and not a Node thing. Sorry for reporting it in the wrong place.

polybuildr avatar Aug 28 '16 12:08 polybuildr

Where should I report this considering that it's not specific to node's repl?

polybuildr avatar Aug 28 '16 14:08 polybuildr

I wouldn't be surprised if this was how the spec worked.

In general, you'll have a better time using var for variables in the repl.

Fishrock123 avatar Aug 28 '16 14:08 Fishrock123

@polybuildr You can report it over at https://bugs.chromium.org/p/v8/issues/list. It looks spec compliant to me (the binding for s is never fully constructed and stays in the TDZ) but perhaps the error messages can be improved.

bnoordhuis avatar Aug 29 '16 04:08 bnoordhuis

This is per spec: https://esdiscuss.org/topic/take-let-variable-out-of-temporal-dead-zone

Slayer95 avatar Aug 29 '16 04:08 Slayer95

@bnoordhuis, @Slayer95, it does look spec-compliant, so I'm going to close this issue. However, that esdiscuss topic pointed me to something interesting that the Firefox Devtools console does and might be worth a shot.

For any such unresolved bindings (at least in the DevTools), Firefox steps in and turns them into undefined. So a redeclaration with let doesn't work, but simply s = 5 works from that point on. If anyone would like to consider doing this for the repl, feel free to reopen the issue.

polybuildr avatar Aug 29 '16 04:08 polybuildr

Not working all variations

> rangeArray = nj.arange(6,12)
ReferenceError: rangeArray is not defined
> rangeArray = new nj.arange(6,12)
ReferenceError: rangeArray is not defined
> var rangeArray = new nj.arange(6,12)
SyntaxError: Identifier 'rangeArray' has already been declared
> let rangeArray = new nj.arange(6,12)
SyntaxError: Identifier 'rangeArray' has already been declared
> let rangeArray = nj.arange(6,12)
SyntaxError: Identifier 'rangeArray' has already been declared
> var rangeArray = nj.arange(6,12)
SyntaxError: Identifier 'rangeArray' has already been declared

MasterJames avatar Jun 09 '18 08:06 MasterJames

re-opening, per https://github.com/nodejs/node/issues/32288#issuecomment-599270508, https://github.com/nodejs/node/issues/32288#issuecomment-599300785 and https://github.com/nodejs/node/issues/32288#issuecomment-599333938

gireeshpunathil avatar Mar 16 '20 04:03 gireeshpunathil

This is fixable pending migration to v8 repl mode pending v8:10539

devsnek avatar May 19 '20 03:05 devsnek

Just trying to make this more searchable :innocent:

devsnek avatar Mar 01 '21 16:03 devsnek

Wait, 5 year old issues are still open? 😨

TheRamann avatar Mar 04 '21 17:03 TheRamann

+1 this behavior is unpleasant. After making a typo, the only way to proceed is to start over if e.g. you were setting up to paste in a line of code.

TiraO avatar Dec 01 '21 17:12 TiraO

This is fixable pending migration to v8 repl mode pending v8:10539

@devsnek is this still blocked by that issue? It was closed as wontfix.

mcollina avatar Dec 29 '21 14:12 mcollina

@mcollina yeah we could implement repl using runtime.evaluate now, just no one has gotten around to it.

devsnek avatar Dec 29 '21 15:12 devsnek

@devsnek So this is a full reimplementation of the repl?

ShogunPanda avatar Dec 29 '21 15:12 ShogunPanda

I don't think it requires complete reimplementation but it will definitely require some work

devsnek avatar Dec 29 '21 16:12 devsnek

I see.

Once I get some bandwidth I might take a look at this. This looks like and interesting challenge.

ShogunPanda avatar Dec 30 '21 08:12 ShogunPanda

nudge

gregfenton avatar Apr 09 '23 15:04 gregfenton

Use the new keyword when creating a new Set instance:

let s = new Set();
s.add("OldestIssueOnNodeJS"); 
console.log(s);

ankit142 avatar Feb 15 '24 19:02 ankit142

@ankit142 The issue as posted isn't about fixing the code in the example provided. There are many examples that could be provided.

Essentially this issue is that calling let x = <some_code_that_throws_an_error> leads to a situation where you cannot use x and you cannot redeclare let x. So for the remainder of the REPL session, the symbol x is unusable.

gregfenton avatar Feb 15 '24 19:02 gregfenton

To address this issue, you can manually reset the variable by using the delete keyword to remove it from the global scope.

let x;

try {
    x = <some_code_that_throws_an_error>;
} catch (error) {
    console.error('Error:', error);
    delete global.x; // Reset variable x
}

// Now you can safely redeclare x or use it again
x = <valid_code>;

ankit142 avatar Feb 15 '24 19:02 ankit142

Again, the issue is not with "fixing the code". It is a bad behaviour of the REPL. You don't know that the code you just typed will hit an error. It does. The symbol you tried to use (x) is now unusable for the remainder of the REPL.

This isn't about "writing good code" vs. "writing bad code". This is about the user experience using the REPL when playing around with code.

  • Why would someone do this?
    • developer trying stuff -- copy/paste instructions from somewhere or whatever
  • Why not just use another symbol once x is unusable?
    • other code coming (think copy/paste instructions) leverages that same symbol; the user would be forced to either stop/restart the REPL or refactor the code they are about to paste
      • both of the workarounds above are not a good/healthy user experience

gregfenton avatar Feb 15 '24 23:02 gregfenton

FWIW @1Git2Clone has a issue with chromium at https://issues.chromium.org/issues/345248266.

redyetidev avatar Jun 05 '24 20:06 redyetidev