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

repl: Failed assignment "blocks" further assignments to a variable name #6118

Closed
dodev opened this issue Apr 8, 2016 · 7 comments
Closed
Labels
repl Issues and PRs related to the REPL subsystem.

Comments

@dodev
Copy link
Contributor

dodev commented Apr 8, 2016

Hi!

On an assignment statement TypeError, using the same variable name is not possible due to either Reference or TypeError when trying to assign a value to a variable with that name.

Steps:

  1. Assign to a variable with statement which causes TypeError ((let|const|var) a = Math.PI())
  2. Try to assign to the same variable name using let|const|var OR try to use the variable;

Result:
The variable name is no longer available, because you get a TypeError: Identifier has already been declared OR ReferenceError: variable is not defined if you try to use the variable name

Expected Behavior:
The variable name to remain undeclared.

Sample Output:

> let c = 1;
undefined
> let a = c();
TypeError: c is not a function
    at repl:2:9
    at REPLServer.defaultEval (repl.js:269:27)
    at bound (domain.js:287:14)
    at REPLServer.runBound [as eval] (domain.js:300:12)
    at REPLServer.<anonymous> (repl.js:439:12)
    at emitOne (events.js:95:20)
    at REPLServer.emit (events.js:182:7)
    at REPLServer.Interface._onLine (readline.js:211:10)
    at REPLServer.Interface._line (readline.js:550:8)
    at REPLServer.Interface._ttyWrite (readline.js:827:14)
> let a = 1;
TypeError: Identifier 'a' has already been declared
    at repl:1:1
    at REPLServer.defaultEval (repl.js:269:27)
    at bound (domain.js:287:14)
    at REPLServer.runBound [as eval] (domain.js:300:12)
    at REPLServer.<anonymous> (repl.js:439:12)
    at emitOne (events.js:95:20)
    at REPLServer.emit (events.js:182:7)
    at REPLServer.Interface._onLine (readline.js:211:10)
    at REPLServer.Interface._line (readline.js:550:8)
    at REPLServer.Interface._ttyWrite (readline.js:827:14)
> a = 1;
ReferenceError: a is not defined
    at repl:1:3
    at REPLServer.defaultEval (repl.js:269:27)
    at bound (domain.js:287:14)
    at REPLServer.runBound [as eval] (domain.js:300:12)
    at REPLServer.<anonymous> (repl.js:439:12)
    at emitOne (events.js:95:20)
    at REPLServer.emit (events.js:182:7)
    at REPLServer.Interface._onLine (readline.js:211:10)
    at REPLServer.Interface._line (readline.js:550:8)
    at REPLServer.Interface._ttyWrite (readline.js:827:14)
> 
@mscdex mscdex added the repl Issues and PRs related to the REPL subsystem. label Apr 8, 2016
@mscdex mscdex changed the title repl: Failed assignment "blocks" further assignemts to a variable name repl: Failed assignment "blocks" further assignments to a variable name Apr 8, 2016
@Fishrock123
Copy link
Contributor

The current behavior is technically semantic, but this is a repl so I agree it is somewhat poor usability.

Ideally if you did const x; it would delete the existing x, even if it was const, and make the new declaration.

I'm not actually sure this can be fixed though, because I'm pretty sure it's interpreted to the VM like a script. 😕

@jasnell
Copy link
Member

jasnell commented Apr 8, 2016

+1 this has been somewhat of an irritation for me for a while. Just not convinced that it is something that can be fixed in Node.js as I believe it's a v8 issue (Chrome gives precisely the same error). Quick test in the Chrome dev console shows:

const m = n
VM192:1 Uncaught ReferenceError: n is not defined(…)
const m = 1
VM221:1 Uncaught TypeError: Identifier 'm' has already been declared(…)

@Fishrock123
Copy link
Contributor

It originates in v8 I think, but I doubt it is an "issue" on that level, it's just how the language semantics work.

Maybe we could give short errors for redeclarations in the REPL along with a more informative message.

@dodev
Copy link
Contributor Author

dodev commented Apr 8, 2016

@jasnell In chromium's repl I get a different behavior, than the one I get in node. But it is unexpected non the less:

> const q = 1();
VM481:2 Uncaught TypeError: 1 is not a function(…)(anonymous function) @ 
> const q = 1;
undefined
> q
VM520:2 Uncaught ReferenceError: q is not defined(…)(anonymous function) @ 

@jasnell
Copy link
Member

jasnell commented Apr 8, 2016

Sigh.. gotta love consistency. +1 to seeing if we can at least improve the errors in REPL.

@lance
Copy link
Member

lance commented Apr 25, 2016

This seems to be a side effect of the way Javascript evaluates let and const declarations as defined by the spec: http://www.ecma-international.org/ecma-262/6.0/#sec-let-and-const-declarations. Based on this grammar, I can see why const would behave this way, since the variables are "created when their containing Lexical Environment is instantiated". So for const, it seems the variable is created, but when the exception is thrown, it's the lingering const reference cleaned up. But I'm kind of spitballing here, since let variables can be reassigned, and so should not throw a ReferenceError when reassigned.

Without digging too much, it almost seems like a V8 bug to me, but a quick search of the bug tracker doesn't shed any light: https://bugs.chromium.org/p/v8/issues/list?can=1&q=assignment+exception&colspec=ID+Type+Status+Priority+Owner+Summary+HW+OS+Component+Stars&x=priority&y=owner&cells=ids

@jasnell
Copy link
Member

jasnell commented Apr 25, 2016

Yep, there's actually nothing we can do on this one in Node except maybe make the error a bit more informative. There has been at least one other issue about this reported. Going to close this as it's not something we can fix.

@jasnell jasnell closed this as completed Apr 25, 2016
arsenerei added a commit to arsenerei/clojurescript-site that referenced this issue Jan 30, 2017
When running through the `(require ... :reload)` example, I got an error message from Node:

SyntaxError: Identifier 'sayHello$$module$src$js$hello' has already been declared
    at /home/rei/repos/hello-es6/.cljs_node_repl/src/js/hello.js:1:1
    at ContextifyScript.Script.runInThisContext (vm.js:26:33)
    at Object.exports.runInThisContext (vm.js:79:17)
    at nodeGlobalRequire (repl:85:6)
    at global.CLOSURE_IMPORT_SCRIPT (repl:75:3)
    at Object.goog.require (repl:21:8)
    at repl:1:6
    at ContextifyScript.Script.runInThisContext (vm.js:26:33)
    at Object.exports.runInThisContext (vm.js:79:17)
    at Domain.<anonymous> ([stdin]:50:34)

This was due to the fact that Node (my version is 7.4.0) disallows redefinining anything declared with a `let`.  Cf: nodejs/node#6118

This commit replace any `export let` with an `export var` which can be refined without error.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
repl Issues and PRs related to the REPL subsystem.
Projects
None yet
Development

No branches or pull requests

5 participants