Commit graph

1852 commits

Author SHA1 Message Date
aplefull
e0dd182964 LibJS: Use stored input for RegExp legacy static property views
The m_last_match, m_left_context, and m_right_context views were being
created from a temporary string instead of from the owned m_input.
This caused the views to point to destroyed stack memory when accessing
RegExp.lastMatch after calling String.replace() with a regex.
2025-12-03 13:45:26 +01:00
Timothy Flynn
c7b3a4fcf8 LibJS: Implement Iterator.concat
This proposal reached stage 4 and was merged into ECMA-262. See:
aefd096
2025-12-03 12:08:40 +01:00
Timothy Flynn
7ee415a7c2 LibJS: Directly indicate when the IteratorHelper generator is complete
Our existing implementation was checking if the generator step result
was `undefined` to indicate that the generator is complete. This is
not sufficient for an upcoming implementation of Iterator.concat, where
`undefined` is used as an incomplete iteration result.

Instead, let's have the Iterator prototype return an IterationResult to
explicitly indicate its completeness. As a result, the prototype also
looks more like the spec now.
2025-12-03 12:08:40 +01:00
Timothy Flynn
6976ff389e LibJS: Mark IteratorHelper::create as infallible
This is just allocating an IteratorHelper. There is no way for this to
throw an exception.
2025-12-03 12:08:40 +01:00
Timothy Flynn
e011f8d6b1 LibJS: Replace [[UnderlyingIterator]] with [[UnderlyingIterators]]
This is an editorial change in the EMCA-262 spec. See:
c541680
2025-12-03 12:08:40 +01:00
Timothy Flynn
557805d6ef LibJS: Compute byteIndexInBuffer sooner in Atomic's DoWait
This is a normative change in the ECMA-262 spec. See:
4d2116b

Note this does not yet affect us as we do not implement the remainder of
this AO.
2025-12-03 12:08:40 +01:00
Timothy Flynn
b060d5dcdf LibJS: Fix typo in ResolveExport assertion
This is an editorial change in the ECMA-262 spec. See:
29c5b17
2025-12-03 12:08:40 +01:00
Andreas Kling
99bef81d09 LibJS: Fast path for TypedArray.slice()
We now try to do a bulk memcpy() when possible. This is significantly
faster than going byte-at-a-time.
2025-12-01 15:12:52 +01:00
Andreas Kling
4d7d8aa827 LibJS: Allow fast conversions between Uint8Array and Uint8ClampedArray
These two typed array kinds have the same exact underlying data type and
differ only in how assignment works.

We can allow them to take the fast paths for same-type conversions.
2025-12-01 15:12:52 +01:00
Callum Law
1f7fe97ac3 LibJS/AK: Move XorShift128PlusRNG to AK
This will be useful for CSS random functions so it should be in a
reusable place.

This does require us to use `AK::get_random` instead of
`Crypto::get_secure_random`, but this is fine since the latter is in the
process of being removed (see #6564).
2025-12-01 11:00:33 +00:00
Rocco Corsi
11dc254d27 LibJS: Add missing internal object string printing for debugging
When testing with JS_BYTECODE_DEBUG macro defined or using the All_Debug
profile, internal objects were not known in Value class to the function
Value::to_string_without_side_effects leading to a VERIFICATION FAILED
when running the test-js or test-web programs.

Internal objects are known in the Value class as cells, and do not have
a dedicated tag to identify them. Internal objects are detected using
is_cell function call, but only after all other types have been
checked as other types of non-internal objects can also be cells.

Both the String and Utf16String version of the function were updated.
2025-11-30 19:22:46 +01:00
Luke Wilde
0eceee0a05 LibJS: Replace Array.fromAsync with a native JavaScript implementation
This allows us to use the bytecode implementation of await, which
correctly suspends execution contexts and handles completion
injections.

This gains us 4 test262 tests around mutating Array.fromAsync's
iterable whilst it's suspended as well.

This is also one step towards removing spin_until, which the
non-bytecode implementation of await uses.

```
Duration:
     -5.98s

Summary:
    Diff Tests:
        +4     -4 

Diff Tests:
    [...]/Array/fromAsync/asyncitems-array-add-to-singleton.js  -> 
    [...]/Array/fromAsync/asyncitems-array-add.js               -> 
    [...]/Array/fromAsync/asyncitems-array-mutate.js            -> 
    [...]/Array/fromAsync/asyncitems-array-remove.js            -> 
```
2025-11-30 11:54:54 +01:00
Luke Wilde
a63b0cfaba LibJS: Introduce NativeJavaScriptBackedFunction
This hosts the ability to compile and run JavaScript to implement
native functions. This is particularly useful for any native function
that is not a normal function, for example async functions such as
Array.fromAsync, which require yielding.

These functions are not allowed to observe anything from outside their
environment. Any global identifiers will instead be assumed to be a
reference to an abstract operation or a constant. The generator will
inject the appropriate bytecode if the name of the global identifier
matches a known name. Anything else will cause a code generation error.
2025-11-30 11:54:54 +01:00
Luke Wilde
899c6ebffc LibJS: Make stored realm in NativeFunction non-null
We now always have a realm for NativeFunction, which allows removing an
old hack in internal_call and internal_construct.
2025-11-30 11:54:54 +01:00
Luke Wilde
354888640d LibJS/Bytecode: Make compilation use SharedFunctionInstanceData instead
All the data we need for compilation is in SharedFunctionInstanceData,
so we shouldn't depend on ECMAScriptFunctionObject.

Allows NativeJavaScriptBackedFunction to compile bytecode.
2025-11-30 11:54:54 +01:00
Luke Wilde
2d15326f5d LibJS: Moved SharedFunctionInstanceData into separate files
This will allow it to be reused by NativeJavaScriptBackedFunction.
2025-11-30 11:54:54 +01:00
Tim Ledbetter
166c8b116f LibJS: Avoid cast to out-of-range value in MathObject::abs() fast path 2025-11-30 11:54:02 +01:00
Andreas Kling
702977373c LibJS: Some Bytecode.def fixes
- Add missing @nothrow to a bunch of instructions.
- Rename fields that were colliding between base and derived class.
2025-11-30 11:53:56 +01:00
Andreas Kling
2d76e21cfd LibJS: Don't use GC::Root unnecessarily in Error stack traces
This was causing a fair bit of root registration churn on pages that
throw lots of errors.

Since there's no need for these pointers to float around freely, we can
just visit them during the mark phase as usual.
2025-11-30 11:53:56 +01:00
Andreas Kling
c1c24e8fd6 LibJS: Use non-copying GetUint8ArrayBytes() in Uint8Array.toBase64()
If the ArrayBuffer we're looking at is non-shared, we can simply get a
view onto the underlying bytes and pass that to the Base64 encoder.
2025-11-29 09:39:43 -05:00
Andreas Kling
124b4fc06a LibJS: Limit the length of strings we put in the VM string cache
For excessively long strings, we often end up spending a ton of time
hashing and comparing them, and it basically ruins the value of the
cache as optimization.

This commit puts a cap (256) on the length of strings we put into the
cache. The number is arbitrary and there may be value in tuning it.
2025-11-29 09:39:43 -05:00
Andreas Kling
b6ef80ff36 LibJS: Avoid options object allocation in fromBase64() and toBase64()
When no options (or undefined) are passed into these APIs, the spec has
us synthesize a temporary "options object" to read the options from.

We don't actually need these objects, so let's sidestep the allocation
if we can (and just use the default values in that case).
2025-11-29 09:39:43 -05:00
Andreas Kling
b2761b5640 LibJS: Avoid redundant ByteBuffer in Uint8Array.fromBase64()
Since we already have a ByteBuffer from decoding the Base64 data, we can
pass that when creating a new ArrayBuffer.

This avoids a buffer allocation + memory clear + memory copy.
2025-11-29 09:39:43 -05:00
Tim Ledbetter
cfce5dc970 LibJS: Add fast path for loosely comparing object and nullish values 2025-11-26 22:03:31 -05:00
aplefull
eed4dd3745 LibRegex: Add support for string literals in character classes 2025-11-26 11:34:38 +01:00
aplefull
a49c39de32 LibRegex: Support matching unicode multi-character sequences 2025-11-26 11:34:38 +01:00
Tim Ledbetter
7ce103b96a LibJS: Demote VERIFY to ASSERT in JS value casting functions
This yields a ~3% performance increase across the board in JS
benchmarks.
2025-11-26 09:38:00 +01:00
Tim Ledbetter
e20e79e7a5 LibJS: Demote VERIFY in ThrowCompletionOr() to ASSERT
This improves JetStream performance by ~16% on my machine.
2025-11-25 08:38:23 +01:00
Tim Ledbetter
999656a7d3 LibJS: Add a localCompare() fast path for ASCII strings
When comparing ASCII strings we now use our own collation tables rather
than invoking ICU.
2025-11-24 00:22:10 +01:00
Tim Ledbetter
f268458aa4 LibJS: Add a localCompare() fast path for identical strings
When identical strings use the default collator, a simple equality
check can be used.
2025-11-24 00:22:10 +01:00
Timothy Flynn
37f49d5f6d LibJS: Use nanoseconds to normalize values in IsValidDuration
This is an editorial change in the Temporal proposal. See:
68004cc
a6043aa
1962c8b

Note that we were already performing this calculation using nanoseconds.
2025-11-21 13:52:55 +01:00
Timothy Flynn
8feabc3158 LibJS: Re-order infallible operations in GetDifferenceSettings
This is an editorial change in the Temporal proposal. See:
c11021a
2025-11-21 13:52:55 +01:00
Andreas Kling
e7388646bb LibJS: Remove unused InstructionStreamIterator::source_range() 2025-11-21 09:46:03 +01:00
Andreas Kling
f37063e2a1 LibJS: Stop worrying about Instruction destructors
By adding static_asserts to prove that all of our generated instruction
classes are trivially destructible, we can confidently remove the
destructor walk in BasicBlock and save ourselves some unnecessary work.
2025-11-21 09:46:03 +01:00
Andreas Kling
370b81f1b7 LibJS: Remove unused "Dump" instruction 2025-11-21 09:46:03 +01:00
Andreas Kling
003589db2d LibJS: Generate C++ bytecode instruction classes from a definition file
This commit adds a new Bytecode.def file that describes all the LibJS
bytecode instructions.

From this, we are able to generate the full declarations for all C++
bytecode instruction classes, as well as their serialization code.

Note that some of the bytecode compiler was updated since instructions
no longer have default constructor arguments.

The big immediate benefit here is that we lose a couple thousand lines
of hand-written C++ code. Going forward, this also allows us to do more
tooling for the bytecode VM, now that we have an authoritative
description of its instructions.

Key things to know about:

- Instructions can inherit from one another. At the moment, everything
  simply inherits from the base "Instruction".

- @terminator means the instruction terminates a basic block.

- @nothrow means the instruction cannot throw. This affects how the
  interpreter interacts with it.

- Variable-length instructions are automatically supported. Just put an
  array of something as the last field of the instruction.

- The m_length field is magical. If present, it will be populated with
  the full length of the instruction. This is used for variable-length
  instructions.
2025-11-21 09:46:03 +01:00
Timothy Flynn
54b9ddcc80 LibJS: Use relative date in NudgeToCalendarUnit when comparing durations
This is a normative change in the Temporal proposal. See:
17e12be

The test added here would previously crash.
2025-11-20 08:28:51 -05:00
Rocco Corsi
5fb78ae455 LibJS: Correct completion_cell typo in GeneratorObject 2025-11-17 23:43:04 +01:00
Andreas Kling
04238d0f3f LibJS: Make AsyncGenerator and GeneratorObject factories infallible
These should never fail.
2025-11-17 23:42:51 +01:00
Andreas Kling
d8f5971ddf LibJS: Allow constructing generator from function with null "prototype"
Fixes 4 test262 tests and simplifies some upcoming stuff.
2025-11-17 23:42:51 +01:00
Timothy Flynn
15e4deb831 LibJS: Remove "era" from Temporal's DateTimeFormat formatting options
This is an editorial change in the Temporal proposal. See:
0ecf157

The test added here would previously throw:

    TypeError: Unable to determine format for Temporal.PlainDate
2025-11-16 07:59:59 -05:00
Timothy Flynn
c7e4a99219 LibJS: Handle negativity in Temporal's ApplyUnsignedRoundingMode
I don't fully understand the BigInt math here, as the computation for
d1 and d2 don't align with the spec due to BigInt logic. This was
discussed a bit in SerenityOS's Discord some years ago:

https://discord.com/channels/830522505605283862/851522357734408232/978786665306918932

But some new tests in test262 indicate that we need to handle negative
values here, instead of just throwing away the sign.
2025-11-14 06:32:49 -05:00
Psychpsyo
100f37995f Everywhere: Clean up AD-HOC and FIXME comments without colons 2025-11-13 15:56:04 +01:00
Timothy Flynn
a8514a2c29 LibJS: Do not assume cyclic modules have a cycle root
This is a normative change in the ECMA-262 spec. See:
939b993
2025-11-13 14:05:18 +01:00
Timothy Flynn
5c0fdd371a LibJS: Mark invocation to ParseMonthCode as infallible
This is an editorial change in the Temporal proposal. See:
c1f7bd5

Note the related assertion here was a bit silly. It was effectively:

    if (!cond) { return; }
    VERIFY(cond);
2025-11-12 16:20:04 -05:00
Timothy Flynn
041c4f4c79 LibJS: Remove unnecessary Temporal month code check
This is an editorial change in the Temporal proposal. See:
9110854

This change actually exposed a bug in our validator for month codes
(which is only used by this same function). We would previously allow
"M00" as a month code, which is invalid (it must be "M00L").
2025-11-12 16:20:04 -05:00
Timothy Flynn
bf3481b301 LibJS: Explicitly state integer limits for UTC offset minutes and ns
This is an editorial change in the Temporal proposal. See:
1fdf09a

Note that the integer limits in the above commit are in spec headers,
which we don't copy to our implementation.
2025-11-12 16:20:04 -05:00
Timothy Flynn
462e7b0c87 LibJS: Introduce Time Zone Identifier Parse Records to Temporal
This is an editorial change in the Temporal proposal. See:
96bb9b0

Note that we already had a struct for this, but now that it has a proper
name and spec link, this renames it to match other Parse Records and
places it alongside them.
2025-11-12 16:20:04 -05:00
Jelle Raaijmakers
cb333c53e7 LibJS: Remove unused NativeFunction::m_name_string 2025-11-12 14:39:14 +01:00
Andreas Kling
201803f601 LibJS: Cache length-in-code-units in SourceCode
This avoids some bit twiddling whenever accessing the length in code
units in the lexer.
2025-11-09 12:14:03 +01:00