Library / SDK
paulmillr/es6-shim avatar
paulmillr/es6-shim

es6-shim: ES6 compatibility shims for legacy JavaScript engines

ECMAScript 6 compatibility shims for legacy JS engines

3,099 stars372 forksJavaScriptMIT

At a glance

What is it?
es6-shim patches Map, Set, Promise, Symbol and dozens of methods onto engines that predate ECMAScript 6. It is a targeted patch for old browsers, not a transpiler, and its README is explicit about what it will not fix.
Who is it for?
Adopt es6-shim if you must ship one bundle to engines without native Map, Set or Promise and you accept the patch-over-detection model. Do not adopt it if you target only current browsers, or if you need syntax-level ES6 such as arrow functions and let, which a shim cannot add at runtime.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 167 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What es6-shim patches, and the engines it targets

The README describes the project as providing "compatibility shims so that legacy JavaScript engines behave as closely as possible to ECMAScript 6 (Harmony)." That wording matters: the goal is behavioural closeness, not full conformance. The package installs missing globals and prototype methods by detecting what the engine already has and only filling the gaps.

The scope is enumerable. The README lists Map, Set, Promise, Symbol, Reflect, a large block of Math functions, and prototype methods across String, Array, Number, Object, RegExp and Function. The audience is anyone maintaining a bundle that has to run on an engine old enough to lack these, typically a browser from the ES5 era. If your build already targets a runtime with native Map and Promise, the package has little to do and you are paying bundle weight for nothing.

Detection first: how the shim decides to install

The mechanism is conditional assignment. Each shim checks whether the feature exists and behaves correctly, and only defines it when the check fails. That is why the README can call these "safe shims": installing es6-shim on a modern engine is meant to be a no-op rather than an override.

That design has a direct consequence for debugging. When a method misbehaves, the first question is whether you are running the native implementation or the shim, and the answer depends on the engine. The package.json exposes this: the test:native script runs the same suite with NO_ES6_SHIM=1, which disables the shim so the tests exercise the host engine instead. That variable is the practical way to tell the two apart.

Some entries carry explicit prerequisites in the README. Map and Set "require ES5 property descriptor support", and the Symbol.match, Symbol.replace, Symbol.search and Symbol.split entries "require native Symbols". Those are not optional footnotes. On an engine without property descriptors, Map and Set are not going to be installed correctly, and the shim cannot manufacture that capability.

Installing es6-shim and a first real use

The README recommends npm for Node, io.js or any npm-managed workflow, and gives this command.

bash
npm install es6-shim

After that, requiring the package applies the shims as a side effect. The README's browser instructions say to include es6-shim before your scripts, and to include es5-shim first, because "every JS engine requires the es5-shim to correct broken implementations". Load order therefore matters in a browser bundle: es5-shim, then es6-shim, then your code.

The README also documents a standalone shim for Map at the npm package es-map, and for Set at es-set. Those are the granular alternatives discussed below.

There is one more optional dependency worth knowing about. The README says that in both browser and Node you "may also want to include unorm", pointing at the String.prototype.normalize section for the reason. Unicode normalization is not something es6-shim implements on its own.

The es6-sham file and the Function.prototype.name case

The repository ships two source files, es6-shim.js and es6-sham.js, each with a minified build and a source map. The README distinguishes them indirectly: Function.prototype.name is listed under "es6-sham", covering IE 9 through 11, rather than under the safe shims.

That naming is a useful signal about confidence. A shim fills in a method that is missing. A sham approximates behaviour that cannot be reproduced faithfully in that engine. Function.prototype.name is the visible example here, and the README does not present it as exact. If your code depends on function names for anything beyond debugging output, treat that entry as approximate and verify it on the engine you actually support.

The build tooling reinforces the legacy target. The minify scripts run uglifyjs with --support-ie8, and the minified output is written with ascii_only=true. The project is built for engines that need that flag.

Where es6-shim stops: syntax, and the Math accuracy floor

A runtime shim cannot add syntax. es6-shim patches objects and prototypes at load time, which means arrow functions, let and const, destructuring, classes and template literals are outside its reach entirely. If your codebase uses any of those, you need a transpiler such as Babel, and es6-shim is a complement to that pipeline rather than a replacement. This is the most common way to pick the wrong tool here.

The README also states a precision bound: "Math functions' accuracy is 1e-11." That is fine for display arithmetic and risky for anything where accumulated error matters. If you are shimming Math.hypot or Math.expm1 for numerical work, the shim's result is not guaranteed to match a native implementation bit for bit.

Two more constraints are stated rather than implied. Map and Set need ES5 property descriptors, and the Symbol-based RegExp methods need native Symbols. On an engine missing either, those entries do not become available, and the README does not offer a fallback for them.

es6-shim against per-feature shims

The README links a standalone package for nearly every entry it lists: es-map and es-set for collections, array.from, object.assign, number.isinteger, string.prototype.includes, math.cbrt, reflect.apply, regexp.prototype.flags, es-constants for the Number constants, and so on.

The difference in approach is granularity. es6-shim is one file that installs everything it can, with a single load-order rule and a single upgrade to track. The standalone packages let you pull in exactly the gaps your target engine has, which keeps the bundle smaller and makes each dependency's behaviour easier to reason about. The cost is a longer dependency list and more version bookkeeping.

The practical split: if you support one known legacy engine with a known set of gaps, the individual packages give you tighter control. If you support a range of engines and want one consistent baseline, the single shim is simpler to reason about, at the price of shipping code many of your users will never execute.

Maintenance, licence and upgrade cost

The repository is not archived, and its last push was on 2026-04-16. The most recent tagged releases are 0.35.4, 0.35.5 and 0.35.6, all dated 2022-08-12, while package.json declares version 0.35.8. So commits have continued past the newest tag. That is worth knowing before you pin: if you depend on a tag, you are not tracking the tip of master.

The licence is MIT, stated in both the README badge block and package.json. MIT permits commercial use and modification; it requires the copyright notice and licence text to be retained. That is a general description of the licence, not legal advice for your situation.

Upgrade cost is dominated by test surface rather than API churn. The package.json test pipeline runs lint, then mocha over test/**/*.js and test-sham/*.js under nyc, then an npm audit. There are separate test:shim, test:sham and test:native entry points, so you can reproduce the project's own matrix locally. If you rely on the shim for Map or Promise, run the suite against your oldest supported engine before and after any version bump, because a change in detection logic can silently switch an engine from native to shimmed behaviour.

Editorial conclusion

Adopt es6-shim if you must ship one bundle to engines without native Map, Set or Promise and you accept the patch-over-detection model. Do not adopt it if you target only current browsers, or if you need syntax-level ES6 such as arrow functions and let, which a shim cannot add at runtime. Before committing, check the README's requirements list against your oldest target engine, confirm es5-shim loads first in your bundle order, and run the project's own test suite with NO_ES6_SHIM=1 to see which features your runtime already provides natively.

Frequently asked questions

What does ES6 stand for in es6-shim?

ES6 stands for ECMAScript 6, the version the README also calls Harmony. The package description in package.json names it as ECMAScript 6 (Harmony) compatibility shims for legacy JavaScript engines.

Is ES6 the same as ECMAScript 2015 in es6-shim?

The README does not use the name ECMAScript 2015. It refers to ECMAScript 6 and Harmony throughout, and links to an HTML version of the final ECMAScript 6 spec.

What is the difference between ES5 and ES6 for es6-shim users?

es6-shim assumes ES5 is already in place: the README says es5-shim should be loaded before es6-shim, and that Map and Set require ES5 property descriptor support. ES6 is the layer es6-shim adds on top.

What is the difference between ES6 and ES7 in es6-shim?

The README only covers ECMAScript 6 and does not discuss ES7 or later versions. The shim list stops at the ES6 feature set it enumerates.

Official sources

  1. License: MIT
  2. paulmillr/es6-shim on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/paulmillr-es6-shim.svg)](https://hysenlabs.com/projects/paulmillr-es6-shim)