Browse Source

LibJS: Only "var" declarations go in the global object at program level

"let" and "const" go in the lexical environment.

This fixes one part of #4001 (Lexically declared variables are mixed up
with global object properties)
Andreas Kling 4 years ago
parent
commit
4bc98fd39f

+ 3 - 1
Userland/Libraries/LibJS/Interpreter.cpp

@@ -94,9 +94,11 @@ void Interpreter::enter_scope(const ScopeNode& scope_node, ScopeType scope_type,
     HashMap<FlyString, Variable> scope_variables_with_declaration_kind;
     scope_variables_with_declaration_kind.ensure_capacity(16);
 
+    bool is_program_node = is<Program>(scope_node);
+
     for (auto& declaration : scope_node.variables()) {
         for (auto& declarator : declaration.declarations()) {
-            if (is<Program>(scope_node)) {
+            if (is_program_node && declaration.declaration_kind() == DeclarationKind::Var) {
                 declarator.target().visit(
                     [&](const NonnullRefPtr<Identifier>& id) {
                         global_object.put(id->string(), js_undefined());

+ 21 - 0
Userland/Libraries/LibJS/Tests/global-var-let-const.js

@@ -0,0 +1,21 @@
+var foo = 1;
+let bar = 2;
+const baz = 3;
+
+test("behavior of program-level var/let/const", () => {
+    expect(foo).toBe(1);
+    expect(bar).toBe(2);
+    expect(baz).toBe(3);
+    expect(globalThis.foo).toBe(1);
+    expect(globalThis.bar).toBeUndefined();
+    expect(globalThis.baz).toBeUndefined();
+    globalThis.foo = 4;
+    globalThis.bar = 5;
+    globalThis.baz = 6;
+    expect(foo).toBe(4);
+    expect(bar).toBe(2);
+    expect(baz).toBe(3);
+    expect(globalThis.foo).toBe(4);
+    expect(globalThis.bar).toBe(5);
+    expect(globalThis.baz).toBe(6);
+});