Polyfilling Promise.allSettled with core-js/pure: A Minimal, Safe Architecture
Guidance on importing only the needed polyfill, keeping globals clean, and verifying legacy support in a JavaScript library.
07 Feb 2026, 22:47 UTC

Requirements
The library must provide Promise.allSettled behavior for runtimes that lack it natively (e.g., IE11, Node < 12). At the same time, the polyfill must not leak onto the global Promise object, preventing consumers from unintentionally relying on a patched method outside the library’s scope.
Smallest Suitable Design
Import only the specific polyfill module from core-js/pure and expose a thin wrapper that delegates to it. This keeps the rest of core‑js out of the bundle and guarantees that the polyfill lives only in the module’s closure.
// src/allSettled.js
import 'core-js/pure/es/promise/all-settled';
/**
* Returns a promise that settles when all input promises settle.
* @param {Iterable} promises
* @returns {Promise>}
*/
export function allSettled(promises) {
return Promise.allSettled(promises);
}
In a bundler configuration (e.g., webpack) enable tree‑shaking so that only the imported module is retained:
// webpack.config.js
module.exports = {
mode: 'production',
module: {
rules: [{ test: /\.m?js$/, use: 'babel-loader' }]
},
optimization: {
usedExports: true
}
};
Trust and Data Boundaries
Because core-js/pure does not modify built‑in prototypes, the polyfilled Promise.allSettled exists only within the module’s execution context. Consumers who import the library cannot access the polyfill directly; they receive the wrapper function, which internally calls the polyfilled method. This boundary prevents accidental reliance on a global shim.
Operational Checks
- Build‑time verification: After bundling, confirm that the exported wrapper is a function and that the imported polyfill resolved correctly.
- Unit‑test matrix: Run the library’s test suite in two environments:
- A modern runtime (Node ≥ 14 or latest Chrome) where the native method is present.
- A legacy runtime (Node 8 or an IE11 simulator) where the native method is missing.
{status, value, reason}objects matching the spec. - Bundle inspection: Use a source‑map explorer (e.g.,
webpack-bundle-analyzer) to verify that only thecore-js/pure/es/promise/all-settledmodule appears and that no globalPromise.allSettledproperty is created when the library is loaded in a clean iframe. - Legacy runtime smoke test: Execute the bundled library in an Node 8 process and call the wrapper with a mix of resolved and rejected promises; ensure no
ReferenceError: Promise.allSettled is not definedis thrown.
Failure Modes
If the polyfill fails to load (e.g., due to a corrupted core-js version or a network error when using dynamic imports), the wrapper will throw a ReferenceError when invoked because Promise.allSettled remains undefined. The library can catch this and either:
- Return a rejected promise with a clear error message indicating missing ES2021 support.
- Fall back to a no‑op that resolves to an empty array, if the caller can tolerate the loss of functionality.
Either approach should be documented so consumers know how to handle the degradation.
Design‑Change Conditions
The current design would be revisited if any of the following occur:
- The library decides to target only evergreen browsers and Node ≥ 12, making the polyfill unnecessary.
- The API is changed to expose the polyfilled method directly (e.g.,
export { allSettled } from 'core-js/pure/es/promise/all-settled'). In that case, switching tocore-js/stablewould be required to avoid globals pollution, or a re‑export wrapper would need to be added. - A new version of core‑js introduces breaking changes to the pure import path, necessitating an update to the import statement.
When any condition is met, the smallest suitable design should be re‑evaluated and the bundle inspected again to confirm that unused code is removed.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.