Skip to content

Error with let: "Identifier '*' has already been declared" on REPL #8441

Description

@zladuric

The problem I'm seeing is that if during declaring a variable with let something throws - that identifier is "taken", but I can't use it.

Essentially like this (stripped unnecessary stack).

let broken = JSON.parse('I am broken');
> SyntaxError: Unexpected token I
let broken = 5;
> TypeError: Identifier 'broken' has already been declared
let broken = 5;
> TypeError: Identifier 'broken' has already been declared

I'm seeing this for a long time, but never took an effort to look into it more.

Now I'm curious - is this expected behaviour? Why? If not, how can one go about and fix it?

It's on Node 5 and latest 6, but I believe I've seen it on older versions as well.

[zlatko@zlatko-desktop ~/tmp]$ node -v
v5.12.0
[zlatko@zlatko-desktop ~/tmp]$ uname -a
Linux zlatko-desktop 4.4.0-36-generic #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

Activity

  1. added
    replIssues and PRs related to the REPL subsystem.
    on Sep 8, 2016
  2. addaleax commented on Sep 8, 2016

    @addaleax
    Member

    See e.g. #8376, #8309 and probably more… unfortunately, that appears to be spec-compliant behaviour.

  3. added
    v8 engineIssues and PRs related to the V8 dependency.
    wontfixIssues that will not be fixed.
    on Sep 8, 2016
  4. Fishrock123 commented on Sep 8, 2016

    @Fishrock123
    Contributor

    I guess we may be able to provide a better error message? Maybe?

  5. lance commented on Sep 13, 2016

    @lance
    Member

    @Fishrock123 how would you improve the error message? To me it appears pretty clear. The only thing that is really confusing is that you get two different errors depending on how you try and redefine the variable. E.g.

    > let broken = foo
    ReferenceError: foo is not defined
    > let broken = 'foo'
    TypeError: Identifier 'broken' has already been declared
    > broken = 'foo';
    ReferenceError: broken is not defined
    

    Providing better error messages would mean catching all Reference errors, and comparing the error messages to these known values, then changing the message. This seems like a lot of work for something that is spec compliant.

  6. fhinkel commented on Sep 22, 2016

    @fhinkel
    Contributor

    Any objections to closing this issue since it's a wontfix?

  7. bnoordhuis commented on Sep 22, 2016

    @bnoordhuis
    Member

    Let's close, I don't think we'll fix this anytime soon.

    #8309 (comment) makes an interesting suggestion of turning uninitialized bindings into undefined values but that probably needs support in V8.

  8. princejwesley commented on Sep 22, 2016

    @princejwesley
    Contributor

    @bnoordhuis We can preprocess it before passing to vm. I'll give PR if it seems good to you.

        function preprocess(code) {
           ...
            const letBinding = /^\s*let\s+([^\s=]+)\s*(?==)/;
            const letMatch = cmd.match(letBinding);
            if (letMatch && letMatch[0] !== letMatch.input) {
              const binding = letMatch[1];
              cmd = cmd.replace(letMatch[0], `let ${binding};\n${binding}`);
            }
          ...
        }
    node 🙈 ₹ git:(upstream ⚡ repl.let) ./node
    > let x = foo
    ReferenceError: foo is not defined
        at repl:2:4
        at sigintHandlersWrap (vm.js:22:35)
        at sigintHandlersWrap (vm.js:96:12)
        at ContextifyScript.Script.runInThisContext (vm.js:21:12)
        at REPLServer.defaultEval (repl.js:313:29)
        at bound (domain.js:280:14)
        at REPLServer.runBound [as eval] (domain.js:293:12)
        at REPLServer.<anonymous> (repl.js:513:10)
        at emitOne (events.js:101:20)
        at REPLServer.emit (events.js:188:7)
    > x
    undefined
    > x = 3
    3
    >
  9. bnoordhuis commented on Sep 22, 2016

    @bnoordhuis
    Member

    A bit too much of a hack, IMO. I know perfect is the enemy of good but it would fail on simple inputs like let x = 1, y = boom, let /* comment */ y = boom, f(); let y = boom, etc.

  10. pplam commented on Oct 30, 2016

    @pplam

    @lance I just caught the same issue as you in node@6.9.1 !

  11. pplam commented on Oct 30, 2016

    @pplam

    I used let, but the variable can't be reassigned. It's maybe a bug of node@6.9.1 REPL

  12. CherryDT commented on Jan 7, 2017

    @CherryDT

    @pplam No, it's spec-compliant, see also #6118, but is problematic for a REPL environment of course...

  13. atul9911 commented on Jun 10, 2018

    @atul9911

    This is very weird behaviour as i cannot use that variable and can lead to memory leak as memory is already given to this obj but the compiler can not clean it.

  14. DinmaOtutu commented on Aug 26, 2018

    @DinmaOtutu

    class Drone {
    constructor(id, name) {
    this.id = id;
    this.name = name;
    }
    }

    let drone = new Drone(A1223, flyer);
    console.log('drone :' + drone.id +' ' + drone.name);
    I keep getting this error "VM55:1 Uncaught SyntaxError: Identifier 'Drone' has already been declared
    at :1:1" please can someone tell me why?

  15. CherryDT commented on Aug 26, 2018

    @CherryDT

    @DinmaOtutu How is this related to node REPL? REPL doesn't produce errors with "VMxx" in the message. Looks like an error in a browser, not in node...

    Also, I guess you already declared it further above or in a previous statement. That's what the error literally tells you.

  16. brentknudsenstud commented on May 20, 2021

    @brentknudsenstud

    class Drone {
    constructor(id, name) {
    this.id = id;
    this.name = name;
    }
    }

    let drone = new Drone(A1223, flyer);
    console.log('drone :' + drone.id +' ' + drone.name);
    I keep getting this error "VM55:1 Uncaught SyntaxError: Identifier 'Drone' has already been declared
    at :1:1" please can someone tell me why?

    I'm running into the same problem in some of my code. I don't understand why it has said that Drone has already been declared when it wasn't declared as a variable. It was set as a class. Are setting a class and setting a variable both declarations?

  17. CherryDT commented on May 20, 2021

    @CherryDT

    Yes, class X {} is almost the same as const X = class {}. But this has nothing to do with this REPL-specific issue.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    replIssues and PRs related to the REPL subsystem.v8 engineIssues and PRs related to the V8 dependency.wontfixIssues that will not be fixed.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions