Treat zero length UTF-16 slices from Rust as empty views at the FFI
boundary instead of assuming a non null backing pointer.
Add a regression test which crashed before these changes. Fixes
a crash loading github.com/ladybirdbrowser/ladybird.
RegExpBuiltinExec used to snap any Unicode lastIndex that landed on a
low surrogate back to the start of the pair. That matched `/😀/u`,
but it skipped valid empty matches when the original low-surrogate
position was itself matchable, such as `/p{Script=Cyrillic}?(?<!\D)/v`
on `"A😘"` and the longer fuzzed global case.
Try the snapped position first, then retry the original lastIndex when
the snapped match fails. Only keep that second result when it is empty
at the original low-surrogate position, so consuming /u and /v matches
still cannot split a surrogate pair. In the Rust VM, treat backward
Unicode matches that start between surrogate halves as having no
complete code point to their left, which matches V8's lookbehind
behavior for those positions.
Add reduced coverage for both low-surrogate exec cases, the original
global match count regression, and the consuming-match retry regression.
Reject surrogate pairs in named group names unless both halves come
from the same raw form. A literal surrogate half was being
normalized into \uXXXX before LibRegex parsed the pattern, which let
mixed literal and escaped forms sneak through.
Validate surrogate handling on the UTF-16 pattern before
normalization, but only treat \k<...> as a named backreference when
the parser would do that too. Legacy regexes without named groups
still use \k as an identity escape, so their literal text must not be
rejected by the pre-scan.
Add runtime and syntax tests for the mixed forms, the valid literal,
fixed-width, and braced escape cases, and the legacy \k literals.
Teach import_rust_crate() to track RustFFI.h as a real build output,
and teach the relevant Rust build scripts to rerun when their FFI
inputs change.
Also keep a copy of RustFFI.h in Cargo's own OUT_DIR and restore the
configured FFI output from that cached copy after cargo rustc runs.
This fixes the case where Ninja knows the header is missing, reruns
the custom command, and Cargo exits without rerunning build.rs
because the crate itself is already up to date.
When Cargo leaves multiple hashed build-script outputs behind, pick
the newest root-output before restoring RustFFI.h so we do not copy a
stale header after Rust-side API changes.
Finally, track the remaining Rust-side inputs that could leave build
artifacts stale: LibUnicode and LibJS now rerun build.rs when src/
changes, and the asmintgen rule now depends on Cargo.lock, the
BytecodeDef path dependency, and newly added Rust source files.
When decoding a zero length string, we would pass through the (null)
data() of an empty Vector to the Utf16View constructor. Return an empty
PrimitiveString early instead.
On platforms like FreeBSD x86_64 has the value of lowercase `amd64` in
`CMAKE_SYSTEM_PROCESSOR` which caused this check to fail and then
caused linking errors.
This better describes what the method returns and avoids the possible
confusion caused by the mismatch in behavior between
`Value::is_array()` and `Value::as_array()`.
Previously, we would crash if `console.table()` was called with a
proxy-wrapped array. This is because `Value::is_array()` returns true
for proxy-wrapped arrays but `as_array()` simply casts to an Array
object. We now treat these objects as array-like and access elements
generically through the Object interface, which correctly dispatches
through Proxy traps.
In b2d9fd3352, the root cause of the crash
was somewhat misdiagnosed, particularly around what place in code an
allocation could occur while constants data was uninitialized.
But more importantly, we can do better than the solution in that commit.
Instead of initializing constants with default values and then
overwriting them afterwards, simply initialize them with their actual
values directly when constructing the execution context.
This effectivly reverts commit b2d9fd3352.
The additional data being passed will be used in an upcoming commit.
Allows splitting the churn of modified function signatures from the
logically meaningful code change.
No behavior change.
When allocating ExecutionContext, we were skipping allocating constants,
because they are filled in shortly after. However, there is still some
code executing between allocating the ExecutionContext and assigning
constants. This code may allocate GC-aware objects before the
assignment. Allocating any GC object may cause a garbage collection to
be triggered. And running garbage collection on uninitialized objects
might have all kinds of unintended effects.
To avoid that, simply initialize constants right away. To be safe, also
initialize arguments, but I haven't checked more closely if it is needed
for them or not.
The specific case where this bug manifested was JetStream3's
raytrace-private-class-fields.js, which was triggering a segmentation
fault when trying to visit a functions constant during GC marking phase.
The offending allocation triggering the garbage collection is the
corresponding FunctionEnvironment being created.
This crash was exposed as a combination of multiple things coming
together. In particular, both of 1179e40d3f and 61e6dbe4e7 combined
were exposing the problem, but is seems neither commit is at fault. Most
likely the crash happening or not is sensitive to the exact amount of GC
pressure being present or size of individual execution contexts. And so
any change that affects those might make it appear or go away.
To put in an additional wrinkle, this could only be observed using the
ASM JS interpreter. The CPP interpreter was using a fast path for
function calls that has a different allocation pattern and did not run
into the crash.
No explicit regression test for this change because:
* The problem is very sensitive to implementation details and a
reproduction that stays valid with code changes in the interpreter is
probably impossible to come by.
* The bug was exposed by the JS benchmarks, which already are as good as
a regression test as we are going to get here realistically.