const and eval in non-strict code

Luke Hoban lukeh at
Wed Jul 18 19:08:42 PDT 2012

>From: Allen Wirfs-Brock [mailto:allen at] 

>> What is the intended behavior of this code:
>>    (function() {
>>        eval("const x = 4");
>>        const x = 3;
>>    })();

> Regarding, this specific issue.  I assume that it would be a early error (during the eval)  because the scope contour (the function's top level) where eval needs to instantiate x already has a declaration for x and multiple declaration are not allowed.

That makes some sense, but seems to mix phases of the current spec. The "duplicate identifier" errors are today solely in places (12.1) where they can be identified with just the information about a single parse.  Making the above an early error requires compilation time to know about the scope in which the compilation is being done just to report early errors.  As I understand it, that would be new to the spec, and to implementations.  I doubt that complexity would be warranted here.  I could imagine this being a late error during binding instantiation in the future "Eval Declaration Binding" section instead would be cleaner?

A couple more questions:

#1:   The current spec says that an early error is reported on an assignment to a const-bound variable only if it "can be statically determined to always resolve to a declarative environment record binding and the resolved binding is immutable".  Does that mean that the example below is not an error?  By the spec text, it should not be an error, but I'm unclear on exactly what set of "static analysis" is required.  For instance, is the mere presence of an eval inside the body of g enough to assume it cannot be statically determined?  What if the eval did not redeclare x?  Or is the spec text not what is actually intended, and this should be an early error even though it would run without any error?

function f() {
  const x = 5;
  function g() {
    eval("var x = 10");
    x = 20;

#2: The spec has added block scoped function declarations.  With 1JS, this is a non-opt-in breaking change for most browsers.  I have not yet investigated how significant this break is in practice, but I understand there has been concern about changes here in the past due to web compatibility.

If it happened to not be okay to break compatibility here, and browsers with function scoped function statements were to need to keep support for that extension, it seems that several concerns arise with let/const.  For example - the following would need to capture a reference to a nested scope during creation of a function object upon entering f, which requires the nested scope to exist earlier than it needs to in the spec today.  I suspect there are cases where that is not even implementable.  Was this discussed previously?  If so, was the result an approach that would allow reasonable semantics for block scoped bindings combined with function scoped function statements?  Or was the result that block scoped bindings only make sense when combined with block scoped function statements?

function f() {
    let x = 10;
    function g() { return x; }


More information about the es-discuss mailing list