Commit graph

12 commits

Author SHA1 Message Date
mikiubo
d4df0e1db9 LibWeb: Make Event.currentTarget return WindowProxy instead of Window
Make WindowProxy implement the EventTarget interface. Add a new method
current_target_for_bindings() that returns a WindowProxy object instead
of directly exposing the Window object.

These changes fixes several WPT tests that contain `window ===
currentTarget`.
2025-10-15 15:36:34 +02:00
Aliaksandr Kalenik
451c947c3f LibJS: Fast-path own-property enumeration and reduce descriptor lookups
Before this change, PropertyNameIterator (used by for..in) and
`Object::enumerable_own_property_names()` (used by `Object.keys()`,
`Object.values()`, and `Object.entries()`) enumerated an object's own
enumerable properties exactly as the spec prescribes:
- Call `internal_own_property_keys()`, allocating a list of JS::Value
  keys.
- For each key, call internal_get_own_property() to obtain a
  descriptor and check `[[Enumerable]]`.

While that is required in the general case (e.g. for Proxy objects or
platform/exotic objects that override `[[OwnPropertyKeys]]`), it's
overkill for ordinary JS objects that store their own properties in the
shape table and indexed-properties storage.

This change introduces `for_each_own_property_with_enumerability()`,
which, for objects where
`eligible_for_own_property_enumeration_fast_path()` is `true`, lets us
read the enumerability directly from shape metadata (and from
indexed-properties storage) without a per-property descriptor lookup.
When we cannot avoid `internal_get_own_property()`, we still
benefit by skipping the temporary `Vector<Value>` of keys and avoiding
the unnecessary round-trip between PropertyKey and Value.
2025-09-21 15:06:32 +02:00
Aliaksandr Kalenik
d45f8a3081 LibJS: Add inline caching for adding new own properties to objects
We already had IC support in PutById for the following cases:
- Changing an existing own property
- Calling a setter located in the prototype chain

This was enough to speed up code where structurally identical objects
(same shape) are processed in a loop:
```js
const arr = [{ a: 1 }, { a: 2 }, { a: 3 }];
for (let obj of arr) {
    obj.a += 1;
}
```

However, creating structurally identical objects in a loop was still
slow:
```js
for (let i = 0; i < 10_000_000; i++) {
    const o = {};
    o.a = 1;
    o.b = 2;
    o.c = 3;
}
```

This change addresses that by adding a new IC type that caches both the
source and target shapes, allowing property additions to be fast-pathed
by directly jumping to the shape that already includes the new property.
2025-09-17 12:44:44 +02:00
Aliaksandr Kalenik
a54215c07d LibJS: Make internal_define_own_property() save added property offset
...in `PropertyDescriptor`. This is required for the upcoming change
that needs to know offset of newly added properties to set up inline
caching.
2025-09-17 12:44:44 +02:00
ayeteadoe
3df8e00d91 LibWeb: Enable EXPLICIT_SYMBOL_EXPORT 2025-08-23 16:04:36 -06:00
Tim Ledbetter
2903defcfc Revert "LibJS+LibWeb: Return Vector<PropertyKey> from…
internal_own_property_keys"

This reverts commit 5ee810f772.
2025-05-16 06:33:09 +01:00
Aliaksandr Kalenik
5ee810f772 LibJS+LibWeb: Return Vector<PropertyKey> from internal_own_property_keys
By doing that we avoid lots of `PropertyKey` -> `Value` -> `PropertyKey`
transforms, which are quite expensive because of underlying
`FlyString` -> `PrimitiveString` -> `FlyString` conversions.

10% improvement on MicroBench/object-keys.js
2025-05-15 14:12:18 -04:00
Andreas Kling
183c847c80 LibJS: Cache PutById to setters in the prototype chain
This is *extremely* common on the web, but barely shows up at all in
JavaScript benchmarks.

A typical example is setting Element.innerHTML on a HTMLDivElement.
HTMLDivElement doesn't have innerHTML, so it has to travel up the
prototype chain until it finds it.

Before this change, we didn't cache this at all, so we had to travel
the prototype chain every time a setter like this was used.

We now use the same mechanism we already had for GetBydId and cache
PutById setter accesses in the prototype chain as well.

1.74x speedup on MicroBench/setter-in-prototype-chain.js
2025-05-05 15:21:43 +02:00
Andreas Kling
d8188c9f14 LibJS+LibWeb: Add JS::Object::fast_is<T> helpers for some LibWeb types
These are slightly unfortunate as we're crossing the library boundary,
but there's precedent with Object::is_dom_node(), and these are just
knocking down a few more items that were showing up in profiles.
2025-04-18 14:45:56 +02:00
Andreas Kling
3bfb0534be LibGC: Rename MarkedVector => RootVector
Let's try to make it a bit more clear that this is a Vector of GC roots.
2024-12-26 19:10:44 +01:00
Shannon Booth
f87041bf3a LibGC+Everywhere: Factor out a LibGC from LibJS
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
2024-11-15 14:49:20 +01:00
Timothy Flynn
93712b24bf Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
Renamed from Userland/Libraries/LibWeb/HTML/WindowProxy.h (Browse further)