소스 검색

LibJS: Elide some declarative environments in ECMAScript function calls

By spec, calling an ECMAScript function object in non-strict mode should
always create a new top-level declarative environment, even if there are
no lexically scoped bindings (let/const) that belong in it. This is
used for scope disambiguation in direct eval() calls.

However, if there are no direct eval() calls within the function, and no
lexically scoped bindings, we can simply not allocate the extra
environment and save ourselves the trouble.
Andreas Kling 3 년 전
부모
커밋
fa6c06ce8d
1개의 변경된 파일20개의 추가작업 그리고 3개의 파일을 삭제
  1. 20 3
      Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp

+ 20 - 3
Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp

@@ -345,11 +345,28 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
 
 
     Environment* lex_environment;
     Environment* lex_environment;
 
 
-    if (!is_strict_mode())
-        lex_environment = new_declarative_environment(*var_environment);
-    else
+    // 30. If strict is false, then
+    if (!is_strict_mode()) {
+        // Optimization: We avoid creating empty top-level declarative environments in non-strict mode, if both of these conditions are true:
+        //               1. there is no direct call to eval() within this function
+        //               2. there are no lexical declarations that would go into the environment
+        bool can_elide_declarative_environment = !m_contains_direct_call_to_eval && (!scope_body || !scope_body->has_lexical_declarations());
+        if (can_elide_declarative_environment) {
+            lex_environment = var_environment;
+        } else {
+            // a. Let lexEnv be NewDeclarativeEnvironment(varEnv).
+            // b. NOTE: Non-strict functions use a separate Environment Record for top-level lexical declarations so that a direct eval
+            //          can determine whether any var scoped declarations introduced by the eval code conflict with pre-existing top-level
+            //          lexically scoped declarations. This is not needed for strict functions because a strict direct eval always places
+            //          all declarations into a new Environment Record.
+            lex_environment = new_declarative_environment(*var_environment);
+        }
+    } else {
+        // 31. Else, let lexEnv be varEnv.
         lex_environment = var_environment;
         lex_environment = var_environment;
+    }
 
 
+    // 32. Set the LexicalEnvironment of calleeContext to lexEnv.
     callee_context.lexical_environment = lex_environment;
     callee_context.lexical_environment = lex_environment;
 
 
     if (!scope_body)
     if (!scope_body)