diff --git a/.eleventy.js b/.eleventy.js index 1583d9b64..7bc166176 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -181,6 +181,7 @@ module.exports = (eleventyConfig) => { // Copy assets that don’t require a build step. eleventyConfig.addPassthroughCopy('src/favicon.ico'); + eleventyConfig.addPassthroughCopy('src/favicon.png'); eleventyConfig.addPassthroughCopy('src/robots.txt'); eleventyConfig.addPassthroughCopy('src/_img'); eleventyConfig.addPassthroughCopy('src/_css/img'); diff --git a/.gitignore b/.gitignore index f9e667f75..8b70d746a 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,7 @@ dist/ firebase-debug.log node_modules/ package-lock.json +.DS_Store +Desktop.ini +._* +Thumbs.db diff --git a/firebase.json b/firebase.json index b2bd2d4ca..5b8e51257 100644 --- a/firebase.json +++ b/firebase.json @@ -78,17 +78,13 @@ { "source": "/sw.js", "headers": [ - { - "key": "Cache-Control", - "value": "no-cache" - }, { "key": "Content-Type", "value": "text/javascript;charset=utf-8" }, { "key": "Cache-Control", - "value": "max-age=31557600" + "value": "public, max-age=600, stale-while-revalidate=3600" } ] }, @@ -101,7 +97,7 @@ }, { "key": "Cache-Control", - "value": "max-age=31557600" + "value": "max-age=604800" } ] }, @@ -128,7 +124,7 @@ "headers": [ { "key": "Cache-Control", - "value": "max-age=31557600" + "value": "max-age=604800" } ] }, @@ -137,7 +133,7 @@ "headers": [ { "key": "Cache-Control", - "value": "max-age=31557600" + "value": "max-age=604800" } ] } diff --git a/src/_css/img/safari.png b/src/_css/img/safari.png deleted file mode 100644 index c09ac65d3..000000000 Binary files a/src/_css/img/safari.png and /dev/null differ diff --git a/src/_css/main.css b/src/_css/main.css index a0e009e68..e559acfbc 100644 --- a/src/_css/main.css +++ b/src/_css/main.css @@ -191,7 +191,13 @@ hr { font-size: 0.8em; } .footnote-item:target { - background: var(--lightyellow); + background-color: var(--lightyellow); + --html-color: var(--black); + --main-background: var(--white); + --main-and-footer-link-color: var(--darkblue); +} +.footnote-item:target > * { + color: var(--html-color); } .retweet { display: inline-block; diff --git a/src/_img/avatars/README.md b/src/_img/avatars/README.md new file mode 100644 index 000000000..0f166d761 --- /dev/null +++ b/src/_img/avatars/README.md @@ -0,0 +1,5 @@ +# Avatar Images + +This folder contains 192x192px avif files. +You can generate them easily on using AVIF encoder with +a low quality settings of around 40. diff --git a/src/_img/avatars/adam-klein.avif b/src/_img/avatars/adam-klein.avif index afcc2b8d1..63503234d 100644 Binary files a/src/_img/avatars/adam-klein.avif and b/src/_img/avatars/adam-klein.avif differ diff --git a/src/_img/avatars/adam-klein.jpg b/src/_img/avatars/adam-klein.jpg deleted file mode 100644 index 63172d279..000000000 Binary files a/src/_img/avatars/adam-klein.jpg and /dev/null differ diff --git a/src/_img/avatars/adam-klein@2x.avif b/src/_img/avatars/adam-klein@2x.avif deleted file mode 100644 index 63503234d..000000000 Binary files a/src/_img/avatars/adam-klein@2x.avif and /dev/null differ diff --git a/src/_img/avatars/adam-klein@2x.jpg b/src/_img/avatars/adam-klein@2x.jpg deleted file mode 100644 index e6cbe2bdf..000000000 Binary files a/src/_img/avatars/adam-klein@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/addy-osmani.avif b/src/_img/avatars/addy-osmani.avif index 8bc14daf4..ead8d85d5 100644 Binary files a/src/_img/avatars/addy-osmani.avif and b/src/_img/avatars/addy-osmani.avif differ diff --git a/src/_img/avatars/addy-osmani.jpg b/src/_img/avatars/addy-osmani.jpg deleted file mode 100644 index ceba8622e..000000000 Binary files a/src/_img/avatars/addy-osmani.jpg and /dev/null differ diff --git a/src/_img/avatars/addy-osmani@2x.avif b/src/_img/avatars/addy-osmani@2x.avif deleted file mode 100644 index ead8d85d5..000000000 Binary files a/src/_img/avatars/addy-osmani@2x.avif and /dev/null differ diff --git a/src/_img/avatars/addy-osmani@2x.jpg b/src/_img/avatars/addy-osmani@2x.jpg deleted file mode 100644 index f681b78be..000000000 Binary files a/src/_img/avatars/addy-osmani@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/alon-zakai.avif b/src/_img/avatars/alon-zakai.avif index 242626e27..c00448a23 100644 Binary files a/src/_img/avatars/alon-zakai.avif and b/src/_img/avatars/alon-zakai.avif differ diff --git a/src/_img/avatars/alon-zakai.jpg b/src/_img/avatars/alon-zakai.jpg deleted file mode 100644 index 53f1c9808..000000000 Binary files a/src/_img/avatars/alon-zakai.jpg and /dev/null differ diff --git a/src/_img/avatars/alon-zakai@2x.avif b/src/_img/avatars/alon-zakai@2x.avif deleted file mode 100644 index c00448a23..000000000 Binary files a/src/_img/avatars/alon-zakai@2x.avif and /dev/null differ diff --git a/src/_img/avatars/alon-zakai@2x.jpg b/src/_img/avatars/alon-zakai@2x.jpg deleted file mode 100644 index 74d947806..000000000 Binary files a/src/_img/avatars/alon-zakai@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/ana-pesko.avif b/src/_img/avatars/ana-pesko.avif index 95d8ecb5d..7794e5bfe 100644 Binary files a/src/_img/avatars/ana-pesko.avif and b/src/_img/avatars/ana-pesko.avif differ diff --git a/src/_img/avatars/ana-pesko.jpg b/src/_img/avatars/ana-pesko.jpg deleted file mode 100644 index 52c5723db..000000000 Binary files a/src/_img/avatars/ana-pesko.jpg and /dev/null differ diff --git a/src/_img/avatars/ana-pesko@2x.avif b/src/_img/avatars/ana-pesko@2x.avif deleted file mode 100644 index 7794e5bfe..000000000 Binary files a/src/_img/avatars/ana-pesko@2x.avif and /dev/null differ diff --git a/src/_img/avatars/ana-pesko@2x.jpg b/src/_img/avatars/ana-pesko@2x.jpg deleted file mode 100644 index 8a944d6d8..000000000 Binary files a/src/_img/avatars/ana-pesko@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/andreas-haas.avif b/src/_img/avatars/andreas-haas.avif index b612d139b..7ec3d7391 100644 Binary files a/src/_img/avatars/andreas-haas.avif and b/src/_img/avatars/andreas-haas.avif differ diff --git a/src/_img/avatars/andreas-haas.jpg b/src/_img/avatars/andreas-haas.jpg deleted file mode 100644 index a052600b4..000000000 Binary files a/src/_img/avatars/andreas-haas.jpg and /dev/null differ diff --git a/src/_img/avatars/andreas-haas@2x.avif b/src/_img/avatars/andreas-haas@2x.avif deleted file mode 100644 index 7ec3d7391..000000000 Binary files a/src/_img/avatars/andreas-haas@2x.avif and /dev/null differ diff --git a/src/_img/avatars/andreas-haas@2x.jpg b/src/_img/avatars/andreas-haas@2x.jpg deleted file mode 100644 index e7285ca70..000000000 Binary files a/src/_img/avatars/andreas-haas@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/anton-bikineev.avif b/src/_img/avatars/anton-bikineev.avif index 8e03b11fe..1c9bdda3b 100644 Binary files a/src/_img/avatars/anton-bikineev.avif and b/src/_img/avatars/anton-bikineev.avif differ diff --git a/src/_img/avatars/anton-bikineev.jpg b/src/_img/avatars/anton-bikineev.jpg deleted file mode 100644 index 6aa9b8f2d..000000000 Binary files a/src/_img/avatars/anton-bikineev.jpg and /dev/null differ diff --git a/src/_img/avatars/anton-bikineev@2x.avif b/src/_img/avatars/anton-bikineev@2x.avif deleted file mode 100644 index 1c9bdda3b..000000000 Binary files a/src/_img/avatars/anton-bikineev@2x.avif and /dev/null differ diff --git a/src/_img/avatars/anton-bikineev@2x.jpg b/src/_img/avatars/anton-bikineev@2x.jpg deleted file mode 100644 index 7700d47f9..000000000 Binary files a/src/_img/avatars/anton-bikineev@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/ben-titzer.avif b/src/_img/avatars/ben-titzer.avif index e7c3b2a9e..7ee9ceaf9 100644 Binary files a/src/_img/avatars/ben-titzer.avif and b/src/_img/avatars/ben-titzer.avif differ diff --git a/src/_img/avatars/ben-titzer.jpg b/src/_img/avatars/ben-titzer.jpg deleted file mode 100644 index 05fedef8c..000000000 Binary files a/src/_img/avatars/ben-titzer.jpg and /dev/null differ diff --git a/src/_img/avatars/ben-titzer@2x.avif b/src/_img/avatars/ben-titzer@2x.avif deleted file mode 100644 index 7ee9ceaf9..000000000 Binary files a/src/_img/avatars/ben-titzer@2x.avif and /dev/null differ diff --git a/src/_img/avatars/ben-titzer@2x.jpg b/src/_img/avatars/ben-titzer@2x.jpg deleted file mode 100644 index 2e9d1c4cb..000000000 Binary files a/src/_img/avatars/ben-titzer@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/benedikt-meurer.avif b/src/_img/avatars/benedikt-meurer.avif index a7cd17f56..c36cceffb 100644 Binary files a/src/_img/avatars/benedikt-meurer.avif and b/src/_img/avatars/benedikt-meurer.avif differ diff --git a/src/_img/avatars/benedikt-meurer.jpg b/src/_img/avatars/benedikt-meurer.jpg deleted file mode 100644 index 855fc5500..000000000 Binary files a/src/_img/avatars/benedikt-meurer.jpg and /dev/null differ diff --git a/src/_img/avatars/benedikt-meurer@2x.avif b/src/_img/avatars/benedikt-meurer@2x.avif deleted file mode 100644 index c36cceffb..000000000 Binary files a/src/_img/avatars/benedikt-meurer@2x.avif and /dev/null differ diff --git a/src/_img/avatars/benedikt-meurer@2x.jpg b/src/_img/avatars/benedikt-meurer@2x.jpg deleted file mode 100644 index ffb0a6b98..000000000 Binary files a/src/_img/avatars/benedikt-meurer@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/bill-budge.avif b/src/_img/avatars/bill-budge.avif index 17887bb0a..fc9b45cb2 100644 Binary files a/src/_img/avatars/bill-budge.avif and b/src/_img/avatars/bill-budge.avif differ diff --git a/src/_img/avatars/bill-budge.jpg b/src/_img/avatars/bill-budge.jpg deleted file mode 100644 index 0403f0fa2..000000000 Binary files a/src/_img/avatars/bill-budge.jpg and /dev/null differ diff --git a/src/_img/avatars/bill-budge@2x.avif b/src/_img/avatars/bill-budge@2x.avif deleted file mode 100644 index fc9b45cb2..000000000 Binary files a/src/_img/avatars/bill-budge@2x.avif and /dev/null differ diff --git a/src/_img/avatars/bill-budge@2x.jpg b/src/_img/avatars/bill-budge@2x.jpg deleted file mode 100644 index 1f70708aa..000000000 Binary files a/src/_img/avatars/bill-budge@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/camillo-bruni.avif b/src/_img/avatars/camillo-bruni.avif index 6220b8fe3..8c3b063dc 100644 Binary files a/src/_img/avatars/camillo-bruni.avif and b/src/_img/avatars/camillo-bruni.avif differ diff --git a/src/_img/avatars/camillo-bruni.jpg b/src/_img/avatars/camillo-bruni.jpg deleted file mode 100644 index 1195acea8..000000000 Binary files a/src/_img/avatars/camillo-bruni.jpg and /dev/null differ diff --git a/src/_img/avatars/camillo-bruni@2x.avif b/src/_img/avatars/camillo-bruni@2x.avif deleted file mode 100644 index 8c3b063dc..000000000 Binary files a/src/_img/avatars/camillo-bruni@2x.avif and /dev/null differ diff --git a/src/_img/avatars/camillo-bruni@2x.jpg b/src/_img/avatars/camillo-bruni@2x.jpg deleted file mode 100644 index d04dbae29..000000000 Binary files a/src/_img/avatars/camillo-bruni@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/clemens-backes.avif b/src/_img/avatars/clemens-backes.avif index bc1417e27..6815b425b 100644 Binary files a/src/_img/avatars/clemens-backes.avif and b/src/_img/avatars/clemens-backes.avif differ diff --git a/src/_img/avatars/clemens-backes.jpg b/src/_img/avatars/clemens-backes.jpg deleted file mode 100644 index 33ac00628..000000000 Binary files a/src/_img/avatars/clemens-backes.jpg and /dev/null differ diff --git a/src/_img/avatars/clemens-backes@2x.avif b/src/_img/avatars/clemens-backes@2x.avif deleted file mode 100644 index 6815b425b..000000000 Binary files a/src/_img/avatars/clemens-backes@2x.avif and /dev/null differ diff --git a/src/_img/avatars/clemens-backes@2x.jpg b/src/_img/avatars/clemens-backes@2x.jpg deleted file mode 100644 index dc2b0966d..000000000 Binary files a/src/_img/avatars/clemens-backes@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/dan-clark.avif b/src/_img/avatars/dan-clark.avif index 39d7c14fa..92fcb4a5e 100644 Binary files a/src/_img/avatars/dan-clark.avif and b/src/_img/avatars/dan-clark.avif differ diff --git a/src/_img/avatars/dan-clark.jpg b/src/_img/avatars/dan-clark.jpg deleted file mode 100644 index b8299132f..000000000 Binary files a/src/_img/avatars/dan-clark.jpg and /dev/null differ diff --git a/src/_img/avatars/dan-clark@2x.avif b/src/_img/avatars/dan-clark@2x.avif deleted file mode 100644 index 92fcb4a5e..000000000 Binary files a/src/_img/avatars/dan-clark@2x.avif and /dev/null differ diff --git a/src/_img/avatars/dan-clark@2x.jpg b/src/_img/avatars/dan-clark@2x.jpg deleted file mode 100644 index a8e3502a1..000000000 Binary files a/src/_img/avatars/dan-clark@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/dan-elphick.avif b/src/_img/avatars/dan-elphick.avif index 8309f2a52..0ececd946 100644 Binary files a/src/_img/avatars/dan-elphick.avif and b/src/_img/avatars/dan-elphick.avif differ diff --git a/src/_img/avatars/dan-elphick.jpg b/src/_img/avatars/dan-elphick.jpg deleted file mode 100644 index 231334070..000000000 Binary files a/src/_img/avatars/dan-elphick.jpg and /dev/null differ diff --git a/src/_img/avatars/dan-elphick@2x.avif b/src/_img/avatars/dan-elphick@2x.avif deleted file mode 100644 index 0ececd946..000000000 Binary files a/src/_img/avatars/dan-elphick@2x.avif and /dev/null differ diff --git a/src/_img/avatars/dan-elphick@2x.jpg b/src/_img/avatars/dan-elphick@2x.jpg deleted file mode 100644 index 2cbdc6191..000000000 Binary files a/src/_img/avatars/dan-elphick@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/darius-mercadier.avif b/src/_img/avatars/darius-mercadier.avif index 05c6df817..915e682dc 100644 Binary files a/src/_img/avatars/darius-mercadier.avif and b/src/_img/avatars/darius-mercadier.avif differ diff --git a/src/_img/avatars/darius-mercadier.jpg b/src/_img/avatars/darius-mercadier.jpg deleted file mode 100644 index 33d76cc8e..000000000 Binary files a/src/_img/avatars/darius-mercadier.jpg and /dev/null differ diff --git a/src/_img/avatars/darius-mercadier@2x.avif b/src/_img/avatars/darius-mercadier@2x.avif deleted file mode 100644 index 915e682dc..000000000 Binary files a/src/_img/avatars/darius-mercadier@2x.avif and /dev/null differ diff --git a/src/_img/avatars/darius-mercadier@2x.jpg b/src/_img/avatars/darius-mercadier@2x.jpg deleted file mode 100644 index d85e70d25..000000000 Binary files a/src/_img/avatars/darius-mercadier@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/domenic-denicola.avif b/src/_img/avatars/domenic-denicola.avif index 629844f56..b6d0c5ee2 100644 Binary files a/src/_img/avatars/domenic-denicola.avif and b/src/_img/avatars/domenic-denicola.avif differ diff --git a/src/_img/avatars/domenic-denicola.jpg b/src/_img/avatars/domenic-denicola.jpg deleted file mode 100644 index 09d28a6b1..000000000 Binary files a/src/_img/avatars/domenic-denicola.jpg and /dev/null differ diff --git a/src/_img/avatars/domenic-denicola@2x.avif b/src/_img/avatars/domenic-denicola@2x.avif deleted file mode 100644 index b6d0c5ee2..000000000 Binary files a/src/_img/avatars/domenic-denicola@2x.avif and /dev/null differ diff --git a/src/_img/avatars/domenic-denicola@2x.jpg b/src/_img/avatars/domenic-denicola@2x.jpg deleted file mode 100644 index 648191578..000000000 Binary files a/src/_img/avatars/domenic-denicola@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/dominik-infuehr.avif b/src/_img/avatars/dominik-infuehr.avif index dda1c7062..cd36ab220 100644 Binary files a/src/_img/avatars/dominik-infuehr.avif and b/src/_img/avatars/dominik-infuehr.avif differ diff --git a/src/_img/avatars/dominik-infuehr.jpg b/src/_img/avatars/dominik-infuehr.jpg deleted file mode 100644 index c8e91b6a0..000000000 Binary files a/src/_img/avatars/dominik-infuehr.jpg and /dev/null differ diff --git a/src/_img/avatars/dominik-infuehr@2x.avif b/src/_img/avatars/dominik-infuehr@2x.avif deleted file mode 100644 index cd36ab220..000000000 Binary files a/src/_img/avatars/dominik-infuehr@2x.avif and /dev/null differ diff --git a/src/_img/avatars/dominik-infuehr@2x.jpg b/src/_img/avatars/dominik-infuehr@2x.jpg deleted file mode 100644 index a233837a8..000000000 Binary files a/src/_img/avatars/dominik-infuehr@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/frank-tang.avif b/src/_img/avatars/frank-tang.avif index fc9b47988..0ef198d30 100644 Binary files a/src/_img/avatars/frank-tang.avif and b/src/_img/avatars/frank-tang.avif differ diff --git a/src/_img/avatars/frank-tang.jpg b/src/_img/avatars/frank-tang.jpg deleted file mode 100644 index fbd173366..000000000 Binary files a/src/_img/avatars/frank-tang.jpg and /dev/null differ diff --git a/src/_img/avatars/frank-tang@2x.avif b/src/_img/avatars/frank-tang@2x.avif deleted file mode 100644 index 0ef198d30..000000000 Binary files a/src/_img/avatars/frank-tang@2x.avif and /dev/null differ diff --git a/src/_img/avatars/frank-tang@2x.jpg b/src/_img/avatars/frank-tang@2x.jpg deleted file mode 100644 index 3a47bb311..000000000 Binary files a/src/_img/avatars/frank-tang@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/hannes-payer.avif b/src/_img/avatars/hannes-payer.avif index 78a5b3138..29495c08c 100644 Binary files a/src/_img/avatars/hannes-payer.avif and b/src/_img/avatars/hannes-payer.avif differ diff --git a/src/_img/avatars/hannes-payer.jpg b/src/_img/avatars/hannes-payer.jpg deleted file mode 100644 index 08c34ae3e..000000000 Binary files a/src/_img/avatars/hannes-payer.jpg and /dev/null differ diff --git a/src/_img/avatars/hannes-payer@2x.avif b/src/_img/avatars/hannes-payer@2x.avif deleted file mode 100644 index 29495c08c..000000000 Binary files a/src/_img/avatars/hannes-payer@2x.avif and /dev/null differ diff --git a/src/_img/avatars/hannes-payer@2x.jpg b/src/_img/avatars/hannes-payer@2x.jpg deleted file mode 100644 index eea67ac18..000000000 Binary files a/src/_img/avatars/hannes-payer@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/igor-sheludko.avif b/src/_img/avatars/igor-sheludko.avif index 87cb69234..e2228667c 100644 Binary files a/src/_img/avatars/igor-sheludko.avif and b/src/_img/avatars/igor-sheludko.avif differ diff --git a/src/_img/avatars/igor-sheludko.jpg b/src/_img/avatars/igor-sheludko.jpg deleted file mode 100644 index 15655efe5..000000000 Binary files a/src/_img/avatars/igor-sheludko.jpg and /dev/null differ diff --git a/src/_img/avatars/igor-sheludko@2x.avif b/src/_img/avatars/igor-sheludko@2x.avif deleted file mode 100644 index e2228667c..000000000 Binary files a/src/_img/avatars/igor-sheludko@2x.avif and /dev/null differ diff --git a/src/_img/avatars/igor-sheludko@2x.jpg b/src/_img/avatars/igor-sheludko@2x.jpg deleted file mode 100644 index 70f9af2e9..000000000 Binary files a/src/_img/avatars/igor-sheludko@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/ingvar-stepanyan.avif b/src/_img/avatars/ingvar-stepanyan.avif index fafd659d3..3fca160ba 100644 Binary files a/src/_img/avatars/ingvar-stepanyan.avif and b/src/_img/avatars/ingvar-stepanyan.avif differ diff --git a/src/_img/avatars/ingvar-stepanyan.jpg b/src/_img/avatars/ingvar-stepanyan.jpg deleted file mode 100644 index a49bbe792..000000000 Binary files a/src/_img/avatars/ingvar-stepanyan.jpg and /dev/null differ diff --git a/src/_img/avatars/ingvar-stepanyan@2x.avif b/src/_img/avatars/ingvar-stepanyan@2x.avif deleted file mode 100644 index 3fca160ba..000000000 Binary files a/src/_img/avatars/ingvar-stepanyan@2x.avif and /dev/null differ diff --git a/src/_img/avatars/ingvar-stepanyan@2x.jpg b/src/_img/avatars/ingvar-stepanyan@2x.jpg deleted file mode 100644 index 4eb11b0ab..000000000 Binary files a/src/_img/avatars/ingvar-stepanyan@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/jakob-gruber.avif b/src/_img/avatars/jakob-gruber.avif index 19ce493c7..b75c0e03b 100644 Binary files a/src/_img/avatars/jakob-gruber.avif and b/src/_img/avatars/jakob-gruber.avif differ diff --git a/src/_img/avatars/jakob-gruber.jpg b/src/_img/avatars/jakob-gruber.jpg deleted file mode 100644 index f2a7f032b..000000000 Binary files a/src/_img/avatars/jakob-gruber.jpg and /dev/null differ diff --git a/src/_img/avatars/jakob-gruber@2x.avif b/src/_img/avatars/jakob-gruber@2x.avif deleted file mode 100644 index b75c0e03b..000000000 Binary files a/src/_img/avatars/jakob-gruber@2x.avif and /dev/null differ diff --git a/src/_img/avatars/jakob-gruber@2x.jpg b/src/_img/avatars/jakob-gruber@2x.jpg deleted file mode 100644 index f409c836c..000000000 Binary files a/src/_img/avatars/jakob-gruber@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/jakob-kummerow.avif b/src/_img/avatars/jakob-kummerow.avif index f9c411f45..22e4a2a6f 100644 Binary files a/src/_img/avatars/jakob-kummerow.avif and b/src/_img/avatars/jakob-kummerow.avif differ diff --git a/src/_img/avatars/jakob-kummerow.jpg b/src/_img/avatars/jakob-kummerow.jpg deleted file mode 100644 index 291cd29be..000000000 Binary files a/src/_img/avatars/jakob-kummerow.jpg and /dev/null differ diff --git a/src/_img/avatars/jakob-kummerow@2x.avif b/src/_img/avatars/jakob-kummerow@2x.avif deleted file mode 100644 index 22e4a2a6f..000000000 Binary files a/src/_img/avatars/jakob-kummerow@2x.avif and /dev/null differ diff --git a/src/_img/avatars/jakob-kummerow@2x.jpg b/src/_img/avatars/jakob-kummerow@2x.jpg deleted file mode 100644 index f5ea641df..000000000 Binary files a/src/_img/avatars/jakob-kummerow@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/jaroslav-sevcik.avif b/src/_img/avatars/jaroslav-sevcik.avif index 0904d2995..97b618d96 100644 Binary files a/src/_img/avatars/jaroslav-sevcik.avif and b/src/_img/avatars/jaroslav-sevcik.avif differ diff --git a/src/_img/avatars/jaroslav-sevcik.jpg b/src/_img/avatars/jaroslav-sevcik.jpg deleted file mode 100644 index bb003a194..000000000 Binary files a/src/_img/avatars/jaroslav-sevcik.jpg and /dev/null differ diff --git a/src/_img/avatars/jaroslav-sevcik@2x.avif b/src/_img/avatars/jaroslav-sevcik@2x.avif deleted file mode 100644 index 97b618d96..000000000 Binary files a/src/_img/avatars/jaroslav-sevcik@2x.avif and /dev/null differ diff --git a/src/_img/avatars/jaroslav-sevcik@2x.jpg b/src/_img/avatars/jaroslav-sevcik@2x.jpg deleted file mode 100644 index 90c9e8722..000000000 Binary files a/src/_img/avatars/jaroslav-sevcik@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/joyee-cheung.avif b/src/_img/avatars/joyee-cheung.avif index 646ca0082..bbda89cd1 100644 Binary files a/src/_img/avatars/joyee-cheung.avif and b/src/_img/avatars/joyee-cheung.avif differ diff --git a/src/_img/avatars/joyee-cheung.jpg b/src/_img/avatars/joyee-cheung.jpg deleted file mode 100644 index 7a194a311..000000000 Binary files a/src/_img/avatars/joyee-cheung.jpg and /dev/null differ diff --git a/src/_img/avatars/joyee-cheung@2x.avif b/src/_img/avatars/joyee-cheung@2x.avif deleted file mode 100644 index bbda89cd1..000000000 Binary files a/src/_img/avatars/joyee-cheung@2x.avif and /dev/null differ diff --git a/src/_img/avatars/joyee-cheung@2x.jpg b/src/_img/avatars/joyee-cheung@2x.jpg deleted file mode 100644 index 93d1c4efc..000000000 Binary files a/src/_img/avatars/joyee-cheung@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/justin-ridgewell.avif b/src/_img/avatars/justin-ridgewell.avif index 81616c6f8..ac43a307b 100644 Binary files a/src/_img/avatars/justin-ridgewell.avif and b/src/_img/avatars/justin-ridgewell.avif differ diff --git a/src/_img/avatars/justin-ridgewell.jpg b/src/_img/avatars/justin-ridgewell.jpg deleted file mode 100644 index f822821d2..000000000 Binary files a/src/_img/avatars/justin-ridgewell.jpg and /dev/null differ diff --git a/src/_img/avatars/justin-ridgewell@2x.avif b/src/_img/avatars/justin-ridgewell@2x.avif deleted file mode 100644 index ac43a307b..000000000 Binary files a/src/_img/avatars/justin-ridgewell@2x.avif and /dev/null differ diff --git a/src/_img/avatars/justin-ridgewell@2x.jpg b/src/_img/avatars/justin-ridgewell@2x.jpg deleted file mode 100644 index bb3678ea2..000000000 Binary files a/src/_img/avatars/justin-ridgewell@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/leszek-swirski.avif b/src/_img/avatars/leszek-swirski.avif index 3e48a1654..1a97d0141 100644 Binary files a/src/_img/avatars/leszek-swirski.avif and b/src/_img/avatars/leszek-swirski.avif differ diff --git a/src/_img/avatars/leszek-swirski.jpg b/src/_img/avatars/leszek-swirski.jpg deleted file mode 100644 index adbe77155..000000000 Binary files a/src/_img/avatars/leszek-swirski.jpg and /dev/null differ diff --git a/src/_img/avatars/leszek-swirski@2x.avif b/src/_img/avatars/leszek-swirski@2x.avif deleted file mode 100644 index 1a97d0141..000000000 Binary files a/src/_img/avatars/leszek-swirski@2x.avif and /dev/null differ diff --git a/src/_img/avatars/leszek-swirski@2x.jpg b/src/_img/avatars/leszek-swirski@2x.jpg deleted file mode 100644 index 391991570..000000000 Binary files a/src/_img/avatars/leszek-swirski@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/marja-holtta.avif b/src/_img/avatars/marja-holtta.avif index 2b03ba819..0bcd83575 100644 Binary files a/src/_img/avatars/marja-holtta.avif and b/src/_img/avatars/marja-holtta.avif differ diff --git a/src/_img/avatars/marja-holtta.jpg b/src/_img/avatars/marja-holtta.jpg deleted file mode 100644 index f3f5f31bf..000000000 Binary files a/src/_img/avatars/marja-holtta.jpg and /dev/null differ diff --git a/src/_img/avatars/marja-holtta@2x.avif b/src/_img/avatars/marja-holtta@2x.avif deleted file mode 100644 index 0bcd83575..000000000 Binary files a/src/_img/avatars/marja-holtta@2x.avif and /dev/null differ diff --git a/src/_img/avatars/marja-holtta@2x.jpg b/src/_img/avatars/marja-holtta@2x.jpg deleted file mode 100644 index c46a584fb..000000000 Binary files a/src/_img/avatars/marja-holtta@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/mark-davis.avif b/src/_img/avatars/mark-davis.avif index 51d9261c1..4ca36f13b 100644 Binary files a/src/_img/avatars/mark-davis.avif and b/src/_img/avatars/mark-davis.avif differ diff --git a/src/_img/avatars/mark-davis.jpg b/src/_img/avatars/mark-davis.jpg deleted file mode 100644 index 3c2fb3c21..000000000 Binary files a/src/_img/avatars/mark-davis.jpg and /dev/null differ diff --git a/src/_img/avatars/mark-davis@2x.avif b/src/_img/avatars/mark-davis@2x.avif deleted file mode 100644 index 4ca36f13b..000000000 Binary files a/src/_img/avatars/mark-davis@2x.avif and /dev/null differ diff --git a/src/_img/avatars/mark-davis@2x.jpg b/src/_img/avatars/mark-davis@2x.jpg deleted file mode 100644 index 90f8fe900..000000000 Binary files a/src/_img/avatars/mark-davis@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/markus-scherer.avif b/src/_img/avatars/markus-scherer.avif index 1ab52d055..eb0682282 100644 Binary files a/src/_img/avatars/markus-scherer.avif and b/src/_img/avatars/markus-scherer.avif differ diff --git a/src/_img/avatars/markus-scherer.jpg b/src/_img/avatars/markus-scherer.jpg deleted file mode 100644 index 629b19ae4..000000000 Binary files a/src/_img/avatars/markus-scherer.jpg and /dev/null differ diff --git a/src/_img/avatars/markus-scherer@2x.avif b/src/_img/avatars/markus-scherer@2x.avif deleted file mode 100644 index eb0682282..000000000 Binary files a/src/_img/avatars/markus-scherer@2x.avif and /dev/null differ diff --git a/src/_img/avatars/markus-scherer@2x.jpg b/src/_img/avatars/markus-scherer@2x.jpg deleted file mode 100644 index bb868cc74..000000000 Binary files a/src/_img/avatars/markus-scherer@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/mathias-bynens.avif b/src/_img/avatars/mathias-bynens.avif index 3fe5a3188..0d089df71 100644 Binary files a/src/_img/avatars/mathias-bynens.avif and b/src/_img/avatars/mathias-bynens.avif differ diff --git a/src/_img/avatars/mathias-bynens.jpg b/src/_img/avatars/mathias-bynens.jpg deleted file mode 100644 index c337286d0..000000000 Binary files a/src/_img/avatars/mathias-bynens.jpg and /dev/null differ diff --git a/src/_img/avatars/mathias-bynens@2x.avif b/src/_img/avatars/mathias-bynens@2x.avif deleted file mode 100644 index 0d089df71..000000000 Binary files a/src/_img/avatars/mathias-bynens@2x.avif and /dev/null differ diff --git a/src/_img/avatars/mathias-bynens@2x.jpg b/src/_img/avatars/mathias-bynens@2x.jpg deleted file mode 100644 index a4df8451f..000000000 Binary files a/src/_img/avatars/mathias-bynens@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/maya-armyanova.avif b/src/_img/avatars/maya-armyanova.avif index 1e4f1100f..43cb6e59f 100644 Binary files a/src/_img/avatars/maya-armyanova.avif and b/src/_img/avatars/maya-armyanova.avif differ diff --git a/src/_img/avatars/maya-armyanova.jpg b/src/_img/avatars/maya-armyanova.jpg deleted file mode 100644 index 84ba914b0..000000000 Binary files a/src/_img/avatars/maya-armyanova.jpg and /dev/null differ diff --git a/src/_img/avatars/maya-armyanova@2x.avif b/src/_img/avatars/maya-armyanova@2x.avif deleted file mode 100644 index 43cb6e59f..000000000 Binary files a/src/_img/avatars/maya-armyanova@2x.avif and /dev/null differ diff --git a/src/_img/avatars/maya-armyanova@2x.jpg b/src/_img/avatars/maya-armyanova@2x.jpg deleted file mode 100644 index db34ffbd5..000000000 Binary files a/src/_img/avatars/maya-armyanova@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/michael-hablich.avif b/src/_img/avatars/michael-hablich.avif index a09d66f62..94638f38f 100644 Binary files a/src/_img/avatars/michael-hablich.avif and b/src/_img/avatars/michael-hablich.avif differ diff --git a/src/_img/avatars/michael-hablich.jpg b/src/_img/avatars/michael-hablich.jpg deleted file mode 100644 index 43ea1058b..000000000 Binary files a/src/_img/avatars/michael-hablich.jpg and /dev/null differ diff --git a/src/_img/avatars/michael-hablich@2x.avif b/src/_img/avatars/michael-hablich@2x.avif deleted file mode 100644 index 94638f38f..000000000 Binary files a/src/_img/avatars/michael-hablich@2x.avif and /dev/null differ diff --git a/src/_img/avatars/michael-hablich@2x.jpg b/src/_img/avatars/michael-hablich@2x.jpg deleted file mode 100644 index b8c255ca9..000000000 Binary files a/src/_img/avatars/michael-hablich@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/michael-lippautz.avif b/src/_img/avatars/michael-lippautz.avif index d76275158..8709414fe 100644 Binary files a/src/_img/avatars/michael-lippautz.avif and b/src/_img/avatars/michael-lippautz.avif differ diff --git a/src/_img/avatars/michael-lippautz.jpg b/src/_img/avatars/michael-lippautz.jpg deleted file mode 100644 index e6487bd02..000000000 Binary files a/src/_img/avatars/michael-lippautz.jpg and /dev/null differ diff --git a/src/_img/avatars/michael-lippautz@2x.avif b/src/_img/avatars/michael-lippautz@2x.avif deleted file mode 100644 index 8709414fe..000000000 Binary files a/src/_img/avatars/michael-lippautz@2x.avif and /dev/null differ diff --git a/src/_img/avatars/michael-lippautz@2x.jpg b/src/_img/avatars/michael-lippautz@2x.jpg deleted file mode 100644 index 41e1daaa1..000000000 Binary files a/src/_img/avatars/michael-lippautz@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/michael-stanton.avif b/src/_img/avatars/michael-stanton.avif index 110852f39..d3472b36a 100644 Binary files a/src/_img/avatars/michael-stanton.avif and b/src/_img/avatars/michael-stanton.avif differ diff --git a/src/_img/avatars/michael-stanton.jpg b/src/_img/avatars/michael-stanton.jpg deleted file mode 100644 index af8235c5b..000000000 Binary files a/src/_img/avatars/michael-stanton.jpg and /dev/null differ diff --git a/src/_img/avatars/michael-stanton@2x.avif b/src/_img/avatars/michael-stanton@2x.avif deleted file mode 100644 index d3472b36a..000000000 Binary files a/src/_img/avatars/michael-stanton@2x.avif and /dev/null differ diff --git a/src/_img/avatars/michael-stanton@2x.jpg b/src/_img/avatars/michael-stanton@2x.jpg deleted file mode 100644 index 99d42cec1..000000000 Binary files a/src/_img/avatars/michael-stanton@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/myles-borins.avif b/src/_img/avatars/myles-borins.avif index e9e06cf18..f39ff246d 100644 Binary files a/src/_img/avatars/myles-borins.avif and b/src/_img/avatars/myles-borins.avif differ diff --git a/src/_img/avatars/myles-borins.jpg b/src/_img/avatars/myles-borins.jpg deleted file mode 100644 index 000e6298e..000000000 Binary files a/src/_img/avatars/myles-borins.jpg and /dev/null differ diff --git a/src/_img/avatars/myles-borins@2x.avif b/src/_img/avatars/myles-borins@2x.avif deleted file mode 100644 index f39ff246d..000000000 Binary files a/src/_img/avatars/myles-borins@2x.avif and /dev/null differ diff --git a/src/_img/avatars/myles-borins@2x.jpg b/src/_img/avatars/myles-borins@2x.jpg deleted file mode 100644 index 3fbd6f0a5..000000000 Binary files a/src/_img/avatars/myles-borins@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/mythri-alle.avif b/src/_img/avatars/mythri-alle.avif index 0648b647c..dd724d716 100644 Binary files a/src/_img/avatars/mythri-alle.avif and b/src/_img/avatars/mythri-alle.avif differ diff --git a/src/_img/avatars/mythri-alle.jpg b/src/_img/avatars/mythri-alle.jpg deleted file mode 100644 index 621e9359c..000000000 Binary files a/src/_img/avatars/mythri-alle.jpg and /dev/null differ diff --git a/src/_img/avatars/mythri-alle@2x.avif b/src/_img/avatars/mythri-alle@2x.avif deleted file mode 100644 index dd724d716..000000000 Binary files a/src/_img/avatars/mythri-alle@2x.avif and /dev/null differ diff --git a/src/_img/avatars/mythri-alle@2x.jpg b/src/_img/avatars/mythri-alle@2x.jpg deleted file mode 100644 index 4e1d6ec8b..000000000 Binary files a/src/_img/avatars/mythri-alle@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/olivier-flueckiger.avif b/src/_img/avatars/olivier-flueckiger.avif index e9311b0bc..8cd8ceb57 100644 Binary files a/src/_img/avatars/olivier-flueckiger.avif and b/src/_img/avatars/olivier-flueckiger.avif differ diff --git a/src/_img/avatars/olivier-flueckiger.jpg b/src/_img/avatars/olivier-flueckiger.jpg deleted file mode 100644 index 1bd75e80e..000000000 Binary files a/src/_img/avatars/olivier-flueckiger.jpg and /dev/null differ diff --git a/src/_img/avatars/olivier-flueckiger@2x.avif b/src/_img/avatars/olivier-flueckiger@2x.avif deleted file mode 100644 index 8cd8ceb57..000000000 Binary files a/src/_img/avatars/olivier-flueckiger@2x.avif and /dev/null differ diff --git a/src/_img/avatars/olivier-flueckiger@2x.jpg b/src/_img/avatars/olivier-flueckiger@2x.jpg deleted file mode 100644 index 3e87851f4..000000000 Binary files a/src/_img/avatars/olivier-flueckiger@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/omer-katz.avif b/src/_img/avatars/omer-katz.avif index 53c8e8287..412fd8939 100644 Binary files a/src/_img/avatars/omer-katz.avif and b/src/_img/avatars/omer-katz.avif differ diff --git a/src/_img/avatars/omer-katz.jpg b/src/_img/avatars/omer-katz.jpg deleted file mode 100644 index 22cdde1c5..000000000 Binary files a/src/_img/avatars/omer-katz.jpg and /dev/null differ diff --git a/src/_img/avatars/omer-katz@2x.avif b/src/_img/avatars/omer-katz@2x.avif deleted file mode 100644 index 412fd8939..000000000 Binary files a/src/_img/avatars/omer-katz@2x.avif and /dev/null differ diff --git a/src/_img/avatars/omer-katz@2x.jpg b/src/_img/avatars/omer-katz@2x.jpg deleted file mode 100644 index 9e3d8ec34..000000000 Binary files a/src/_img/avatars/omer-katz@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/patrick-thier.avif b/src/_img/avatars/patrick-thier.avif index a3b10e1c9..b307aa92f 100644 Binary files a/src/_img/avatars/patrick-thier.avif and b/src/_img/avatars/patrick-thier.avif differ diff --git a/src/_img/avatars/patrick-thier.jpg b/src/_img/avatars/patrick-thier.jpg deleted file mode 100644 index dc179d2dd..000000000 Binary files a/src/_img/avatars/patrick-thier.jpg and /dev/null differ diff --git a/src/_img/avatars/patrick-thier@2x.avif b/src/_img/avatars/patrick-thier@2x.avif deleted file mode 100644 index b307aa92f..000000000 Binary files a/src/_img/avatars/patrick-thier@2x.avif and /dev/null differ diff --git a/src/_img/avatars/patrick-thier@2x.jpg b/src/_img/avatars/patrick-thier@2x.jpg deleted file mode 100644 index 160f48f1c..000000000 Binary files a/src/_img/avatars/patrick-thier@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/peter-marshall.avif b/src/_img/avatars/peter-marshall.avif index 7021f46b8..13a491fad 100644 Binary files a/src/_img/avatars/peter-marshall.avif and b/src/_img/avatars/peter-marshall.avif differ diff --git a/src/_img/avatars/peter-marshall.jpg b/src/_img/avatars/peter-marshall.jpg deleted file mode 100644 index f467a4e81..000000000 Binary files a/src/_img/avatars/peter-marshall.jpg and /dev/null differ diff --git a/src/_img/avatars/peter-marshall@2x.avif b/src/_img/avatars/peter-marshall@2x.avif deleted file mode 100644 index 13a491fad..000000000 Binary files a/src/_img/avatars/peter-marshall@2x.avif and /dev/null differ diff --git a/src/_img/avatars/peter-marshall@2x.jpg b/src/_img/avatars/peter-marshall@2x.jpg deleted file mode 100644 index de5ff9a47..000000000 Binary files a/src/_img/avatars/peter-marshall@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/rezvan-mahdavi-hezaveh.avif b/src/_img/avatars/rezvan-mahdavi-hezaveh.avif new file mode 100644 index 000000000..84168d781 Binary files /dev/null and b/src/_img/avatars/rezvan-mahdavi-hezaveh.avif differ diff --git a/src/_img/avatars/ross-mcilroy.avif b/src/_img/avatars/ross-mcilroy.avif index 0c9dd57c0..b3ecfe85b 100644 Binary files a/src/_img/avatars/ross-mcilroy.avif and b/src/_img/avatars/ross-mcilroy.avif differ diff --git a/src/_img/avatars/ross-mcilroy.jpg b/src/_img/avatars/ross-mcilroy.jpg deleted file mode 100644 index 9859edd0b..000000000 Binary files a/src/_img/avatars/ross-mcilroy.jpg and /dev/null differ diff --git a/src/_img/avatars/ross-mcilroy@2x.avif b/src/_img/avatars/ross-mcilroy@2x.avif deleted file mode 100644 index b3ecfe85b..000000000 Binary files a/src/_img/avatars/ross-mcilroy@2x.avif and /dev/null differ diff --git a/src/_img/avatars/ross-mcilroy@2x.jpg b/src/_img/avatars/ross-mcilroy@2x.jpg deleted file mode 100644 index 2230d0f21..000000000 Binary files a/src/_img/avatars/ross-mcilroy@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/samuel-gross.avif b/src/_img/avatars/samuel-gross.avif new file mode 100644 index 000000000..c4afefb75 Binary files /dev/null and b/src/_img/avatars/samuel-gross.avif differ diff --git a/src/_img/avatars/santiago-aboy-solanes.avif b/src/_img/avatars/santiago-aboy-solanes.avif index 1d3c60374..36873ba20 100644 Binary files a/src/_img/avatars/santiago-aboy-solanes.avif and b/src/_img/avatars/santiago-aboy-solanes.avif differ diff --git a/src/_img/avatars/santiago-aboy-solanes.jpg b/src/_img/avatars/santiago-aboy-solanes.jpg deleted file mode 100644 index 812cad928..000000000 Binary files a/src/_img/avatars/santiago-aboy-solanes.jpg and /dev/null differ diff --git a/src/_img/avatars/santiago-aboy-solanes@2x.avif b/src/_img/avatars/santiago-aboy-solanes@2x.avif deleted file mode 100644 index 36873ba20..000000000 Binary files a/src/_img/avatars/santiago-aboy-solanes@2x.avif and /dev/null differ diff --git a/src/_img/avatars/santiago-aboy-solanes@2x.jpg b/src/_img/avatars/santiago-aboy-solanes@2x.jpg deleted file mode 100644 index f9d1a1a3d..000000000 Binary files a/src/_img/avatars/santiago-aboy-solanes@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/sathya-gunasekaran.avif b/src/_img/avatars/sathya-gunasekaran.avif index da769b117..a71e960c2 100644 Binary files a/src/_img/avatars/sathya-gunasekaran.avif and b/src/_img/avatars/sathya-gunasekaran.avif differ diff --git a/src/_img/avatars/sathya-gunasekaran.jpg b/src/_img/avatars/sathya-gunasekaran.jpg deleted file mode 100644 index 34296326d..000000000 Binary files a/src/_img/avatars/sathya-gunasekaran.jpg and /dev/null differ diff --git a/src/_img/avatars/sathya-gunasekaran@2x.avif b/src/_img/avatars/sathya-gunasekaran@2x.avif deleted file mode 100644 index a71e960c2..000000000 Binary files a/src/_img/avatars/sathya-gunasekaran@2x.avif and /dev/null differ diff --git a/src/_img/avatars/sathya-gunasekaran@2x.jpg b/src/_img/avatars/sathya-gunasekaran@2x.jpg deleted file mode 100644 index ac7478eb9..000000000 Binary files a/src/_img/avatars/sathya-gunasekaran@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/shane-carr.avif b/src/_img/avatars/shane-carr.avif index bb7b1bb62..a366c5d00 100644 Binary files a/src/_img/avatars/shane-carr.avif and b/src/_img/avatars/shane-carr.avif differ diff --git a/src/_img/avatars/shane-carr.jpg b/src/_img/avatars/shane-carr.jpg deleted file mode 100644 index 2b159c617..000000000 Binary files a/src/_img/avatars/shane-carr.jpg and /dev/null differ diff --git a/src/_img/avatars/shane-carr@2x.avif b/src/_img/avatars/shane-carr@2x.avif deleted file mode 100644 index a366c5d00..000000000 Binary files a/src/_img/avatars/shane-carr@2x.avif and /dev/null differ diff --git a/src/_img/avatars/shane-carr@2x.jpg b/src/_img/avatars/shane-carr@2x.jpg deleted file mode 100644 index b9c639ab1..000000000 Binary files a/src/_img/avatars/shane-carr@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/shu-yu-guo.avif b/src/_img/avatars/shu-yu-guo.avif index ef73662c9..55089dd42 100644 Binary files a/src/_img/avatars/shu-yu-guo.avif and b/src/_img/avatars/shu-yu-guo.avif differ diff --git a/src/_img/avatars/shu-yu-guo.jpg b/src/_img/avatars/shu-yu-guo.jpg deleted file mode 100644 index cc4295af6..000000000 Binary files a/src/_img/avatars/shu-yu-guo.jpg and /dev/null differ diff --git a/src/_img/avatars/shu-yu-guo@2x.avif b/src/_img/avatars/shu-yu-guo@2x.avif deleted file mode 100644 index 55089dd42..000000000 Binary files a/src/_img/avatars/shu-yu-guo@2x.avif and /dev/null differ diff --git a/src/_img/avatars/shu-yu-guo@2x.jpg b/src/_img/avatars/shu-yu-guo@2x.jpg deleted file mode 100644 index 3adb52273..000000000 Binary files a/src/_img/avatars/shu-yu-guo@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/simon-zuend.avif b/src/_img/avatars/simon-zuend.avif index f8e532298..f81a189c5 100644 Binary files a/src/_img/avatars/simon-zuend.avif and b/src/_img/avatars/simon-zuend.avif differ diff --git a/src/_img/avatars/simon-zuend.jpg b/src/_img/avatars/simon-zuend.jpg deleted file mode 100644 index 2052107d0..000000000 Binary files a/src/_img/avatars/simon-zuend.jpg and /dev/null differ diff --git a/src/_img/avatars/simon-zuend@2x.avif b/src/_img/avatars/simon-zuend@2x.avif deleted file mode 100644 index f81a189c5..000000000 Binary files a/src/_img/avatars/simon-zuend@2x.avif and /dev/null differ diff --git a/src/_img/avatars/simon-zuend@2x.jpg b/src/_img/avatars/simon-zuend@2x.jpg deleted file mode 100644 index 2080e48f3..000000000 Binary files a/src/_img/avatars/simon-zuend@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/stephan-herhut.avif b/src/_img/avatars/stephan-herhut.avif index bf63d917b..73d295069 100644 Binary files a/src/_img/avatars/stephan-herhut.avif and b/src/_img/avatars/stephan-herhut.avif differ diff --git a/src/_img/avatars/stephan-herhut.jpg b/src/_img/avatars/stephan-herhut.jpg deleted file mode 100644 index 47aa3bf69..000000000 Binary files a/src/_img/avatars/stephan-herhut.jpg and /dev/null differ diff --git a/src/_img/avatars/stephan-herhut@2x.avif b/src/_img/avatars/stephan-herhut@2x.avif deleted file mode 100644 index 73d295069..000000000 Binary files a/src/_img/avatars/stephan-herhut@2x.avif and /dev/null differ diff --git a/src/_img/avatars/stephan-herhut@2x.jpg b/src/_img/avatars/stephan-herhut@2x.jpg deleted file mode 100644 index 47149009e..000000000 Binary files a/src/_img/avatars/stephan-herhut@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/toon-verwaest.avif b/src/_img/avatars/toon-verwaest.avif index 26de853db..278ee1121 100644 Binary files a/src/_img/avatars/toon-verwaest.avif and b/src/_img/avatars/toon-verwaest.avif differ diff --git a/src/_img/avatars/toon-verwaest.jpg b/src/_img/avatars/toon-verwaest.jpg deleted file mode 100644 index ced7b9627..000000000 Binary files a/src/_img/avatars/toon-verwaest.jpg and /dev/null differ diff --git a/src/_img/avatars/toon-verwaest@2x.avif b/src/_img/avatars/toon-verwaest@2x.avif deleted file mode 100644 index 278ee1121..000000000 Binary files a/src/_img/avatars/toon-verwaest@2x.avif and /dev/null differ diff --git a/src/_img/avatars/toon-verwaest@2x.jpg b/src/_img/avatars/toon-verwaest@2x.jpg deleted file mode 100644 index fc2b2ec92..000000000 Binary files a/src/_img/avatars/toon-verwaest@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/ulan-degenbaev.avif b/src/_img/avatars/ulan-degenbaev.avif index ea1ad9c78..6169a20e1 100644 Binary files a/src/_img/avatars/ulan-degenbaev.avif and b/src/_img/avatars/ulan-degenbaev.avif differ diff --git a/src/_img/avatars/ulan-degenbaev.jpg b/src/_img/avatars/ulan-degenbaev.jpg deleted file mode 100644 index d96604307..000000000 Binary files a/src/_img/avatars/ulan-degenbaev.jpg and /dev/null differ diff --git a/src/_img/avatars/ulan-degenbaev@2x.avif b/src/_img/avatars/ulan-degenbaev@2x.avif deleted file mode 100644 index 6169a20e1..000000000 Binary files a/src/_img/avatars/ulan-degenbaev@2x.avif and /dev/null differ diff --git a/src/_img/avatars/ulan-degenbaev@2x.jpg b/src/_img/avatars/ulan-degenbaev@2x.jpg deleted file mode 100644 index 304adab54..000000000 Binary files a/src/_img/avatars/ulan-degenbaev@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/victor-gomes.avif b/src/_img/avatars/victor-gomes.avif index eac563490..033a5b0fb 100644 Binary files a/src/_img/avatars/victor-gomes.avif and b/src/_img/avatars/victor-gomes.avif differ diff --git a/src/_img/avatars/victor-gomes.jpg b/src/_img/avatars/victor-gomes.jpg deleted file mode 100644 index f9eb7fab3..000000000 Binary files a/src/_img/avatars/victor-gomes.jpg and /dev/null differ diff --git a/src/_img/avatars/victor-gomes@2x.avif b/src/_img/avatars/victor-gomes@2x.avif deleted file mode 100644 index 033a5b0fb..000000000 Binary files a/src/_img/avatars/victor-gomes@2x.avif and /dev/null differ diff --git a/src/_img/avatars/victor-gomes@2x.jpg b/src/_img/avatars/victor-gomes@2x.jpg deleted file mode 100644 index cc0427fbf..000000000 Binary files a/src/_img/avatars/victor-gomes@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/wouter-van-oortmerssen.avif b/src/_img/avatars/wouter-van-oortmerssen.avif index d9f4066c4..dfa9a2303 100644 Binary files a/src/_img/avatars/wouter-van-oortmerssen.avif and b/src/_img/avatars/wouter-van-oortmerssen.avif differ diff --git a/src/_img/avatars/wouter-van-oortmerssen.jpg b/src/_img/avatars/wouter-van-oortmerssen.jpg deleted file mode 100644 index 1f33aebd3..000000000 Binary files a/src/_img/avatars/wouter-van-oortmerssen.jpg and /dev/null differ diff --git a/src/_img/avatars/wouter-van-oortmerssen@2x.avif b/src/_img/avatars/wouter-van-oortmerssen@2x.avif deleted file mode 100644 index dfa9a2303..000000000 Binary files a/src/_img/avatars/wouter-van-oortmerssen@2x.avif and /dev/null differ diff --git a/src/_img/avatars/wouter-van-oortmerssen@2x.jpg b/src/_img/avatars/wouter-van-oortmerssen@2x.jpg deleted file mode 100644 index 133703427..000000000 Binary files a/src/_img/avatars/wouter-van-oortmerssen@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/yang-guo.avif b/src/_img/avatars/yang-guo.avif index ea83a6231..8a8566485 100644 Binary files a/src/_img/avatars/yang-guo.avif and b/src/_img/avatars/yang-guo.avif differ diff --git a/src/_img/avatars/yang-guo.jpg b/src/_img/avatars/yang-guo.jpg deleted file mode 100644 index 2e17fae01..000000000 Binary files a/src/_img/avatars/yang-guo.jpg and /dev/null differ diff --git a/src/_img/avatars/yang-guo@2x.avif b/src/_img/avatars/yang-guo@2x.avif deleted file mode 100644 index 8a8566485..000000000 Binary files a/src/_img/avatars/yang-guo@2x.avif and /dev/null differ diff --git a/src/_img/avatars/yang-guo@2x.jpg b/src/_img/avatars/yang-guo@2x.jpg deleted file mode 100644 index b20657712..000000000 Binary files a/src/_img/avatars/yang-guo@2x.jpg and /dev/null differ diff --git a/src/_img/avatars/zeynep-cankara.avif b/src/_img/avatars/zeynep-cankara.avif index e32b59283..5d1955ad2 100644 Binary files a/src/_img/avatars/zeynep-cankara.avif and b/src/_img/avatars/zeynep-cankara.avif differ diff --git a/src/_img/avatars/zeynep-cankara.jpg b/src/_img/avatars/zeynep-cankara.jpg deleted file mode 100644 index bc6e7d2d5..000000000 Binary files a/src/_img/avatars/zeynep-cankara.jpg and /dev/null differ diff --git a/src/_img/avatars/zeynep-cankara@2x.avif b/src/_img/avatars/zeynep-cankara@2x.avif deleted file mode 100644 index 5d1955ad2..000000000 Binary files a/src/_img/avatars/zeynep-cankara@2x.avif and /dev/null differ diff --git a/src/_img/avatars/zeynep-cankara@2x.jpg b/src/_img/avatars/zeynep-cankara@2x.jpg deleted file mode 100644 index a45d32cb1..000000000 Binary files a/src/_img/avatars/zeynep-cankara@2x.jpg and /dev/null differ diff --git a/src/_img/sandbox/sandbox.svg b/src/_img/sandbox/sandbox.svg new file mode 100644 index 000000000..f8f419a34 --- /dev/null +++ b/src/_img/sandbox/sandbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/_img/static-roots/static-roots1.svg b/src/_img/static-roots/static-roots1.svg new file mode 100644 index 000000000..d54543651 --- /dev/null +++ b/src/_img/static-roots/static-roots1.svg @@ -0,0 +1,262 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/_img/static-roots/static-roots2.svg b/src/_img/static-roots/static-roots2.svg new file mode 100644 index 000000000..61d3af847 --- /dev/null +++ b/src/_img/static-roots/static-roots2.svg @@ -0,0 +1,409 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/_includes/layouts/base.njk b/src/_includes/layouts/base.njk index a06f0e159..a5a80eb27 100644 --- a/src/_includes/layouts/base.njk +++ b/src/_includes/layouts/base.njk @@ -9,6 +9,7 @@ {% if '/features' in page.url %} {% endif %} + diff --git a/src/_includes/layouts/feature.njk b/src/_includes/layouts/feature.njk index e39a5b11b..d0b689202 100644 --- a/src/_includes/layouts/feature.njk +++ b/src/_includes/layouts/feature.njk @@ -23,10 +23,7 @@ layout: layouts/base.njk
{% if avatars %} {% for avatar in avatars %} - - - - + {% endfor %} {% endif %}

Posted by {{ author | markdown | safe }}.

diff --git a/src/_includes/layouts/post.njk b/src/_includes/layouts/post.njk index cb9c546c8..a570a84aa 100644 --- a/src/_includes/layouts/post.njk +++ b/src/_includes/layouts/post.njk @@ -23,10 +23,7 @@ layout: layouts/base.njk
{% if avatars %} {% for avatar in avatars %} - - - - + {% endfor %} {% endif %}

JSObject::GetPropertyNames() { + int num_properties = TotalNumberOfProperties(); + std::vector properties(num_properties); + + for (int i = 0; i < NumberOfInObjectProperties(); i++) { + properties[i] = GetNameOfInObjectProperty(i); + } + + // Deal with the other types of properties + // ... +``` + +This code makes the (reasonable) assumption that the number of properties stored directly in a JSObject must be less than the total number of properties of that object. However, assuming these numbers are simply stored as integers somewhere in the JSObject, an attacker could corrupt one of them to break this invariant. Subsequently, the access into the (out-of-sandbox) `std::vector` would go out of bounds. Adding an explicit bounds check, for example with an [`SBXCHECK`](https://chromium.googlesource.com/v8/v8.git/+/0deeaf5f593b98d6a6a2bb64e3f71d39314c727c), would fix this. + +Encouragingly, nearly all "sandbox violations" discovered so far are like this: trivial (1st order) memory corruption bugs such as use-after-frees or out-of-bounds accesses due to lack of a bounds check. Contrary to the 2nd order vulnerabilities typically found in V8, these sandbox bugs could actually be prevented or mitigated by the approaches discussed earlier. In fact, the particular bug above would already be mitigated today due to [Chrome's libc++ hardening](http://issues.chromium.org/issues/40228527). As such, the hope is that in the long run, the sandbox becomes a **more defensible security boundary** than V8 itself. While the currently available data set of sandbox bugs is very limited, the VRP integration launching today will hopefully help produce a clearer picture of the type of vulnerabilities encountered on the sandbox attack surface. + +## Performance + +One major advantage of this approach is that it is fundamentally cheap: the overhead caused by the sandbox comes mostly from the pointer table indirection for external objects (costing roughly one additional memory load) and to a lesser extent from the use of offsets instead of raw pointers (costing mostly just a shift+add operation, which is very cheap). The current overhead of the sandbox is therefore only around 1% or less on typical workloads (measured using the [Speedometer](https://browserbench.org/Speedometer3.0/) and [JetStream](https://browserbench.org/JetStream/) benchmark suites). This allows the V8 Sandbox to be enabled by default on compatible platforms. + +## Testing + +A desirable feature for any security boundary is testability: the ability to manually and automatically test that the promised security guarantees actually hold in practice. This requires a clear attacker model, a way to "emulate" an attacker, and ideally a way of automatically determining when the security boundary has failed. The V8 Sandbox fulfills all of these requirements: + +1. **A clear attacker model:** it is assumed that an attacker can read and write arbitrarily inside the V8 Sandbox. The goal is to prevent memory corruption outside of the sandbox. +2. **A way to emulate an attacker:** V8 provides a "memory corruption API" when built with the `v8_enable_memory_corruption_api = true` flag. This emulates the primitives obtained from typical V8 vulnerabilities and in particular provides full read- and write access inside the sandbox. +3. **A way to detect "sandbox violations":** V8 provides a "sandbox testing" mode (enabled via either `--sandbox-testing` or `--sandbox-fuzzing`) which installs a [signal handler](https://source.chromium.org/chromium/chromium/src/+/main:v8/src/sandbox/testing.cc;l=425;drc=97b7d0066254778f766214d247b65d01f8a81ebb) that determines if a signal such as `SIGSEGV` represents a violation of the sandbox's security guarantees. + +Ultimately, this allows the sandbox to be integrated into Chrome's VRP program and be fuzzed by specialized fuzzers. + +## Usage + +The V8 Sandbox must be enabled/disabled at build time using the `v8_enable_sandbox` build flag. It is (for technical reasons) not possible to enable/disable the sandbox at runtime. The V8 Sandbox requires a 64-bit system as it needs to reserve a large amount of virtual address space, currently one terabyte. + +The V8 Sandbox has already been enabled by default on 64-bit (specifically x64 and arm64) versions of Chrome on Android, ChromeOS, Linux, macOS, and Windows for roughly the last two years. Even though the sandbox was (and still is) not feature complete, this was mainly done to ensure that it does not cause stability issues and to collect real-world performance statistics. Consequently, recent V8 exploits already had to work their way past the sandbox, providing helpful early feedback on its security properties. + + +# Conclusion + +The V8 Sandbox is a new security mechanism designed to prevent memory corruption in V8 from impacting other memory in the process. The sandbox is motivated by the fact that current memory safety technologies are largely inapplicable to optimizing JavaScript engines. While these technologies fail to prevent memory corruption in V8 itself, they can in fact protect the V8 Sandbox attack surface. The sandbox is therefore a necessary step towards memory safety. diff --git a/src/blog/static-roots.md b/src/blog/static-roots.md new file mode 100644 index 000000000..96dd7863a --- /dev/null +++ b/src/blog/static-roots.md @@ -0,0 +1,41 @@ +--- +title: 'Static Roots: Objects with Compile-Time Constant Addresses' +author: 'Olivier Flückiger' +avatars: + - olivier-flueckiger +date: 2024-02-05 +tags: + - JavaScript +description: "Static Roots makes the addresses of certain JS objects a compile-time constant." +tweet: '' +--- + +Did you ever wonder where `undefined`, `true`, and other core JavaScript objects come from? These objects are the atoms of any user defined object and need to be there first. V8 calls them immovable immutable roots and they live in their own heap – the read-only heap. Since they are used constantly, quick access is crucial. And what could be quicker than correctly guessing their memory address at compile time? + +As an example, consider the extremely common `IsUndefined` [API function](https://source.chromium.org/chromium/chromium/src/+/main:v8/include/v8-value.h?q=symbol:%5Cbv8::Value::IsUndefined%5Cb%20case:yes). Instead of having to look up the address of the `undefined` object for reference, what if we could simply check if an object's pointer ends in, say, `0x61` to know if it is undefined. This is exactly what the V8’s *static roots* feature achieves. This post explores the hurdles we had to take to get there. The feature landed in Chrome 111 and brought performance benefits across the whole VM, particularly speeding up C++ code and builtin functions. + +## Bootstrapping the Read-Only Heap + +Creating the read-only objects takes some time, so V8 creates them at compile time. To compile V8, first a minimal proto-V8 binary called `mksnapshot` is compiled. This one creates all the shared read-only objects as well as the native code of builtin functions and writes them into a snapshot. Then, the actual V8 binary is compiled and bundled with the snapshot. To start V8 the snapshot is loaded into memory and we can immediately start using its content. The following diagram shows the simplified build process for the standalone `d8` binary. + +![](/_img/static-roots/static-roots1.svg) + +Once `d8` is up and running all the read-only objects have their fixed place in memory and never move. When we JIT code, we can e.g., directly refer to `undefined` by its address. However, when building the snapshot and when compiling the C++ for libv8 the address is not known yet. It depends on two things unknown at build time. First, the binary layout of the read-only heap and second, where in the memory space that read-only heap is located. + +## How to Predict Addresses? + +V8 uses [pointer compression](https://v8.dev/blog/pointer-compression). Instead of full 64 bit addresses we refer to objects by a 32 bit offset into a 4GB region of memory. For many operations such as property loads or comparisons, the 32 bit offset into that cage is all that is needed to uniquely identify an object. Therefore our second problem — not knowing where in the memory space the read-only heap is placed — is not actually a problem. We simply place the read-only heap at the start of every pointer compression cage thus giving it a known location. For instance of all objects in V8’s heap, `undefined` always has the smallest compressed address, starting at 0x61 bytes. That’s how we know that if the lower 32 bits of any JS object’s full address are 0x61, then it must be `undefined`. + +This is already useful, but we want to be able to use this address in the snapshot and in libv8 – a seemingly circular problem. However, if we ensure that `mksnapshot` deterministically creates a bit identical read-only heap, then we can re-use these addresses across builds. To use them in libv8 itself, we basically build V8 twice: + +![](/_img/static-roots/static-roots2.svg) + +The first time round calling `mksnapshot` the only artifact produced is a file that contains the [addresses](https://source.chromium.org/chromium/chromium/src/+/main:v8/src/roots/static-roots.h) relative to the cage base of every object in the read-only heap. In the second stage of the build we compile libv8 again and a flag ensures that whenever we refer to `undefined` we literally use `cage_base + StaticRoot::kUndefined` instead; the static offset of `undefined` of course being defined in the static-roots.h file. In many cases this will allow the C++ compiler creating libv8 and the builtins compiler in `mksnapshot` to create much more efficient code as the alternative is to always load the address from a global array of root objects. We end up with a `d8` binary where the compressed address of `undefined` is hardcoded to be `0x61`. + +Well, morally this is how everything works, but practically we only build V8 once – ain’t nobody got time for this. The generated static-roots.h file is cached in the source repository and only needs to be recreated if we change the layout of the read-only heap. + +## Further Applications + +Speaking of practicalities, static roots enable even more optimizations. For instance we have since grouped common objects together allowing us to implement some operations as range checks over their addresses. For instance all string maps (i.e., the [hidden-class](https://v8.dev/docs/hidden-classes) meta objects describing the layout of different string types) are next to each other, hence an object is a string if its map has a compressed address between `0xdd` and `0x49d`. Or, truthy objects must have an address that is at least `0xc1`. + +Not everything is about the performance of JITed code in V8. As this project has shown, a relatively small change to the C++ code can have significant impact too. For instance Speedometer 2, a benchmark which exercises the V8 API and the interaction between V8 and its embedder, gained about 1% in score on an M1 CPU thanks to static roots. diff --git a/src/blog/wasm-gc-porting.md b/src/blog/wasm-gc-porting.md index 532687d9e..b06c8cf7e 100644 --- a/src/blog/wasm-gc-porting.md +++ b/src/blog/wasm-gc-porting.md @@ -203,7 +203,7 @@ Overall, in WasmMVP there was a fairly clear separation between toolchain and VM You can use WasmGC today! After reaching [phase 4](https://github.com/WebAssembly/meetings/blob/main/process/phases.md#4-standardize-the-feature-working-group) at the W3C, WasmGC is now a full and finalized standard, and Chrome 119 shipped with support for it. With that browser (or any other browser that has WasmGC support; for example, Firefox 120 is expected to launch with WasmGC support later this month) you can run this [Flutter demo](https://flutterweb-wasm.web.app/) in which Dart compiled to WasmGC drives the application’s logic, including its widgets, layout, and animation. -![The Flutter demo running in Chrome 119.](/_img/wasm-gc-porting/flutter-wasm-demo.png "Material 3 rendered by Flutter WasmGC.") +![The Flutter demo running in Chrome 119.](/_img/wasm-gc-porting/flutter-wasm-demo.png "Material 3 rendered by Flutter WasmGC."){ .no-darkening } ## Getting started diff --git a/src/docs/feature-launch-process.md b/src/docs/feature-launch-process.md index ea92059c8..6967fb3f6 100644 --- a/src/docs/feature-launch-process.md +++ b/src/docs/feature-launch-process.md @@ -2,24 +2,78 @@ title: 'Implementing and shipping JavaScript/WebAssembly language features' description: 'This document explains the process for implementing and shipping JavaScript or WebAssembly language features in V8.' --- -In general, V8 uses the [Blink Intent process](https://www.chromium.org/blink/launching-features) for JavaScript and WebAssembly language features. The differences are laid out in the errata below. Please follow the Blink Intent process, unless the errata tells you otherwise. +In general, V8 follows the [Blink Intent process for already-defined consensus-based standards](https://www.chromium.org/blink/launching-features/#process-existing-standard) for JavaScript and WebAssembly language features. V8-specific errata are laid out below. Please follow the Blink Intent process, unless the errata tells you otherwise. -If you have any questions on this topic, please send hablich@chromium.org and v8-dev@googlegroups.com an email. +If you have any questions on this topic for JavaScript features, please email syg@chromium.org and v8-dev@googlegroups.com. + +For WebAssembly features, please email gdeepti@chromium.org and v8-dev@googlegroups.com. ## Errata +### JavaScript features usually wait until Stage 3+ { #stage3plus } + +As a rule of thumb, V8 waits to implement JavaScript feature proposals until they advance to [Stage 3 or later in TC39](https://tc39.es/process-document/). TC39 has its own consensus process, and Stage 3 or later signals explicit consensus among TC39 delegates, including all browser vendors, that a feature proposal is ready to implement. This external consensus process means Stage 3+ features do not need to send Intent emails other than Intent to Ship. + ### TAG review { #tag } For smaller JavaScript or WebAssembly features, a TAG review is not required, as TC39 and the Wasm CG already provide significant technical oversight. If the feature is large or cross-cutting (e.g., requires changes to other Web Platform APIs or modifications to Chromium), TAG review is recommended. -### Instead of WPT, Test262 and WebAssembly spec tests are sufficient { #tests } +### Both V8 and blink flags are required { #flags } + +When implementing a feature, both a V8 flag and a blink `base::Feature` are required. + +Blink features are required so that Chrome can turn off features without distributing new binaries in emergency situations. This is usually implemented in [`gin/gin_features.h`](https://source.chromium.org/chromium/chromium/src/+/main:gin/gin_features.h), [`gin/gin_features.cc`](https://source.chromium.org/chromium/chromium/src/+/main:gin/gin_features.cc), and [`gin/v8_initializer.cc`](https://source.chromium.org/chromium/chromium/src/+/main:gin/v8_initializer.cc), + +### Fuzzing is required to ship { #fuzzing } + +JavaScript and WebAssembly features must be fuzzed for a minimum period of 4 weeks, or one (1) release milestone, with all fuzz bugs fixed, before they can be shipped. + +For code-complete JavaScript features, start fuzzing by moving the feature flag to the `JAVASCRIPT_STAGED_FEATURES_BASE` macro in [`src/flags/flag-definitions.h`](https://source.chromium.org/chromium/chromium/src/+/master:v8/src/flags/flag-definitions.h). + +For WebAssembly, see the [WebAssembly shipping checklist](/docs/wasm-shipping-checklist). + +### [Chromestatus](https://chromestatus.com/) and review gates { #chromestatus } + +The blink intent process includes a series of review gates that must be approved on the feature's entry in [Chromestatus](https://chromestatus.com/) before an Intent to Ship is sent out seeking API OWNER approvals. + +These gates are tailored towards web APIs, and some gates may not be applicable to JavaScript and WebAssembly features. The following is broad guidance. The specifics differ from feature to feature; do not apply guidance blindly! + +#### Privacy + +Most JavaScript and WebAssembly features do not affect privacy. Rarely, features may add new fingerprinting vectors that reveal information about a user's operating system or hardware. -Adding Web Platform Tests (WPT) is not required, as JavaScript and WebAssembly language features have their own test repositories. Feel free to add some though, if you think it is beneficial. +#### Security -For JavaScript features, explicit correctness tests in [Test262](https://github.com/tc39/test262) are preferred and required. +While JavaScript and WebAssembly are common attack vectors in security exploits, most new features do not add additional attack surface. [Fuzzing](#fuzzing) is required, and mitigates some of the risk. + +Features that affect known popular attack vectors, such as `ArrayBuffer`s in JavaScript, and features that might enable side-channel attacks, need extra scrutiny and must be reviewed. + +#### Enterprise + +Throughout their standardization process in TC39 and the Wasm CG, JavaScript and WebAssembly features already undergo heavy backwards compatibility scrutiny. It is exceedingly rare for features to be willfuly backwards incompatible. + +For JavaScript, recently shipped features can also be disabled via `chrome://flags/#disable-javascript-harmony-shipping`. + +#### Debuggability + +JavaScript and WebAssembly features' debuggability differs significantly from feature to feature. JavaScript features that only add new built-in methods do not need additional debugger support, while WebAssembly features that add new capabilities may need significant additional debugger support. + +For more details, see the [JavaScript feature debugging checklist](https://docs.google.com/document/d/1_DBgJ9eowJJwZYtY6HdiyrizzWzwXVkG5Kt8s3TccYE/edit#heading=h.u5lyedo73aa9) and the [WebAssembly feature debugging checklist](https://goo.gle/devtools-wasm-checklist). + +When in doubt, this gate is applicable. + +#### Testing { #tests } + +Instead of WPT, Test262 tests are sufficient for JavaScript features, and WebAssembly spec tests are sufficient for WebAssembly features. + +Adding Web Platform Tests (WPT) is not required, as JavaScript and WebAssembly language features have their own interoperable test repositories that are run by multiple implementations. Feel free to add some though, if you think it is beneficial. + +For JavaScript features, explicit correctness tests in [Test262](https://github.com/tc39/test262) are required. Note that tests in the [staging directory](https://github.com/tc39/test262/blob/main/CONTRIBUTING.md#staging) suffice. For WebAssembly features, explicit correctness tests in the [WebAssembly Spec Test repo](https://github.com/WebAssembly/spec/tree/master/test) are required. +For performance tests, JavaScript already underlies most existing performance benchmarks, like Speedometer. + ### Who to CC { #cc } **Every** “intent to `$something`” email (e.g. “intent to implement”) should CC in addition to . This way, other embedders of V8 are kept in the loop too. diff --git a/src/docs/index.md b/src/docs/index.md index 3a0c268af..c92adcddb 100644 --- a/src/docs/index.md +++ b/src/docs/index.md @@ -8,7 +8,7 @@ This documentation is aimed at C++ developers who want to use V8 in their applic ## About V8 -V8 implements ECMAScript and WebAssembly, and runs on Windows 7 or later, macOS 10.12+, and Linux systems that use x64, IA-32, or ARM processors. Additional systems (IBM i, AIX) and processors (MIPS, ppcle64, s390x) are externally maintained, see [ports](/docs/ports). V8 can run standalone, or can be embedded into any C++ application. +V8 implements ECMAScript and WebAssembly, and runs on Windows, macOS, and Linux systems that use x64, IA-32, or ARM processors. Additional systems (IBM i, AIX) and processors (MIPS, ppcle64, s390x) are externally maintained, see [ports](/docs/ports). V8 can be embedded into any C++ application. V8 compiles and executes JavaScript source code, handles memory allocation for objects, and garbage collects objects it no longer needs. V8’s stop-the-world, generational, accurate garbage collector is one of the keys to V8’s performance. diff --git a/src/favicon.png b/src/favicon.png new file mode 100644 index 000000000..83a49b6e0 Binary files /dev/null and b/src/favicon.png differ diff --git a/src/features/import-attributes.md b/src/features/import-attributes.md new file mode 100644 index 000000000..f2104c270 --- /dev/null +++ b/src/features/import-attributes.md @@ -0,0 +1,63 @@ +--- +title: 'Import attributes' +author: 'Shu-yu Guo ([@_shu](https://twitter.com/_shu))' +avatars: + - 'shu-yu-guo' +date: 2024-01-31 +tags: + - ECMAScript +description: 'Import attributes: the evolution of import assertions' +tweet: '' +--- + +## Previously + +V8 shipped the [import assertions](https://chromestatus.com/feature/5765269513306112) feature in v9.1. This feature allowed module import statements to include additional information by using the `assert` keyword. This additional information is currently used to import JSON and CSS modules inside JavaScript modules. + +## Import attributes + +Since then, import assertions has evolved into [import attributes](https://github.com/tc39/proposal-import-attributes). The point of the feature remains the same: to allow module import statements to include additional information. + +The most important difference is that import assertions had assert-only semantics, while import attributes has more relaxed semantics. Assert-only semantics means that the additional information has no effect on _how_ a module is loaded, only on _whether_ it is loaded. For example, a JSON module is always loaded as JSON module by virtue of its MIME type, and the `assert { type: 'json' }` clause can only cause loading to fail if the requested module's MIME type is not `application/json`. + +However, assert-only semantics had a fatal flaw. On the web, the shape of HTTP requests differs depending on the type of resource that is requested. For example, the [`Accept` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept) affects the MIME type of the response, and the [`Sec-Fetch-Dest` metadata header](https://web.dev/articles/fetch-metadata) affects whether the web server accepts or rejects the request. Because an import assertion could not affect _how_ to load a module, it was not able to change the shape of the HTTP request. The type of the resource that is being requested also affects which [Content Security Policies](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) are used: import assertions could not correctly work with the security model of the web. + +Import attributes relaxes the assert-only semantics to allow the attributes to affect how a module is loaded. In other words, import attributes can generate HTTP requests that contains the appropriate `Accept` and `Sec-Fetch-Dest` headers. To match the syntax to the new semantics, the old `assert` keyword is updated to `with`: + +```javascript +// main.mjs +// +// New 'with' syntax. +import json from './foo.json' with { type: 'json' }; +console.log(json.answer); // 42 +``` + +## Dynamic `import()` + +Similarly, [dynamic `import()`](https://v8.dev/features/dynamic-import#dynamic) is similarly updated to accept a `with` option. + +```javascript +// main.mjs +// +// New 'with' option. +const jsonModule = await import('./foo.json', { + with: { type: 'json' } +}); +console.log(jsonModule.default.answer); // 42 +``` + +## Availability of `with` + +Import attributes is enabled by default in V8 v12.3. + +## Deprecation and eventual removal of `assert` + +The `assert` keyword is deprecated as of V8 v12.3 and is planned to be removed by v12.6. Please use `with` instead of `assert`! Use of the `assert` clause will print a warning to the console urging use of `with` instead. + +## Import attribute support + + diff --git a/src/features/iterator-helpers.md b/src/features/iterator-helpers.md new file mode 100644 index 000000000..1ea2e29ae --- /dev/null +++ b/src/features/iterator-helpers.md @@ -0,0 +1,192 @@ +--- +title: 'Iterator helpers' +author: 'Rezvan Mahdavi Hezaveh' +avatars: + - 'rezvan-mahdavi-hezaveh' +date: 2024-03-27 +tags: + - ECMAScript +description: 'Interfaces that help with general usage and consumption of iterators.' +tweet: '' +--- + +*Iterator helpers* are a collection of new methods on Iterator prototype that help in general use of iterators. Since these helper methods are on the iterator prototype, any object that has `Iterator.prototype` on its prototype chain (e.g. array iterators) will get the methods. In the following subsections, we explain iterator helpers. All the provided examples are working in a blog archive page that includes list of blog posts, illustrating how iterator helpers are helpful for finding and manupulating posts. You can try them on [V8 blog page](https://v8.dev/blog)! + + +## .map(mapperFn) + +`map` takes a mapper function as an argument. This helper returns an iterator of values with the mapper function applied to the original iterator values. + +```javascript +// Select the list of blog posts from a blog archive page. +const posts = document.querySelectorAll('li:not(header li)'); + +// Get the list of posts, return a list of their text content (titles) and log them. +for (const post of posts.values().map((x) => x.textContent)) { + console.log(post); +} +``` + +## .filter(filtererFn) + +`filter` takes a filter function as an argument. This helper returns an iterator of values from the original iterator for which the filter function returned a truthy value. + +```javascript +// Select the list of blog posts from a blog archive page. +const posts = document.querySelectorAll('li:not(header li)'); + +// Filter blog posts that includes `V8` in their text content (titles) and log them. +for (const post of posts.values().filter((x) => x.textContent.includes('V8'))) { + console.log(post); +} +``` + +## .take(limit) + +`take` takes a an integer as an argument. This helper returns an iterator of values from the original iterator, up to `limit` values. + +```javascript +// Select the list of blog posts from a blog archive page. +const posts = document.querySelectorAll('li:not(header li)'); + +// Select 10 recent blog posts and log them. +for (const post of posts.values().take(10)) { + console.log(post); +} +``` + +## .drop(limit) + +`drop` takes a an integer as an argument. This helper returns an iterator of values from the original iterator, starting with the value after the `limit` values. + +```javascript +// Select the list of blog posts from a blog archive page. +const posts = document.querySelectorAll('li:not(header li)'); + +// Drop 10 recent blog posts and log the rest of them. +for (const post of posts.values().drop(10)) { + console.log(post); +} +``` + +## .flatMap(mapperFn) + +`flatMap` takes a mapper function as an argument. This helper returns an iterator of the values of the iterators produced by applying the mapper function to the original iterator values. That is, the iterators returned by the mapper function are flattened into the iterator returned by this helper. + +```javascript +// Select the list of blog posts from a blog archive page. +const posts = document.querySelectorAll('li:not(header li)'); + +// Get list of tags of the blog posts and log them. Each post can have more than +// one tag. +for (const tag of posts.values().flatMap((x) => x.querySelectorAll('.tag').values())) { + console.log(tag.textContent); +} +``` + +## .reduce(reducer [, initialValue ]) + +`reduce` takes a reducer function and an optional initial value. This helper returns one value as a result of applying the reducer function to every value of the iterator while keeping track of the last result of applying the reducer. The initial value is used as the starting point for the reducer function when it processes the first value of the iterator. + +```javascript +// Select the list of blog posts from a blog archive page. +const posts = document.querySelectorAll('li:not(header li)'); + +// Get list of tags for all posts. +const tagLists = posts.values().flatMap((x) => x.querySelectorAll('.tag').values()); + +// Get text context for each tag in the list. +const tags = tagLists.map((x) => x.textContent); + +// Counts posts with security tag. +const count = tags.reduce((sum , value) => sum + (value === 'security' ? 1 : 0), 0); +console.log(count); +``` + +## .toArray() + +`toArray` returns an array from iterator values. + +```javascript +// Select the list of blog posts from a blog archive page. +const posts = document.querySelectorAll('li:not(header li)'); + +// Create an array from the list of 10 recent blog posts. +const arr = posts.values().take(10).toArray(); +``` + +## .forEach(fn) + +`forEach` takes a function as an argument and is applied on each element of the iterator. This helper is called for its side effect and returns `undefined`. + +```javascript +// Select the list of blog posts from a blog archive page. +const posts = document.querySelectorAll('li:not(header li)'); + +// Get the dates that at least one blog post is published and log them. +const dates = new Set(); +const forEach = posts.values().forEach((x) => dates.add(x.querySelector('time'))); +console.log(dates); +``` + +## .some(fn) + +`some` takes a predicate function as an argument. This helper returns `true` if any iterator element returns true when the function is applied to it. The iterator is consumed after `some` is called. + +```javascript +// Select the list of blog posts from a blog archive page. +const posts = document.querySelectorAll('li:not(header li)'); + +// Find out if text content (title) of any blog post includes the `Iterators` +// keyword. +posts.values().some((x) => x.textContent.includes('Iterators')); +``` + +## .every(fn) + +`every` takes a predicate function as an argument. This helper returns `true` if every iterator element returns true when the function is applied to it. The iterator is consumed after `every` is called. + +```javascript +// Select the list of blog posts from a blog archive page. +const posts = document.querySelectorAll('li:not(header li)'); + +// Find out if text content (title) of all blog post includes the `V8` keyword. +posts.values().every((x) => x.textContent.includes('V8')); +``` + +## .find(fn) + +`find` takes a predicate function as an argument. This helper returns the first value of the iterator for which the function returns a truthy value, or `undefined` if no value of the iterator does. + +```javascript +// Select the list of blog posts from a blog archive page. +const posts = document.querySelectorAll('li:not(header li)'); + +// Log the text content (title) of the recent blog post includes `V8` keyword. +console.log(posts.values().find((x) => x.textContent.includes('V8')).textContent); +``` + +## Iterator.from(object) + +`from` is a static method and takes an object as an argument. If the `object` is already an instance of Iterator, the helper returns it directly. If the `object` has `Symbol.iterator`, which means it is an iterable, its `Symbol.iterator` method is called to get the iterator and the helper returns it. Otherwise, a new `Iterator` object (that inherit from `Iterator.prototype` and has `next()` and `return()` methods) is created that wraps the `object` and is returned by this helper. + +```javascript +// Select the list of blog posts from a blog archive page. +const posts = document.querySelectorAll('li:not(header li)'); + +// First create an iterator from the posts. Then, log the text content (title) of +// the recent blog post that includes the `V8` keyword. +console.log(Iterator.from(posts).find((x) => x.textContent.includes('V8')).textContent); +``` + +## Availability + +Iterator helpers are shipped in V8 v12.2. + +## Iterator helpers support + + diff --git a/src/index.njk b/src/index.njk index 86dfb4d21..fc5c2d834 100644 --- a/src/index.njk +++ b/src/index.njk @@ -5,7 +5,7 @@ description: 'V8 is Google’s open source high-performance JavaScript and WebAs ---

What is V8?

-

V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++. It is used in Chrome and in Node.js, among others. It implements ECMAScript and WebAssembly, and runs on Windows 7 or later, macOS 10.12+, and Linux systems that use x64, IA-32, ARM, or MIPS processors. V8 can run standalone, or can be embedded into any C++ application.

+

V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++. It is used in Chrome and in Node.js, among others. It implements ECMAScript and WebAssembly, and runs on Windows, macOS, and Linux systems that use x64, IA-32, or ARM processors. V8 can be embedded into any C++ application.

Latest posts and feature explainers