Rob Palmer

@robpalmer.bsky.social

JavaScript Infrastructure & Tooling at Bloomberg. Co-chairing TC39. Likely to tweet tech stuff about JS & software performance. Opinions are my own.

🧾 Introducing npm.tax Estimate the probability of being impacted by a breach in your npm supply chain. Adjust the knobs to see how slimming your node_modules lowers your risk. Look up a package to see its own risk profile, then share the report, e.g. npm.tax?direct=59&tr.... What's your npm tax?

npm.tax: npm supply-chain risk explorer

Explore how your code, npm dependency count, breach probability, and time horizon combine into cumulative supply-chain risk.

npm.tax

👀 JS Composites proposal update "After benchmarking and general reflection, the proposal is now pursuing an interning based approach." - @acutmore We didn't get Records & Tuples but we may still get interned data structures in JS! Really exciting update if this lands in JS

Bild
Rob Palmer@robpalmer.bsky.social · last yr.

ECMAScript excitement 😉 Congrats to @ashley-c.bsky.social on advancing the Composites proposal to Stage 1 at TC39 today 🎉 This is the evolution of Stage 2 Record & Tuple which has now been withdrawn. A key difference is that Composites are objects, not primitives. github.com/tc39/proposa...

Happy to announce Octane – the successor to Inferno. React’s programming model, compiled. Hooks, Suspense and Actions, compiled ahead of time. No virtual DOM. No Rules of Hooks. No manually maintained dependency arrays. The compiler understands what your code. octanejs.dev

// Counter.tsrx — hooks next to output, no rules of hooks
import { useState, useEffect } from 'octane';

export function Counter(props) @{
	const [count, setCount] = useState(0);

	// A hook behind a condition is fine — slots are
	// assigned by call site, not call order.
	if (!props.paused) {
		useEffect(() => {
			console.log('count is now', count);
		}); // the compiler infers [count]
	}

	<button onClick={() => setCount(count + 1)}>{'Count: ' + count}</button>
}

⚠️ Promise.all() makes your code sensitive to destructuring order 🆕 Promise.allKeyed() is IMHO a better alternative in many cases I've been using my "combine-promise" lib for that, and can finally deprecate it soon

Bild
Rob Palmer@robpalmer.bsky.social · last wk.

ECMAScript excitement 😉 Congrats to my coworker @ashley-c.bsky.social at TechAtBloomberg on advancing Await Dictionary to Stage 3 at TC39 🎉 Promise.all returns positional results as an array. Promise.allKeyed allows named results inside an object 👍 github.com/tc39/proposa...

const {
  shape,
  color,
  mass,
} = await Promise.allKeyed({
  shape: getShape(),
  color: getColor(),
  mass: getMass(),
});

This is a really big deal. For us at Vanta, the speedup was a bit less than the highest values some teams have seen (3–5×), but let me tell you: 3–5× is still a very big deal for our CI times, and the improvement to editor performance is night and day.

TypeScript@typescriptlang.org · 4w ago

The 10x is real for many projects, and the speed improvements make a huge difference for teams at scale. TypeScript 7 drops time in CI, and minimizes delays in editors like VS & VS Code. That makes every part of the developer inner loop feel snappy.

Speedups of various projects between TypeScript 6 and 7

vscode 125.7s to 10.6s -- 11.9x
sentry 139.8s to 15.7s -- 8.9x
bluesky 24.3s to 2.8s -- 8.7x
playwright 12.8s to 1.47s -- 8.7x
tldraw 11.2s to 1.46s -- 7.7x

Landed a few improvements to the error reporting for require(esm) with top-level await (behind --experimental-print-required-tla for now): - No longer need to run the code to collect the TLA locations, so it can be enabled by default soon - Added require stack and location metadata to the error

Before: extra noisy arrow pointing to internals, no require stack, needs to run the code to find the top-level await location
After: no more noisy arrows, added require stacks to the output, finds location without running the codeNew ERR_REQUIRE_ASYNC_MODULE includes error.requireStack and error.topLevelAwaitLocations metadata properties