1
0
mirror of https://github.com/lancedikson/bowser synced 2026-10-08 11:52:04 +00:00

test: guard ES5 runtime APIs and type-check consumers in CI

Follow-up to the ES5 syntax fix, closing the gaps that investigation left.

An ES5-only runtime sandbox. The acorn check catches syntax, but syntax is
only half the contract: preset-env lowers syntax and never polyfills library
calls, so one `Array.prototype.includes` in the parser source compiles
cleanly, passes every test on modern Node, and throws on the browsers es5.js
exists for. The new test runs both legacy bundles in a vm context with the
post-ES5.1 globals, statics and prototype methods deleted, and asserts
bundled.js additionally installs the polyfills its README entry promises.
Includes a test that the sandbox really strips, so it cannot quietly pass
against a modern global.

A consumer type-check across every module resolution mode, run in CI against
the packed tarball. attw already checks that types *resolve* per condition;
it compiles nothing, so it cannot catch a declaration that resolves correctly
and then misdescribes the runtime. Negative cases are asserted too — the maps
must stay non-importable as named exports, which is the line index.d.mts
draws deliberately and only a failing compile can hold.

Also documents two findings that were investigated and deliberately left
alone: the bundled.js size increase is the core-js 2 -> 3 upgrade rather than
waste, and `useBuiltIns: 'usage'` would shrink it by breaking the documented
"all needed polyfills" contract; and the src/*.js ESM-in-CJS wart (publint
warnings, Yarn PnP, Node < 20.19) is longstanding and identical on 2.14.1,
with the nested-package.json fix blocked on @babel/register.

Verified by breaking each guard in turn: an ES6 API call injected into es5.js
fails the sandbox test, and an index.d.mts with its `parse` export removed
fails all three ESM resolution modes while the CJS modes correctly still pass.
This commit is contained in:
naorpeled
2026-08-30 21:57:22 +03:00
parent 2a2ba39ddb
commit 4f59e5d25e
8 changed files with 288 additions and 2 deletions

View File

@@ -23,6 +23,17 @@ const legacyTargets = {
/**
* `useBuiltIns: false` for `es5.js` (syntax transpilation only) and `'entry'`
* for `bundled.js`, which expands the `core-js/stable` import in its entry.
*
* `'entry'` is why `bundled.js` grew from 124 kB to 174 kB when it stopped
* being built from the deprecated `@babel/polyfill`. That package was core-js
* **2**; `core-js/stable` is core-js **3**, whose stable surface is genuinely
* larger — `globalThis`, `Object.fromEntries` and `URLSearchParams` are all
* new here. The extra weight is the upgrade, not waste.
*
* Switching to `useBuiltIns: 'usage'` would shrink the bundle a long way, and
* would be wrong: the README tells consumers to reach for `bundled.js`
* precisely when they have no polyfills of their own, so it has to keep
* shipping the full payload rather than only what bowser itself calls.
*/
const legacyBabel = (useBuiltIns: false | 'entry') => babel({
presets: [['@babel/preset-env', {