You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/content/newsletters/2025-05-31.mdx
+74-3Lines changed: 74 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -21,6 +21,14 @@ Ladybird is entirely funded by the generous support of companies and individuals
21
21
22
22
We are incredibly grateful for their support. If you're interested in sponsoring the project, please [contact us](mailto:contact@ladybird.org).
23
23
24
+
### Our nonprofit is now officially tax-exempt
25
+
26
+
The IRS has officially recognized the Ladybird Browser Initiative as a public charity, granting us tax-exempt status.
27
+
28
+
This is retroactive to March of 2024, which means any donations made since then could be eligible for tax exemption (depending on the origin country of the donation, etc.)
29
+
30
+
You can find all the relevant information on our new [Organization](https://ladybird.org/organization/) page.
31
+
24
32
### Web Platform Tests (WPT)
25
33
26
34
As usual, we've been making solid progress on WPT. This month, we've squeezed out a new **?** passing tests for a total of **?**.
@@ -29,6 +37,16 @@ For context, here are the top 6 engines at the end of April vs end of May:
29
37
30
38
FIXME: Graph
31
39
40
+
### New JavaScript date parser
41
+
42
+
The JavaScript specification only requires that you support one date format (ISO8601). Anything else is implementation defined, and in practice all major engines support a wide range of weird date formats.
43
+
44
+
This has long been a source of web compatibility issues for us, and we've had many cases where weird bugs were painstakingly traced back to not being able to parse a date format we'd never seen before.
45
+
46
+
In the past, we implemented date parsing by trying a list of specific known formats that we'd seen on the web. This list was frequently appended to.
47
+
48
+
We now have a new, more tolerant parser that allows all kinds of arbitrary sequences without relying on a strict list. This is more similar to what other engines do, and makes us far more likely to handle a date format we've never seen before.
49
+
32
50
### Clipboard APIs
33
51
34
52
There are a handful of [clipboard APIs](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API) available for
@@ -45,11 +63,64 @@ much better aligned with the spec. The last remaining feature that we hadn't imp
45
63
developers to transfer streams via `postMessage()` to, for example, a web worker. We've now implemented this feature,
46
64
and as a result, we now have a complete streams implementation!
47
65
48
-
### JavaScript engine optimizations
66
+
### JS optimization: polymorphic inline caches
67
+
68
+
Until now, all our inline caches have been monomorphic. While this doesn't matter very much for the classic JavaScript benchmarks, real-world web content tends to do a lot of polymorphic access.
69
+
70
+
To better support this, inline caches have been expanded to support up to 4 distinct shapes per property access. This greatly improved cache hit rates on Speedometer (from 88% to 97%!)
71
+
72
+
Here's a contrived example to illustrate how a polymorphic cache helps us:
73
+
74
+
```js
75
+
functionreadFoo(o) {
76
+
// The o.foo property access here would be a cache miss in the monomorphic case.
77
+
// That happens because o.foo is property #0 for `o1` below, but property #1 for `o2`.
78
+
// With polymorphic caching, we now remember the shapes for both `o1` and `o2` and always hit!
79
+
returno.foo;
80
+
}
81
+
82
+
consto1= { foo:123 };
83
+
consto2= { bar:123, foo:456 };
84
+
for (let i =0; i <1000; ++i) {
85
+
readFoo(o1);
86
+
readFoo(o2);
87
+
}
88
+
```
89
+
90
+
### JS optimization: faster bound function calls
91
+
92
+
A bound function is a bundled function call with a pre-populated set of arguments.
93
+
94
+
Before this month, we implemented them as generic function calls, which meant that two stack frames were created. By streamlining the implementation, we've cut that down to a single stack frame.
95
+
96
+
```js
97
+
functionbar(a) {
98
+
console.log(a);
99
+
}
100
+
101
+
functionfoo() {
102
+
let boundBar =bar.bind(null, 123);
103
+
boundBar();
104
+
}
105
+
foo();
106
+
107
+
// Stack before:
108
+
// [global context]
109
+
// foo
110
+
// [bound function call helper]
111
+
// bar
112
+
113
+
// Stack after:
114
+
// [global context]
115
+
// foo
116
+
// bar
117
+
```
118
+
119
+
### JS optimization: faster iteration over built-in types
49
120
50
-
We've added new bytecode instruction that avoid creating temporary `{ done, value }` result objects when iterating over built-in types like Array, Map, Set and String. This means `for..of`, `for..in` and the spread operator now run with significantly less overhead.
121
+
We've added new bytecode instruction that avoid creating temporary `{ done, value }` result objects when iterating over built-in types like `Array`, `Map`, `Set` and `String`. This means `for..of`, `for..in` and the spread operator now run with significantly less overhead.
51
122
52
-
We've applied a similar optimization to async functions, which internally rely on generators, and made them faster as well by avoid temporary objects allocation.
123
+
We've also applied a similar optimization to `async` functions, which internally rely on generators, and made them faster as well by avoid temporary objects allocation.
53
124
54
125
Array element assignment now has a fast path. If objects in the array’s prototype chain haven’t been modified and the array is not a proxy, we skip the prototype lookup required for potential setters and instead write the value directly into the array’s storage.
0 commit comments