1 | # ES6 Shim
|
2 | Provides compatibility shims so that legacy JavaScript engines behave as
|
3 | closely as possible to ECMAScript 6 (Harmony).
|
4 |
|
5 | [![Build Status][1]][2] [![dependency status][3]][4] [![dev dependency status][5]][6]
|
6 |
|
7 | [![browser support](https://ci.testling.com/paulmillr/es6-shim.png)](https://ci.testling.com/paulmillr/es6-shim)
|
8 |
|
9 | [![Sauce Test Status](https://saucelabs.com/browser-matrix/es6-shim.svg)](https://saucelabs.com/u/es6-shim)
|
10 |
|
11 | [HTML version of the final ECMAScript 6 spec][spec-html-url]
|
12 |
|
13 | ## Installation
|
14 | If you want to use it in browser:
|
15 |
|
16 | * Just include `es6-shim` before your scripts.
|
17 | * Include [es5-shim][es5-shim-url] especially if your browser doesn't support ECMAScript 5 - but every JS engine requires the `es5-shim` to correct broken implementations, so it's strongly recommended to always include it. Additionally, `es5-shim` should be loaded before `es6-shim`.
|
18 |
|
19 | For `node.js`, `io.js`, or any `npm`-managed workflow (this is the recommended method):
|
20 |
|
21 | npm install es6-shim
|
22 |
|
23 | Alternative methods:
|
24 | * `component install paulmillr/es6-shim` if you’re using [component(1)](https://github.com/componentjs/component).
|
25 | * `bower install es6-shim` if you’re using [Bower](http://bower.io/).
|
26 |
|
27 | In both browser and node you may also want to include `unorm`; see the [`String.prototype.normalize`](#stringprototypenormalize) section for details.
|
28 |
|
29 | ## Safe shims
|
30 |
|
31 | * `Map` (requires ES5 property descriptor support) ([a standalone shim is also available](https://npmjs.com/es-map))
|
32 | * `Set` (requires ES5 property descriptor support) ([a standalone shim is also available](https://npmjs.com/es-set))
|
33 | * `Promise`
|
34 | * `String`:
|
35 | * `fromCodePoint()` ([a standalone shim is also available](https://npmjs.com/string.fromcodepoint))
|
36 | * `raw()` ([a stanadlone shim is also available](https://www.npmjs.com/package/string.raw))
|
37 | * `String.prototype`:
|
38 | * `codePointAt()` ([a standalone shim is also available](https://npmjs.com/string.prototype.codepointat))
|
39 | * `endsWith()` ([a standalone shim is also available](https://npmjs.com/string.prototype.endswith))
|
40 | * `includes()` ([a standalone shim is also available](https://npmjs.com/string.prototype.includes))
|
41 | * `repeat()` ([a standalone shim is also available](https://npmjs.com/string.prototype.repeat))
|
42 | * `startsWith()` ([a standalone shim is also available](https://npmjs.com/string.prototype.startswith))
|
43 | * `RegExp`:
|
44 | * `new RegExp`, when given a RegExp as the pattern, will no longer throw when given a "flags" string argument. (requires ES5)
|
45 | * `RegExp.prototype`:
|
46 | * `flags` (requires ES5) ([a standalone shim is also available](https://npmjs.com/regexp.prototype.flags))
|
47 | * `[Symbol.match]` (requires native `Symbol`s)
|
48 | * `[Symbol.replace]` (requires native `Symbol`s)
|
49 | * `[Symbol.search]` (requires native `Symbol`s)
|
50 | * `[Symbol.split]` (requires native `Symbol`s)
|
51 | * `toString`
|
52 | * `Number`:
|
53 | * binary and octal literals: `Number('0b1')` and `Number('0o7')`
|
54 | * `EPSILON`
|
55 | * `MAX_SAFE_INTEGER`
|
56 | * `MIN_SAFE_INTEGER`
|
57 | * `isNaN()` ([a standalone shim is also available](https://www.npmjs.com/package/is-nan))
|
58 | * `isInteger()` ([a standalone shim is also available(https://www.npmjs.com/package/number.isinteger))
|
59 | * `isSafeInteger()`([a standalone shim is also available](https://www.npmjs.com/package/number.issafeinteger))
|
60 | * `isFinite()` ([a standalone shim is also available](https://www.npmjs.com/package/number.isfinite))
|
61 | * `parseInt()` ([a standalone shim is also available](https://www.npmjs.com/package/parseint))
|
62 | * `parseFloat()`
|
63 | * `Array`:
|
64 | * `from()` ([a standalone shim is also available](https://www.npmjs.com/package/array.from))
|
65 | * `of()` ([a standalone shim is also available](https://www.npmjs.com/package/array.of))
|
66 | * `Array.prototype`:
|
67 | * `copyWithin()` ([a standalone shim is also available](https://npmjs.com/array.prototype.copywithin))
|
68 | * `entries()` ([a standalone shim is also available](https://npmjs.com/array.prototype.entries))
|
69 | * `fill()`
|
70 | * `find()` ([a standalone shim is also available](https://npmjs.com/array.prototype.find))
|
71 | * `findIndex()` ([a standalone shim is also available](https://npmjs.com/array.prototype.findindex))
|
72 | * `keys()` ([a standalone shim is also available](https://npmjs.com/array.prototype.keys))
|
73 | * `values()` ([a standalone shim is also available](https://npmjs.com/array.prototype.values))
|
74 | * `indexOf()` (ES6 errata) ([a standalone shim is also available](https://npmjs.com/array.prototype.indexof))
|
75 | * `Object`:
|
76 | * `assign()` ([a standalone shim is also available](https://npmjs.com/object.assign))
|
77 | * `is()` ([a standalone shim is also available](https://npmjs.com/object-is))
|
78 | * `keys()` (in ES5, but no longer throws on non-object non-null/undefined values in ES6) ([a standalone shim is also available](https://npmjs.com/object-keys)
|
79 | * `setPrototypeOf()` (IE >= 11)
|
80 | * `Function.prototype`:
|
81 | * `name` (es6-sham, covers IE 9-11) ([a standalone shim is also available](https://npmjs.com/function.prototype.name)
|
82 | * `Math`:
|
83 | * `acosh()` ([a standalone shim is also available](https://npmjs.com/math.acosh))
|
84 | * `asinh()`
|
85 | * `atanh()` ([a standalone shim is also available](https://npmjs.com/math.atanh))
|
86 | * `cbrt()` ([a standalone shim is also available](https://npmjs.com/math.cbrt))
|
87 | * `clz32()` ([a standalone shim is also available](https://npmjs.com/math.clz32))
|
88 | * `cosh()`
|
89 | * `expm1()`
|
90 | * `fround()` ([a standalone shim is also available](https://npmjs.com/math.fround))
|
91 | * `hypot()`
|
92 | * `imul()` ([a standalone shim is also available](https://npmjs.com/math.imul))
|
93 | * `log10()` ([a standalone shim is also available](https://npmjs.com/math.log10))
|
94 | * `log1p()` ([a standalone shim is also available](https://npmjs.com/math.log1p))
|
95 | * `log2()`
|
96 | * `sign()` ([a standalone shim is also available](https://npmjs.com/math.sign))
|
97 | * `sinh()`
|
98 | * `tanh()`
|
99 | * `trunc()`
|
100 |
|
101 | Math functions’ accuracy is 1e-11.
|
102 |
|
103 | * `Reflect`
|
104 | * `apply()` ([a standalone shim is also available](https://npmjs.com/reflect.apply))
|
105 | * `construct()`
|
106 | * `defineProperty()`
|
107 | * `deleteProperty()`
|
108 | * `get()`
|
109 | * `getOwnPropertyDescriptor()`
|
110 | * `getPrototypeOf()` ([a standalone shim is also available](https://npmjs.com/reflect.getprototypeof))
|
111 | * `has()`
|
112 | * `isExtensible()`
|
113 | * `ownKeys()` ([a standalone shim is also available](https://npmjs.com/reflect.ownkeys))
|
114 | * `preventExtensions()`
|
115 | * `set()`
|
116 | * `setPrototypeOf()`
|
117 |
|
118 | * `Symbol` (only if it already exists)
|
119 | * `match` (and corresponding `String#match`, `String#startsWith`, `String#endsWith`, `String#includes`, `RegExp` support)
|
120 | * `replace` (and corresponding `String#replace` support)
|
121 | * `search` (and corresponding `String#search` support)
|
122 | * `split` (and corresponding `String#split` support)
|
123 |
|
124 | Well-known symbols will only be provided if the engine already has `Symbol` support.
|
125 |
|
126 | * `String.prototype` Annex B HTML methods ([a standalone shim is also available](https://www.npmjs.com/package/es-string-html-methods))
|
127 | * `anchor()`
|
128 | * `big()`
|
129 | * `blink()`
|
130 | * `bold()`
|
131 | * `fixed()`
|
132 | * `fontcolor()`
|
133 | * `fontsize()`
|
134 | * `italics()`
|
135 | * `link()`
|
136 | * `small()`
|
137 | * `strike()`
|
138 | * `sub()`
|
139 | * `sup()`
|
140 |
|
141 | These methods are part of "Annex B", which means that although they are a defacto standard, you shouldn't use them. None the less, the `es6-shim` provides them and normalizes their behavior across browsers.
|
142 |
|
143 | ## Subclassing
|
144 | The `Map`, `Set`, and `Promise` implementations are subclassable.
|
145 | You should use the following pattern to create a subclass in ES5 which will continue to work in ES6:
|
146 | ```javascript
|
147 | require('es6-shim');
|
148 |
|
149 | function MyPromise(exec) {
|
150 | var promise = new Promise(exec);
|
151 | Object.setPrototypeOf(promise, MyPromise.prototype);
|
152 | // ...
|
153 | return promise;
|
154 | }
|
155 | Object.setPrototypeOf(MyPromise, Promise);
|
156 | MyPromise.prototype = Object.create(Promise.prototype, {
|
157 | constructor: { value: MyPromise }
|
158 | });
|
159 | ```
|
160 |
|
161 | ## String.prototype.normalize
|
162 | Including a proper shim for `String.prototype.normalize` would increase the size of this library by a factor of more than 4.
|
163 | So instead we recommend that you install the [`unorm`](https://github.com/walling/unorm) package alongside `es6-shim` if you need `String.prototype.normalize`.
|
164 | See https://github.com/paulmillr/es6-shim/issues/134 for more discussion.
|
165 |
|
166 |
|
167 | ## WeakMap shim
|
168 | It is not possible to implement WeakMap in pure javascript.
|
169 | The [es6-collections](https://github.com/WebReflection/es6-collections) implementation doesn't hold values strongly, which is critical for the collection. `es6-shim` decided to not include an incorrect shim.
|
170 |
|
171 | `WeakMap` has very unusual use-cases, so you probably won't need it at all (use simple `Map` instead).
|
172 |
|
173 | ## Getting started
|
174 |
|
175 | ```javascript
|
176 | require('es6-shim');
|
177 | var assert = require('assert');
|
178 |
|
179 | assert.equal(true, 'abc'.startsWith('a'));
|
180 | assert.equal(false, 'abc'.endsWith('a'));
|
181 | assert.equal(true, 'john alice'.includes('john'));
|
182 | assert.equal('123'.repeat(2), '123123');
|
183 |
|
184 | assert.equal(false, NaN === NaN);
|
185 | assert.equal(true, Object.is(NaN, NaN));
|
186 | assert.equal(true, -0 === 0);
|
187 | assert.equal(false, Object.is(-0, 0));
|
188 |
|
189 | var result = Object.assign({ a: 1 }, { b: 2 });
|
190 | assert.deepEqual(result, { a: 1, b: 2 });
|
191 |
|
192 | assert.equal(true, isNaN('a'));
|
193 | assert.equal(false, Number.isNaN('a'));
|
194 | assert.equal(true, Number.isNaN(NaN));
|
195 |
|
196 | assert.equal(true, isFinite('123'));
|
197 | assert.equal(false, Number.isFinite('123'));
|
198 | assert.equal(false, Number.isFinite(Infinity));
|
199 |
|
200 | // Tests if value is a number, finite,
|
201 | // >= -9007199254740992 && <= 9007199254740992 and floor(value) === value
|
202 | assert.equal(false, Number.isInteger(2.4));
|
203 |
|
204 | assert.equal(1, Math.sign(400));
|
205 | assert.equal(0, Math.sign(0));
|
206 | assert.equal(-1, Math.sign(-400));
|
207 |
|
208 | var found = [5, 10, 15, 10].find(function (item) { return item / 2 === 5; });
|
209 | assert.equal(10, found);
|
210 |
|
211 | var foundIndex = [5, 10, 15, 10].findIndex(function (item) { return item / 2 === 5; });
|
212 | assert.equal(1, foundIndex);
|
213 |
|
214 | // Replacement for `{}` key-value storage.
|
215 | // Keys can be anything.
|
216 | var map = new Map([['Bob', 42], ['Foo', 'bar']]);
|
217 | map.set('John', 25);
|
218 | map.set('Alice', 400);
|
219 | map.set(['meh'], 555);
|
220 | assert.equal(undefined, map.get(['meh'])); // undefined because you need to use exactly the same object.
|
221 | map.delete('Alice');
|
222 | map.keys();
|
223 | map.values();
|
224 | assert.equal(4, map.size);
|
225 |
|
226 | // Useful for storing unique items.
|
227 | var set = new Set([0, 1]);
|
228 | set.add(2);
|
229 | set.add(5);
|
230 | assert.equal(true, set.has(0));
|
231 | assert.equal(true, set.has(1));
|
232 | assert.equal(true, set.has(2));
|
233 | assert.equal(false, set.has(4));
|
234 | assert.equal(true, set.has(5));
|
235 | set.delete(5);
|
236 | assert.equal(false, set.has(5));
|
237 |
|
238 | // Promises, see
|
239 | // http://www.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript
|
240 | // https://github.com/petkaantonov/bluebird/#what-are-promises-and-why-should-i-use-them
|
241 | Promise.resolve(5).then(function (value) {
|
242 | assert.equal(value, 5);
|
243 | if (value) throw new Error('whoops!');
|
244 | // do some stuff
|
245 | return anotherPromise();
|
246 | }).catch(function (e) {
|
247 | assert.equal(e.message, 'whoops!');
|
248 | assert.equal(true, e instanceof Error);
|
249 | // any errors thrown asynchronously end up here
|
250 | });
|
251 | ```
|
252 |
|
253 | ## Caveats
|
254 |
|
255 | - `Object.setPrototypeOf` / `Reflect.setPrototypeOf`
|
256 | - Note that null objects (`Object.create(null)`, eg, an object with `null` as its `[[Prototype]]`) can not have their `[[Prototype]]` changed except via a native `Object.setPrototypeOf`.
|
257 | - Well-known `Symbol`s
|
258 | - In order to make them work cross-realm, these are created with the global `Symbol` registry via `Symbol.for`. This does not violate the spec, but it does mean that `Symbol.for('Symbol.search') === Symbol.search` will be `true`, which it would not by default in a fresh compliant realm.
|
259 |
|
260 | ## [License][license-url]
|
261 |
|
262 | The project was initially based on es6-shim by Axel Rauschmayer.
|
263 |
|
264 | [1]: https://travis-ci.org/paulmillr/es6-shim.svg
|
265 | [2]: https://travis-ci.org/paulmillr/es6-shim
|
266 | [3]: https://david-dm.org/paulmillr/es6-shim.svg
|
267 | [4]: https://david-dm.org/paulmillr/es6-shim
|
268 | [5]: https://david-dm.org/paulmillr/es6-shim/dev-status.svg
|
269 | [6]: https://david-dm.org/paulmillr/es6-shim#info=devDependencies
|
270 | [license-url]: https://github.com/paulmillr/es6-shim/blob/master/LICENSE
|
271 | [spec-html-url]: http://www.ecma-international.org/ecma-262/6.0/
|
272 | [es5-shim-url]: https://github.com/es-shims/es5-shim
|