ladybird/Libraries/LibJS
Andreas Kling 5674f8bbe0 LibJS: Limit eval() deoptimization to the containing function scope
Previously, when direct eval() was called, we would mark the entire
environment chain as "permanently screwed by eval", disabling variable
access caching all the way up to the global scope.

This was overly conservative. According to the ECMAScript specification,
a sloppy direct eval() can only inject var declarations into its
containing function's variable environment - it cannot inject variables
into parent function scopes.

This patch makes two changes:

1. Stop propagating the "screwed by eval" flag at function boundaries.
   When set_permanently_screwed_by_eval() hits a FunctionEnvironment or
   GlobalEnvironment, it no longer continues to outer environments.

2. Check each environment during cache lookup traversal. If any
   environment in the path is marked as screwed, we bail to the slow
   path. This catches the case where we're inside a function with eval
   and have a cached coordinate pointing to an outer scope.

The second change is necessary because eval can create local variables
that shadow outer bindings. When looking up a variable from inside a
function that called eval, we can't trust cached coordinates that point
to outer scopes, since eval may have created a closer binding.

This improves performance for code with nested functions where an inner
function uses eval but parent functions perform many variable accesses.
The parent functions can now use cached environment coordinates.

All 29 new tests verify behavior matches V8.
2026-01-27 10:58:39 +01:00
..
Bytecode LibJS: Limit eval() deoptimization to the containing function scope 2026-01-27 10:58:39 +01:00
Contrib/Test262 LibJS+LibWeb+WebContent: Port JS::PropertyKey to UTF-16 2025-08-05 07:07:15 -04:00
Heap LibGC: Enforce that a Cell type must declare the allocator to use 2026-01-20 12:00:11 +01:00
Runtime LibJS: Limit eval() deoptimization to the containing function scope 2026-01-27 10:58:39 +01:00
AST.cpp LibJS: Eliminate HashMap operations in SFID by caching parser data 2026-01-25 23:08:36 +01:00
AST.h LibJS: Eliminate HashMap operations in SFID by caching parser data 2026-01-25 23:08:36 +01:00
CMakeLists.txt CMake: Remove ENABLE_WINDOWS_CI option and adjust presets to match Unix 2026-01-16 11:15:16 -07:00
Console.cpp LibJS: Remove ExecutionContext::function_name field 2025-10-29 21:20:10 +01:00
Console.h LibJS: Implement console.dirxml 2025-08-17 07:28:56 -04:00
CyclicModule.cpp LibJS: Align async module rejection order with fulfillment order 2025-12-17 15:33:26 +01:00
CyclicModule.h LibJS: Sync additional Import Attributes spec changes 2025-10-22 10:58:19 +02:00
Forward.h LibJS: Shrink FunctionEnvironment by reordering members a bit 2025-12-21 12:08:41 -06:00
Lexer.cpp LibJS: Cache length-in-code-units in SourceCode 2025-11-09 12:14:03 +01:00
Lexer.h LibJS: Cache an Utf16View for the full code string in SourceCode 2025-11-09 12:14:03 +01:00
LocalVariable.h LibJS: Port the Identifier AST (and related) nodes to UTF-16 2025-08-13 09:56:13 -04:00
Module.cpp LibGC: Enforce that a Cell type must declare the allocator to use 2026-01-20 12:00:11 +01:00
Module.h LibGC: Enforce that a Cell type must declare the allocator to use 2026-01-20 12:00:11 +01:00
ModuleLoading.h LibGC+Everywhere: Factor out a LibGC from LibJS 2024-11-15 14:49:20 +01:00
Parser.cpp LibJS: Eliminate HashMap operations in SFID by caching parser data 2026-01-25 23:08:36 +01:00
Parser.h LibJS: Remove ParserState::lookahead_lexer 2025-11-09 12:14:03 +01:00
ParserError.cpp LibJS: Port the JS lexer and parser to UTF-16 2025-08-13 09:56:13 -04:00
ParserError.h LibJS: Port the JS lexer and parser to UTF-16 2025-08-13 09:56:13 -04:00
Position.h LibJS: Store full realized SourceRange with each AST node 2025-12-29 13:36:01 +01:00
Print.cpp LibJS+LibWeb: Replace JS::Utf16String with AK::Utf16String 2025-07-18 12:45:38 -04:00
Print.h LibJS: Enable EXPLICIT_SYMBOL_EXPORT and annotate minimum symbol set 2025-07-22 11:51:29 -04:00
Script.cpp LibJS: Have JS::Lexer take a JS::SourceCode as input 2025-11-09 12:14:03 +01:00
Script.h LibJS: Stop tracking whether execution context is strict mode or not 2025-10-29 21:20:10 +01:00
SourceCode.cpp LibJS: Store full realized SourceRange with each AST node 2025-12-29 13:36:01 +01:00
SourceCode.h LibJS: Cache length-in-code-units in SourceCode 2025-11-09 12:14:03 +01:00
SourceRange.h LibJS: Enable EXPLICIT_SYMBOL_EXPORT and annotate minimum symbol set 2025-07-22 11:51:29 -04:00
SourceTextModule.cpp LibJS: Skip initializing constant slots in ExecutionContext 2026-01-19 10:48:12 +01:00
SourceTextModule.h LibJS+LibWeb+WebContent: Port JS::PropertyKey to UTF-16 2025-08-05 07:07:15 -04:00
SyntaxHighlighter.cpp LibJS: Have JS::Lexer take a JS::SourceCode as input 2025-11-09 12:14:03 +01:00
SyntaxHighlighter.h LibJS: Enable EXPLICIT_SYMBOL_EXPORT and annotate minimum symbol set 2025-07-22 11:51:29 -04:00
SyntheticModule.cpp LibJS: Skip initializing constant slots in ExecutionContext 2026-01-19 10:48:12 +01:00
SyntheticModule.h LibJS+LibWeb+WebContent: Port JS::PropertyKey to UTF-16 2025-08-05 07:07:15 -04:00
Token.cpp LibJS: Make JS::Token::message an enum instead of a StringView 2025-11-09 12:14:03 +01:00
Token.h LibJS: Store full realized SourceRange with each AST node 2025-12-29 13:36:01 +01:00