Peter Kröner's Avatar

Peter Kröner

@sirpepe

Developer ✨ edutainment ✨ Shitposting about #javascript and vanilla #webdev. Also there's cat pictures and bursts of travel. Reading web technology specs and doing training/consulting on said web technologies. Also https://mastodon.social/@sir_pepe

169
Followers
116
Following
1,026
Posts
20.11.2023
Joined
Posts Following

Latest posts by Peter Kröner @sirpepe

Preview
Revision 703: Hörenden-Fragen – Progressive Enhancement, Bildformate und JavaScript Disposables | Working Draft In dieser Revision beantworten wir Fragen aus der Hörerschaft. Wir, Peter und Schepp, haben uns einige Themen aus einer längeren Liste herausgepickt und diskutieren darüber, warum bestimmte Web-Techni...

Revision 703: Hörenden-Fragen – Progressive Enhancement, Bildformate und JavaScript Disposables workingdraft.de/703/

11.03.2026 07:26 👍 0 🔁 1 💬 0 📌 0
function doThing(x) {
  if (typeof x === "number" && Number.isInteger(x)) {

  }
}

function doThing(x) { if (typeof x === "number" && Number.isInteger(x)) { } }

🤦 PSA: Number.isInteger() can *only* return true for actual numbers. Feed it any other type, and it is guaranteed to return false. This wasteful pattern is only reproduced by clankers and the incompetent. Do better.

👉 tc39.es/ecma262/#sec...

#javascript #webdev

10.03.2026 09:02 👍 0 🔁 1 💬 0 📌 0
A note in CSS filter spec: For some filter functions the default value for omitted values differes from their initial value for interpolation. For the convenience of content creators, the default value for omitted values for <grayscale()>, <sepia()> and <invert()> is 1 (apply the effect to 100%) while the initial value for interpolation is 0 (no effect).

A note in CSS filter spec: For some filter functions the default value for omitted values differes from their initial value for interpolation. For the convenience of content creators, the default value for omitted values for <grayscale()>, <sepia()> and <invert()> is 1 (apply the effect to 100%) while the initial value for interpolation is 0 (no effect).

Wait, what? The default values for CSS filter functions are literally the way they are to… make producing Instagram cliches easy!?

👉 www.w3.org/TR/filter-ef...

#webdev

10.03.2026 09:17 👍 1 🔁 0 💬 0 📌 0
function doThing(x) {
  if (typeof x === "number" && Number.isInteger(x)) {

  }
}

function doThing(x) { if (typeof x === "number" && Number.isInteger(x)) { } }

🤦 PSA: Number.isInteger() can *only* return true for actual numbers. Feed it any other type, and it is guaranteed to return false. This wasteful pattern is only reproduced by clankers and the incompetent. Do better.

👉 tc39.es/ecma262/#sec...

#javascript #webdev

10.03.2026 09:02 👍 0 🔁 1 💬 0 📌 0
// Generates sequence of numbers
function * range(from, to) {
  while (from < to) {
    yield from++;
  }
}

// Uses range() to output numbers
function * example() {
  let innerGenerator = range(0, 7);
  yield * innerGenerator;
}

let outerGenerator = example();

// Get first value
console.log(outerGenerator.next());

// Respond to first value with error
outerGenerator.throw(new Error("Nope"));

// Generates sequence of numbers function * range(from, to) { while (from < to) { yield from++; } } // Uses range() to output numbers function * example() { let innerGenerator = range(0, 7); yield * innerGenerator; } let outerGenerator = example(); // Get first value console.log(outerGenerator.next()); // Respond to first value with error outerGenerator.throw(new Error("Nope"));

Why use yield* in #JavaScript generators and not just loop over inner Iterables? Because yield* also delegates incoming errors back to the source, so the errors can be handled where they came from. You would rather not shoot the messenger, right?

#webdev

09.03.2026 08:15 👍 0 🔁 1 💬 0 📌 0

I just bring a blow-up pillow, the sort meant for camping. Takes up less space in your luggage than a soda can.

10.03.2026 06:40 👍 1 🔁 0 💬 0 📌 0
Preview
Code.Movie | Declarative animated syntax highlighter Automatically turn code snippets into highlighted step-by-step animations for the web

Every time I want to go to code.movie, I end up at codepen.io. Every time I want to go to codepen.io, I end up at code.movie. Goddamn autocomplete.

09.03.2026 14:34 👍 1 🔁 0 💬 0 📌 0

In other cases the difference IS immediately observable, but requires the use of proxies and inheritance (eg. bsky.app/profile/sirp...). Way too complicated.

09.03.2026 12:50 👍 0 🔁 0 💬 1 📌 0

There would be no immediately observable difference, but if one were to start their research from this observation, getting to the point where no non-fieldness of private properties becomes obvious is straightforward. And that's what I'm after, tangible examples for implementation details.

09.03.2026 12:49 👍 0 🔁 0 💬 1 📌 0
// Generates sequence of numbers
function * range(from, to) {
  while (from < to) {
    yield from++;
  }
}

// Uses range() to output numbers
function * example() {
  let innerGenerator = range(0, 7);
  yield * innerGenerator;
}

let outerGenerator = example();

// Get first value
console.log(outerGenerator.next());

// Respond to first value with error
outerGenerator.throw(new Error("Nope"));

// Generates sequence of numbers function * range(from, to) { while (from < to) { yield from++; } } // Uses range() to output numbers function * example() { let innerGenerator = range(0, 7); yield * innerGenerator; } let outerGenerator = example(); // Get first value console.log(outerGenerator.next()); // Respond to first value with error outerGenerator.throw(new Error("Nope"));

Why use yield* in #JavaScript generators and not just loop over inner Iterables? Because yield* also delegates incoming errors back to the source, so the errors can be handled where they came from. You would rather not shoot the messenger, right?

#webdev

09.03.2026 08:15 👍 0 🔁 1 💬 0 📌 0

I always vehemently denied being surprised :) See bsky.app/profile/sirp...

I was just writing something about how private fields are not fields and thought this was a neat observable side effect of that fact.

09.03.2026 08:05 👍 0 🔁 0 💬 1 📌 0

Ok, I think I almost follow. Our disagreement over what the structured clone algorithm does comes down to which definition of “platform object” we use, right?

09.03.2026 07:38 👍 0 🔁 0 💬 1 📌 0

But both new Map() and new Object() return objects defined by “the platform,” right? I can't find anything in any specs that disentangles this for me; can you help me out?

09.03.2026 07:12 👍 0 🔁 0 💬 1 📌 0
Post image

Mood(s)

08.03.2026 16:26 👍 0 🔁 0 💬 0 📌 0

Damn washing machine pulled a Turkish Airlines 981 on me. Don't design things that can look perfectly closed when they are not, folks!

08.03.2026 12:27 👍 1 🔁 0 💬 0 📌 0
Post image

Please note that Chrome pushed an update, and

YOUR DEV CONSOLE (history) MAY BE READ BY HUMAN REVIEWERS.

Sure, console should never be treated as a secure env, but I still fucking hate this.

06.03.2026 08:34 👍 152 🔁 57 💬 4 📌 20
Post image Post image Post image

🏁

05.03.2026 22:23 👍 0 🔁 0 💬 0 📌 0
Post image

Final stretch

05.03.2026 20:55 👍 0 🔁 0 💬 1 📌 0

Finally moving north (in fits and starts).

05.03.2026 19:25 👍 0 🔁 0 💬 1 📌 0

I left the conference early, hurried through Harburg and power-walked across Pinneberg... to now sit here with the track to Kiel blocked for unknown reasons and for an indeterminate amount of time. Gaaah!

05.03.2026 18:55 👍 0 🔁 0 💬 1 📌 0
Cheese/bread thing on a brown paper bag

Cheese/bread thing on a brown paper bag

While we are waiting around for the train to get going (should have left 10 minutes ago), I'm gonna destroy this 8/10 snack. Looks like it should be disappointing, but is actually extremely tolerable. Traffic Snack in Frankfurt main station is great for when you have like 4 seconds to grab something

05.03.2026 18:42 👍 0 🔁 0 💬 1 📌 0
Inside of a nondescript regional train

Inside of a nondescript regional train

Made the final connection! The first class car is bust, but i could not care less at this point.

05.03.2026 18:31 👍 0 🔁 0 💬 1 📌 0
S-Bahn train arriving in Hamburg

S-Bahn train arriving in Hamburg

I had 60 seconds, I did it in 60 seconds 💪 Next: 3 minutes to make the connection in Pinneberg (in roughly an hour)

05.03.2026 17:32 👍 0 🔁 0 💬 1 📌 0

Last station before Hamburg, 7 Minutes late. I have 8 minutes to make my connection. Thrilling!

05.03.2026 16:59 👍 0 🔁 0 💬 1 📌 0
Post image

So far, so good. Cruising towards Hannover bang on time.

05.03.2026 16:18 👍 0 🔁 0 💬 1 📌 0

But is there any object that's _not_ provided by this definition of “the platform” (encompassing both ECMAScript and DOM) in some fashion?

05.03.2026 15:22 👍 0 🔁 0 💬 1 📌 0
Subway train arriving

Subway train arriving

Let's see how quickly the 3 minute connection in Pinneberg becomes moot, shall we?

05.03.2026 12:58 👍 0 🔁 0 💬 1 📌 0
Preview
Making Firefox’s right-click not suck with about:config A practical about:config checklist to declutter Firefox right-click menus on macOS, disabling AI/chatbot prompts, link previews, OCR, visual search, and other low-value context menu items.

Making Firefox's right-click not suck with about:config

👉 joshua.hu/firefox-maki...

05.03.2026 11:00 👍 0 🔁 0 💬 0 📌 0
Post image

My second talk (about cross-framework performance tuning) is finally a chance to use the web dev alignment chart in a serious context!

05.03.2026 09:15 👍 0 🔁 0 💬 1 📌 0
Tiny conference room with the projector showing slides about "Async/Await 2.0 - Streams and asynchronous Iteration in JavaScript"

Tiny conference room with the projector showing slides about "Async/Await 2.0 - Streams and asynchronous Iteration in JavaScript"

Somehow forgot to keep posting yesterday. Anyway, it's time for the first talk of the conference! While the AI dudes keep on putting the "con" in "conference" with topics like "replace all your forms with chatbots", I'll be sticking to hard-hitting frontend facts 🙃

05.03.2026 07:26 👍 0 🔁 0 💬 1 📌 0