Keep primitive string storage in Utf16String and remove the UTF-8
storage path from PrimitiveString. ASCII strings still use compact
Utf16String ASCII storage, while UTF-16 becomes the only owned
representation.
Host-loaded modules are inserted into the VM module registry before
their dependencies are walked, but entry modules passed directly to
`VM::run()` were not. That made an entry module self-import parse a
second Module Record and observe the second copy after evaluation.
Register named entry modules in the same registry before dependency
loading runs, so self-imports and namespace access go through the
original Module Record. Add a test-js helper for running modules
directly and cover the self-import pre-evaluation binding state.
Add Core::TimeZone as the single entry point for changing the
current time zone. This updates both ICU and the process TZ/tzset
state so libc-backed helpers such as AK::UnixDateTime::to_string()
agree with JS/ICU time zone state. Previously only the ICU timezone
would be updated, which could result in inconsistent results being
returned.
Cover cleanup delivery after target collection and held value retention.
Record unregister token retention as expected-failing coverage on this
branch, where that behavior is still missing.
Add deterministic test hooks to clear WeakRef kept objects and clear
global bindings before collection.
When an automatic cleanup job aborts after invoking a callback, requeue
the registry if records with empty targets remain. This keeps later held
values from being stranded until another target dies.
Add test-js coverage that drains the automatic cleanup queue after two
records die and the first cleanup callback throws.
The cleanupSome proposal was withdrawn, and other engines no longer
expose this method by default. Stop installing it on
FinalizationRegistry.prototype while keeping the internal cleanup path
used for queued cleanup jobs.
Add a test-js helper for invoking that internal cleanup path directly.
Move the FinalizationRegistry cleanup coverage onto it so callbacks
unregistering later dead records remain covered without exposing the
withdrawn API to JavaScript programs.
Fixes#2228
Report Map, WeakMap, and WeakSet entry storage through the GC
external memory hook.
Replace the public values() accessors on WeakMap and WeakSet with
explicit methods so all mutations update external memory accounting.
When species resolves to the default intrinsic, construct the result
directly instead of going through the public TypedArray constructor,
skipping the throwaway empty ArrayBuffer that the constructor
allocates only to immediately overwrite.
Affects subarray, filter, map, and slice. The subarray path re-checks
the buffer state after species lookup, since the lookup can run user
code that detaches or resizes the buffer.
Saves ~300ms of load time (in the WebWorker process) when opening the
Combined Intel ISA PDF :^)
No other engine defines this function, so it is an observable difference
of our engine. This traces back to the earliest days of LibJS.
We now define `gc` in just the test-js and test262 runners.
Keep JS-to-JS inline calls out of m_execution_context_stack and walk
the active stack from the running execution context instead. Base
pushes now record the previous running context so duplicate
TemporaryExecutionContext pushes and host re-entry still restore
correctly.
This keeps the fast JS-to-JS path off the vector without losing GC
root collection, stack traces, or helpers that need to inspect the
active execution context chain.
The bytecode interpreter only needed the running execution context,
but still threaded a separate Interpreter object through both the C++
and asm entry points. Move that state and the bytecode execution
helpers onto VM instead, and teach the asm generator and slow paths to
use VM directly.
Port all remaining users of the C++ Parser/Lexer/Generator to
use the Rust pipeline instead:
- Intrinsics: Remove C++ fallback in parse_builtin_file()
- ECMAScriptFunctionObject: Remove C++ compile() fallback
- NativeJavaScriptBackedFunction: Remove C++ compile() fallback
- EventTarget: Port to compile_dynamic_function
- WebDriver/ExecuteScript: Port to compile_dynamic_function
- LibTest/JavaScriptTestRunner.h: Remove Parser/Lexer includes
- FuzzilliJs: Remove unused Parser/Lexer includes
Also remove the dead Statement-based template instantiation of
async_block_start/async_function_start.
The Rust pipeline is now the only compilation path, so remove:
- The LIBJS_CPP environment variable check
- The rust_pipeline_enabled() helper
- The #ifdef ENABLE_RUST / #else stub section
- The test-js-cpp CTest target and LIBJS_TEST_PARSER_MODE env var
- The ParserMode enum and canParseSourceWithCpp/Rust test functions
rust_pipeline_available() now unconditionally returns true.
This moves the responsibility of setting up a SourceCode object to the
users of JS::Lexer.
This means Lexer and Parser are free to use string views into the
SourceCode internally while working.
It also means Lexer no longer has to think about anything other than
UTF-16 (or ASCII) inputs. So the unit test for parsing various invalid
UTF-8 sequences is deleted here.
This commits puts the strict mode flag in the header of every bytecode
instruction. This allows us to check for strict mode without looking at
the currently running execution context.
Adds inline implementation for the most common case when `Value` is
already an object.
1.47x improvement on the following benchmark:
```js
const o = {};
for (let i = 0; i < 10_000_000; i++) {
o.a = 1;
o.b = 2;
o.c = 3;
}
```
This has quite a lot of fall out. But the majority of it is just type or
UDL substitution, where the changes just fall through to other function
calls.
By changing property key storage to UTF-16, the main affected areas are:
* NativeFunction names must now be UTF-16
* Bytecode identifiers must now be UTF-16
* Module/binding names must now be UTF-16
On Windows, ICU does not look at the TZ environment variable at all. So
to support changing time zones in test-js, let's set ICU's default time
zone directly.
Note that we no longer deal with "null" time zone strings. We just cache
whatever ICU thinks is the current time zone before attempting to change
it, for which we never have a null result.
Co-authored-by: Andrew Kaster <andrew@ladybird.org>
PrimitiveString is now internally either UTF-8, UTF-16, or both.
We no longer convert them to/from ByteString anywhere, nor does VM have
a ByteString cache.
We should always prefer working with String, and Value::to_string() may
even return a cached String if the Value refers to a primitive string,
but no caching occurs for ByteString.
Even though the underlying time zone is already cached by LibUnicode, JS
performs additional expensive lookups with that time zone. There's no
need to do those lookups again until the system time zone has changed.
It's expensive to determine the system time zone from disk each time it
is requested. This makes LibUnicode cache the result, and provides an
API to clear that cache. This will let us set up a monitor to watch for
system time zone changes in platform-dependent ways.
This commit un-deprecates DeprecatedString, and repurposes it as a byte
string.
As the null state has already been removed, there are no other
particularly hairy blockers in repurposing this type as a byte string
(what it _really_ is).
This commit is auto-generated:
$ xs=$(ack -l \bDeprecatedString\b\|deprecated_string AK Userland \
Meta Ports Ladybird Tests Kernel)
$ perl -pie 's/\bDeprecatedString\b/ByteString/g;
s/deprecated_string/byte_string/g' $xs
$ clang-format --style=file -i \
$(git diff --name-only | grep \.cpp\|\.h)
$ gn format $(git ls-files '*.gn' '*.gni')
This is intended to be used in adding test-js tests where there is
different behaviour between the AST interpreter and bytecode mode.
In particular, this is useful for tests which fail in AST, but pass in
bytecode, as the AST interpreter is run in CI but bytecode is not.
The Heap::uproot_cell() API was used to implement markAsGarbage() which
was used in 3 tests to forcibly destroy a value, even if it had
references on the stack or elsewhere.
This patch rewrites the 3 tests that used this mechanism to be
structured in a way that allows garbage collection to collect the values
as intended without hacks. And now that the uprooting mechanism is no
longer needed, it's uprooted as well.
This fixes 3 test-js tests in bytecode mode. :^)
This makes construction of Utf16String fallible in OOM conditions. The
immediate impact is that PrimitiveString must then be fallible as well,
as it may either transcode UTF-8 to UTF-16, or create a UTF-16 string
from ropes.
There are a couple of places where it is very non-trivial to propagate
the error further. A FIXME has been added to those locations.