Commit graph

1843 commits

Author SHA1 Message Date
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
Andreas Kling
7c7a035347 LibJS: Cache an Utf16View for the full code string in SourceCode
This avoids doing the ASCII/UTF-16 flag check every time we access
character data from the lexer.
2025-11-09 12:14:03 +01:00
Andreas Kling
fa44fd58d8 LibJS: Remove ParserState::lookahead_lexer
The lookahead lexer used by next_token() no longer needs to be kept
alive, since tokens created by Parser::next_token() now have any string
views guaranteed safe by the fact that they point into the one true
SourceCode provided by whoever set up the lexer.
2025-11-09 12:14:03 +01:00
Andreas Kling
0dacc94edd LibJS: Have JS::Lexer take a JS::SourceCode as input
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.
2025-11-09 12:14:03 +01:00
Andreas Kling
9ca25e55d7 LibJS: Rearrange Lexer members to shrink it by 16 bytes
This is useful since the parser's state saving mechanism works by
copying the lexer object.
2025-11-09 12:14:03 +01:00
Andreas Kling
81671c3f0f LibJS: Remove unnecessary ParsedIdentifiers thing from Lexer
Identifier tokens are stored as Utf16FlyString, so there's no need to
forcibly keep them alive through this mechanism. (It was useful when
tokens only had string views.)
2025-11-09 12:14:03 +01:00
Andreas Kling
fdd9413e71 LibJS: Avoid some unnecessary ref count churn in parser 2025-11-09 12:14:03 +01:00
Andreas Kling
841fe0b51c LibJS: Don't store current token in both Lexer and Parser
Just give Parser a way to access the one stored in Lexer.
2025-11-09 12:14:03 +01:00
Andreas Kling
d3e8fbd9cd LibJS: Don't create unique FunctionParameters for every empty param set 2025-11-09 12:14:03 +01:00
Andreas Kling
72aa90312a LibJS: Make JS::Token::message an enum instead of a StringView
Just to make JS::Token a little smaller.
2025-11-09 12:14:03 +01:00