We don't need nanosecond precision here anyways, as we only display
millisecond resolution.
This uses our simple duration formatter from AK, which is updated to
accept a Duration here. This method did not have any users after the
move from Serenity.
The Duration record no longer exists in Temporal. Implement it according
to the DurationFormat spec to prepare for its removal from our Temporal
implementation.
We also implement the DurationSign AO here as well, as the Temporal
implementation will now require a Temporal.Duration JS object.
Previously it was only pushing the module context for the call to
capture the module execution context. This is incorrect, as the capture
occurs upon function construction. This resulted in it capturing the
execution context that execute_module was called from, instead of the
newly created module_context.
f87041bf3a/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp (L92)
This can be demonstrated with the following setup:
index.html:
```html
<script>
var foo = 1;
</script>
<script type="module">
import {test} from "./scriptA.mjs";
</script>
```
scriptA.mjs:
```js
function foo() {
return {a: "b"};
}
export let test = await foo();
```
Before this fix, this would throw:
```
[TypeError] 1 is not a function (evaluated from 'foo')
at module code with top-level await
at module code with top-level await
at <unknown>
at <unknown>
```
Fixes#2245.
Resulting in a massive rename across almost everywhere! Alongside the
namespace change, we now have the following names:
* JS::NonnullGCPtr -> GC::Ref
* JS::GCPtr -> GC::Ptr
* JS::HeapFunction -> GC::Function
* JS::CellImpl -> GC::Cell
* JS::Handle -> GC::Root
Instead, smuggle it in as a `void*` private data and let Javascript
aware code cast out that pointer to a VM&.
In order to make this split, rename JS::Cell to JS::CellImpl. Once we
have a LibGC, this will become GC::Cell. CellImpl then has no specific
knowledge of the VM& and Realm&. That knowledge is instead put into
JS::Cell, which inherits from CellImpl. JS::Cell is responsible for
JavaScript's realm initialization, as well as converting of the void*
private data to what it knows should be the VM&.
NanBoxedValue is intended to be a GC-allocatable type which is not
specific to javascript, towards the effort of factoring out the GC
implementation from LibJS.
Now that the heap has no knowledge about a JavaScript realm and is
purely for managing the memory of the heap, it does not make sense
to name this function to say that it is a non-realm variant.
The main motivation behind this is to remove JS specifics of the Realm
from the implementation of the Heap.
As a side effect of this change, this is a bit nicer to read than the
previous approach, and in my opinion, also makes it a little more clear
that this method is specific to a JavaScript Realm.
While this does mean that we keep one copy of the stack info in the VM,
and another in the Heap; keeping a separate instance removes one more
instance of coupling between the heap and LibJS specific details.
There is definitely a possibility I am misunderstanding the reason
behind it - but this does not appear neccessary. The VM owns both the
string cache and Heap. On destruction, the VM should clear out both
the heap and its string cache.
While this is used in the implementation of Runtime objects itself, Heap
seems like a more appropriate home. This will also help in factoring out
the GC implementation into it's own library as the heap explicitly has
knowledge of WeakContainer.
When the cached value was not an accessor, it was simply ignored.
This is the value we really want, so we can just return it.
Shows up to 5x improvements on some benchmarks,
and 1.4x in general js-benchmarks.
Async functions whose promise is never resolved were leaking, since they
had a strong root JS::Handle on themselves.
This doesn't appear to actually be necessary, since the wrapper will be
kept alive as long as it's reachable (and if it's not reachable, nobody
is going to resolve/reject the promise either).
This fixes the vast majority of leaks on Speedometer, bringing memory
usage at the end of a full run from ~12 GiB to ~3 GiB.
This fixes an issue where a badly-timed garbage collection could swallow
a static field initializer.
Caught by running test262 in GC-on-every-allocation mode.
We were miscalculating the length of the buffer in pointer-sized chunks,
which is what the conservative root scan cares about.
This could cause some values to be prematurely garbage-collected.
This is really just a type alias for NonnullGCPtr<T>, but it provides
a way to have non-owning non-visited NonnullGCPtr<T> without getting
yelled at by the Clang plugin for catching GC errors.
We were previously dumping the address of the cell pointer instead of
the address of the cell itself. This was causing mysterious orphans
in GC dumps, and it took me way too long to figure this out.
The following syntax is valid:
```js
e?.example / 1.2
```
Previously, the `/` would be treated as a unterminated regex literal,
because it was calling the regular `consume` instead of
`consume_and_allow_division`.
This is what is done when parsing IdentifierNames in
parse_secondary_expression when a period is encountered.
Allows us to parse clients-main-[hash].js on https://ubereats.com/
Problem:
- Many constructors are defined as `{}` rather than using the ` =
default` compiler-provided constructor.
- Some types provide an implicit conversion operator from `nullptr_t`
instead of requiring the caller to default construct. This violates
the C++ Core Guidelines suggestion to declare single-argument
constructors explicit
(https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c46-by-default-declare-single-argument-constructors-explicit).
Solution:
- Change default constructors to use the compiler-provided default
constructor.
- Remove implicit conversion operators from `nullptr_t` and change
usage to enforce type consistency without conversion.
Yay for more spec compliance! This is pretty easy as everything using
to_size_t() should just be using one of the other abstract operations we
already have implemented.
This allows us to get rid of get_length() in ArrayPrototype, which is
basically a slightly incorrect implementation of length_of_array_like(),
and then finally remove to_size_t()!
Also fixes a couple of "argument is undefined" vs "argument isn't given"
issues along the way.
The pseudo-code from the spec says "Assert: Type(obj) is Object.", so we
can just enforce this at compile time rather than taking it literally
and doing "ASSERT(value.is_object())".
Also fix an issue where the absence of a "length" property on the object
would cause a crash (to_number() on empty value).
This adds a String.prototype.split implementation modelled after
ECMA262 specification.
Additionally, `Value::to_u32` was added as an implementation of
the standard `ToUint32` abstract operation.
There is a tiny kludge for when the separator is an empty string.
Basic tests and visiting google.com prove that this is working.
This was missing a "toInt32()" which returns 0 for NaN and Infinity.
From the spec:
6.1.6.1.2 Number::bitwiseNOT ( x )
The abstract operation Number::bitwiseNOT takes argument x (a Number).
It performs the following steps when called:
Let oldValue be ! ToInt32(x).
Return the result of applying bitwise complement to oldValue.
The mathematical value of the result is exactly representable as
a 32-bit two's complement bit string.
Fixes#4868.
When constructing a GlobalObject, it has to pass itself as the global
object to its own Shape. Since this is done in the Object constructor,
and Object is a base class of GlobalObject, it's not yet valid to cast
"this" to a GlobalObject*.
Fix this by having Shape store the global object as an Object& and move
Shape::global_object() to GlobalObject.h where we can at least perform a
valid static_cast in the getter.
Found by oss-fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=29267