Comparing version 0.9.3 to 0.10.0
{ | ||
"name": "es6-shim", | ||
"repo": "paulmillr/es6-shim", | ||
"version": "0.10.0", | ||
"description": "ECMAScript 6 (Harmony) compatibility shims for legacy JavaScript engines", | ||
"version": "0.9.3", | ||
"keywords": ["ecmascript", "harmony", "es6", "shim"], | ||
"keywords": [ | ||
"ecmascript", | ||
"harmony", | ||
"es6", | ||
"shim", | ||
"promise", | ||
"promises", | ||
"setPrototypeOf", | ||
"map", | ||
"set", | ||
"__proto__" | ||
] | ||
"main": "es6-shim.js", | ||
@@ -8,0 +19,0 @@ "scripts": ["es6-shim.js"], |
@@ -0,1 +1,15 @@ | ||
# es6-shim x.x.x (not yet released) | ||
# es6-shim 0.10.0 (1 March 2014) | ||
* Implement `Promise`, per spec. (#209, #215, #224, #225) | ||
* Make `Map`/`Set` subclassable; support `iterable` argument to | ||
constructor (#218) | ||
* Rename `Number#clz` to `Math.clz32` (#217) | ||
* Bug fixes to `Array#find` and `Array#findIndex` on sparse arrays (#213) | ||
* Re-add `Number.isInteger` (mistakenly removed in 0.9.0) | ||
* Allow use of `arguments` as an iterable | ||
* Minor spec-compliance fixes for `String.raw` | ||
* In ES6, `Object.keys` accepts non-Object types (#220) | ||
* Improved browser compatibility with IE 9/10, Opera 12 (#225) | ||
# es6-shim 0.9.3 (5 February 2014) | ||
@@ -2,0 +16,0 @@ * Per spec, removed `Object.mixin` (#192) |
{ | ||
"name": "es6-shim", | ||
"repo": "paulmillr/es6-shim", | ||
"version": "0.10.0", | ||
"description": "ECMAScript 6 (Harmony) compatibility shims for legacy JavaScript engines", | ||
"version": "0.9.3", | ||
"keywords": ["ecmascript", "harmony", "es6", "shim"], | ||
"keywords": [ | ||
"ecmascript", | ||
"harmony", | ||
"es6", | ||
"shim", | ||
"promise", | ||
"promises", | ||
"setPrototypeOf", | ||
"map", | ||
"set", | ||
"__proto__" | ||
] | ||
"main": "es6-shim.js", | ||
@@ -8,0 +19,0 @@ "scripts": ["es6-shim.js"], |
698
es6-shim.js
@@ -1,2 +0,2 @@ | ||
// ES6-shim 0.9.3 (c) 2013-2014 Paul Miller (http://paulmillr.com) | ||
// ES6-shim 0.10.0 (c) 2013-2014 Paul Miller (http://paulmillr.com) | ||
// ES6-shim may be freely distributed under the MIT license. | ||
@@ -15,2 +15,17 @@ // For more details and documentation: | ||
var supportsSubclassing = function(C, f) { | ||
/* jshint proto:true */ | ||
try { | ||
var Sub = function() { C.apply(this, arguments); }; | ||
if (!Sub.__proto__) { return false; /* skip test on IE < 11 */ } | ||
Object.setPrototypeOf(Sub, C); | ||
Sub.prototype = Object.create(C.prototype, { | ||
constructor: { value: C } | ||
}); | ||
return f(Sub); | ||
} catch (e) { | ||
return false; | ||
} | ||
}; | ||
var arePropertyDescriptorsSupported = function() { | ||
@@ -71,3 +86,3 @@ try { | ||
// pretend to export a "real" Iterator interface. | ||
var $iterator$ = (typeof Symbol === 'object' && Symbol['iterator']) || | ||
var $iterator$ = (typeof Symbol === 'object' && Symbol.iterator) || | ||
'_es6shim_iterator_'; | ||
@@ -87,8 +102,58 @@ // Firefox ships a partial implementation using the name @@iterator. | ||
// taken directly from https://github.com/ljharb/is-arguments/blob/master/index.js | ||
// can be replaced with require('is-arguments') if we ever use a build process instead | ||
var isArguments = function isArguments(value) { | ||
var str = _toString.call(value); | ||
var result = str === '[object Arguments]'; | ||
if (!result) { | ||
result = str !== '[object Array]' && | ||
value !== null && | ||
typeof value === 'object' && | ||
typeof value.length === 'number' && | ||
value.length >= 0 && | ||
_toString.call(value.callee) === '[object Function]'; | ||
} | ||
return result; | ||
}; | ||
var emulateES6construct = function(o) { | ||
if (!ES.TypeIsObject(o)) throw new TypeError('bad object'); | ||
// es5 approximation to es6 subclass semantics: in es6, 'new Foo' | ||
// would invoke Foo.@@create to allocation/initialize the new object. | ||
// In es5 we just get the plain object. So if we detect an | ||
// uninitialized object, invoke o.constructor.@@create | ||
if (!o._es6construct) { | ||
if (o.constructor && ES.IsCallable(o.constructor['@@create'])) { | ||
o = o.constructor['@@create'](o); | ||
} | ||
defineProperties(o, { _es6construct: true }); | ||
} | ||
return o; | ||
}; | ||
var ES = { | ||
CheckObjectCoercible: function(x) { | ||
if (x == null) throw TypeError('Cannot call method on ' + x); | ||
CheckObjectCoercible: function(x, optMessage) { | ||
/* jshint eqnull:true */ | ||
if (x == null) | ||
throw new TypeError(optMessage || ('Cannot call method on ' + x)); | ||
return x; | ||
}, | ||
TypeIsObject: function(x) { | ||
/* jshint eqnull:true */ | ||
// this is expensive when it returns false; use this function | ||
// when you expect it to return true in the common case. | ||
return x != null && Object(x) === x; | ||
}, | ||
ToObject: function(o, optMessage) { | ||
return Object(ES.CheckObjectCoercible(o, optMessage)); | ||
}, | ||
IsCallable: function(x) { | ||
return typeof x === 'function' && | ||
// some versions of IE say that typeof /abc/ === 'function' | ||
_toString.call(x) === '[object Function]'; | ||
}, | ||
ToInt32: function(x) { | ||
@@ -102,3 +167,3 @@ return x >> 0; | ||
toInteger: function(value) { | ||
ToInteger: function(value) { | ||
var number = +value; | ||
@@ -110,2 +175,9 @@ if (Number.isNaN(number)) return 0; | ||
ToLength: function(value) { | ||
var len = ES.ToInteger(value); | ||
if (len <= 0) return 0; // includes converting -0 to +0 | ||
if (len > Number.MAX_SAFE_INTEGER) return Number.MAX_SAFE_INTEGER; | ||
return len; | ||
}, | ||
SameValue: function(a, b) { | ||
@@ -123,2 +195,44 @@ if (a === b) { | ||
return (a === b) || (Number.isNaN(a) && Number.isNaN(b)); | ||
}, | ||
IsIterable: function(o) { | ||
return ES.TypeIsObject(o) && | ||
(ES.IsCallable(o[$iterator$]) || isArguments(o)); | ||
}, | ||
GetIterator: function(o) { | ||
if (isArguments(o)) { | ||
// special case support for `arguments` | ||
return new ArrayIterator(o, "value"); | ||
} | ||
var it = o[$iterator$](); | ||
if (!ES.TypeIsObject(it)) { | ||
throw new TypeError('bad iterator'); | ||
} | ||
return it; | ||
}, | ||
IteratorNext: function(it) { | ||
var result = (arguments.length > 1) ? it.next(arguments[1]) : it.next(); | ||
if (!ES.TypeIsObject(result)) { | ||
throw new TypeError('bad iterator'); | ||
} | ||
return result; | ||
}, | ||
Construct: function(C, args) { | ||
// CreateFromConstructor | ||
var obj; | ||
if (ES.IsCallable(C['@@create'])) { | ||
obj = C['@@create'](); | ||
} else { | ||
// OrdinaryCreateFromConstructor | ||
obj = Object.create(C.prototype || null); | ||
} | ||
// Mark that we've used the es6 construct path | ||
// (see emulateES6construct) | ||
defineProperties(obj, { _es6construct: true }); | ||
// Call the constructor. | ||
var result = C.apply(obj, args); | ||
return ES.TypeIsObject(result) ? result : obj; | ||
} | ||
@@ -272,3 +386,3 @@ }; | ||
next = Number(points[i]); | ||
if (!ES.SameValue(next, ES.toInteger(next)) || | ||
if (!ES.SameValue(next, ES.ToInteger(next)) || | ||
next < 0 || next > 0x10FFFF) { | ||
@@ -289,10 +403,9 @@ throw new RangeError('Invalid code point ' + next); | ||
raw: function() { | ||
var callSite = arguments.length > 0 ? arguments[0] : undefined; | ||
raw: function(callSite) { // raw.length===1 | ||
var substitutions = _slice.call(arguments, 1, arguments.length); | ||
var cooked = Object(callSite); | ||
var cooked = ES.ToObject(callSite, 'bad callSite'); | ||
var rawValue = cooked.raw; | ||
var raw = Object(rawValue); | ||
var raw = ES.ToObject(rawValue, 'bad raw value'); | ||
var len = Object.keys(raw).length; | ||
var literalsegments = ES.ToUint32(len); | ||
var literalsegments = ES.ToLength(len); | ||
if (literalsegments === 0) { | ||
@@ -338,3 +451,3 @@ return ''; | ||
var thisStr = String(ES.CheckObjectCoercible(this)); | ||
times = ES.toInteger(times); | ||
times = ES.ToInteger(times); | ||
if (times < 0 || times === Infinity) { | ||
@@ -352,3 +465,3 @@ throw new RangeError('Invalid String#repeat value'); | ||
var startArg = arguments.length > 1 ? arguments[1] : undefined; | ||
var start = Math.max(ES.toInteger(startArg), 0); | ||
var start = Math.max(ES.ToInteger(startArg), 0); | ||
return thisStr.slice(start, start + searchStr.length) === searchStr; | ||
@@ -363,3 +476,3 @@ }, | ||
var posArg = arguments.length > 1 ? arguments[1] : undefined; | ||
var pos = posArg === undefined ? thisLen : ES.toInteger(posArg); | ||
var pos = posArg === undefined ? thisLen : ES.ToInteger(posArg); | ||
var end = Math.min(Math.max(pos, 0), thisLen); | ||
@@ -377,3 +490,3 @@ return thisStr.slice(end - searchStr.length, end) === searchStr; | ||
var thisStr = String(ES.CheckObjectCoercible(this)); | ||
var position = ES.toInteger(pos); | ||
var position = ES.ToInteger(pos); | ||
var length = thisStr.length; | ||
@@ -393,4 +506,3 @@ if (position < 0 || position >= length) return undefined; | ||
var StringIterator = function(s) { | ||
if (s==null) { throw new TypeError('StringIterator: given null'); } | ||
this._s = String(s); | ||
this._s = String(ES.CheckObjectCoercible(s)); | ||
this._i = 0; | ||
@@ -430,16 +542,14 @@ }; | ||
if (iterable === null || iterable === undefined) { | ||
throw new TypeError('Array.from: null or undefined are not valid values. Use []'); | ||
} else if (mapFn !== undefined && _toString.call(mapFn) !== '[object Function]') { | ||
var list = ES.ToObject(iterable, 'bad iterable'); | ||
if (mapFn !== undefined && !ES.IsCallable(mapFn)) { | ||
throw new TypeError('Array.from: when provided, the second argument must be a function'); | ||
} | ||
var list = Object(iterable); | ||
var usingIterator = ($iterator$ in list); | ||
var usingIterator = ES.IsIterable(list); | ||
// does the spec really mean that Arrays should use ArrayIterator? | ||
// https://bugs.ecmascript.org/show_bug.cgi?id=2416 | ||
//if (Array.isArray(list)) { usingIterator=false; } | ||
var length = usingIterator ? 0 : ES.ToUint32(list.length); | ||
var result = typeof this === 'function' ? Object(usingIterator ? new this() : new this(length)) : new Array(length); | ||
var it = usingIterator ? list[$iterator$]() : null; | ||
var length = usingIterator ? 0 : ES.ToLength(list.length); | ||
var result = ES.IsCallable(this) ? Object(usingIterator ? new this() : new this(length)) : new Array(length); | ||
var it = usingIterator ? ES.GetIterator(list) : null; | ||
var value; | ||
@@ -449,6 +559,3 @@ | ||
if (usingIterator) { | ||
value = it.next(); | ||
if (value == null || typeof value !== 'object') { | ||
throw new TypeError("Bad iterator"); | ||
} | ||
value = ES.IteratorNext(it); | ||
if (value.done) { | ||
@@ -493,3 +600,4 @@ length = i; | ||
if (array!==undefined) { | ||
for (; i < array.length; i++) { | ||
var len = ES.ToLength(array.length); | ||
for (; i < len; i++) { | ||
var kind = this.kind; | ||
@@ -518,9 +626,12 @@ var retval; | ||
copyWithin: function(target, start) { | ||
var o = Object(this); | ||
var len = Math.max(ES.toInteger(o.length), 0); | ||
var end = arguments[2]; // copyWithin.length must be 2 | ||
var o = ES.ToObject(this); | ||
var len = ES.ToLength(o.length); | ||
target = ES.ToInteger(target); | ||
start = ES.ToInteger(start); | ||
var to = target < 0 ? Math.max(len + target, 0) : Math.min(target, len); | ||
var from = start < 0 ? Math.max(len + start, 0) : Math.min(start, len); | ||
var end = arguments.length > 2 ? arguments[2] : len; | ||
var final = end < 0 ? Math.max(len + end, 0) : Math.min(end, len); | ||
var count = Math.min(final - from, len - to); | ||
end = (end===undefined) ? len : ES.ToInteger(end); | ||
var fin = end < 0 ? Math.max(len + end, 0) : Math.min(end, len); | ||
var count = Math.min(fin - from, len - to); | ||
var direction = 1; | ||
@@ -545,5 +656,7 @@ if (from < to && to < (from + count)) { | ||
fill: function(value) { | ||
var len = this.length; | ||
var start = arguments.length > 1 ? ES.toInteger(arguments[1]) : 0; | ||
var end = arguments.length > 2 ? ES.toInteger(arguments[2]) : len; | ||
var start = arguments[1], end = arguments[2]; // fill.length===1 | ||
var O = ES.ToObject(this); | ||
var len = ES.ToLength(O.length); | ||
start = ES.ToInteger(start===undefined ? 0 : start); | ||
end = ES.ToInteger(end===undefined ? len : end); | ||
@@ -553,18 +666,19 @@ var relativeStart = start < 0 ? Math.max(len + start, 0) : Math.min(start, len); | ||
for (var i = relativeStart; i < len && i < end; ++i) { | ||
this[i] = value; | ||
O[i] = value; | ||
} | ||
return this; | ||
return O; | ||
}, | ||
find: function(predicate) { | ||
var list = Object(this); | ||
var length = ES.ToUint32(list.length); | ||
if (length === 0) return undefined; | ||
if (typeof predicate !== 'function') { | ||
var list = ES.ToObject(this); | ||
var length = ES.ToLength(list.length); | ||
if (!ES.IsCallable(predicate)) { | ||
throw new TypeError('Array#find: predicate must be a function'); | ||
} | ||
var thisArg = arguments.length > 1 ? arguments[1] : undefined; | ||
for (var i = 0, value; i < length && i in list; i++) { | ||
value = list[i]; | ||
if (predicate.call(thisArg, value, i, list)) return value; | ||
var thisArg = arguments[1]; | ||
for (var i = 0, value; i < length; i++) { | ||
if (i in list) { | ||
value = list[i]; | ||
if (predicate.call(thisArg, value, i, list)) return value; | ||
} | ||
} | ||
@@ -575,11 +689,12 @@ return undefined; | ||
findIndex: function(predicate) { | ||
var list = Object(this); | ||
var length = ES.ToUint32(list.length); | ||
if (length === 0) return -1; | ||
if (typeof predicate !== 'function') { | ||
var list = ES.ToObject(this); | ||
var length = ES.ToLength(list.length); | ||
if (!ES.IsCallable(predicate)) { | ||
throw new TypeError('Array#findIndex: predicate must be a function'); | ||
} | ||
var thisArg = arguments.length > 1 ? arguments[1] : undefined; | ||
for (var i = 0; i < length && i in list; i++) { | ||
if (predicate.call(thisArg, list[i], i, list)) return i; | ||
var thisArg = arguments[1]; | ||
for (var i = 0; i < length; i++) { | ||
if (i in list) { | ||
if (predicate.call(thisArg, list[i], i, list)) return i; | ||
} | ||
} | ||
@@ -619,7 +734,11 @@ return -1; | ||
isSafeInteger: function(value) { | ||
isInteger: function(value) { | ||
return typeof value === 'number' && | ||
!Number.isNaN(value) && | ||
Number.isFinite(value) && | ||
parseInt(value, 10) === value && | ||
ES.ToInteger(value) === value; | ||
}, | ||
isSafeInteger: function(value) { | ||
return Number.isInteger(value) && | ||
Math.abs(value) <= Number.MAX_SAFE_INTEGER; | ||
@@ -635,3 +754,3 @@ }, | ||
return value !== value; | ||
}, | ||
} | ||
@@ -641,9 +760,2 @@ }); | ||
defineProperties(Number.prototype, { | ||
clz: function() { | ||
var number = Number.prototype.valueOf.call(this) >>> 0; | ||
if (number === 0) { | ||
return 32; | ||
} | ||
return 32 - (number).toString(2).length; | ||
} | ||
}); | ||
@@ -704,7 +816,7 @@ | ||
var checkArgs = function(O, proto) { | ||
if (typeof O !== 'object' || O === null) { | ||
if (!ES.TypeIsObject(O)) { | ||
throw new TypeError('cannot set prototype on a non-object'); | ||
} | ||
if (typeof proto !== 'object') { | ||
throw new TypeError('can only set prototype to an object or null'); | ||
if (!(proto===null || ES.TypeIsObject(proto))) { | ||
throw new TypeError('can only set prototype to an object or null'+proto); | ||
} | ||
@@ -754,2 +866,22 @@ }; | ||
// Workaround bug in Opera 12 where setPrototypeOf(x, null) doesn't work, | ||
// but Object.create(null) does. | ||
if (Object.setPrototypeOf && Object.getPrototypeOf && | ||
Object.getPrototypeOf(Object.setPrototypeOf({}, null)) !== null && | ||
Object.getPrototypeOf(Object.create(null)) === null) { | ||
(function() { | ||
var FAKENULL = Object.create(null); | ||
var gpo = Object.getPrototypeOf, spo = Object.setPrototypeOf; | ||
Object.getPrototypeOf = function(o) { | ||
var result = gpo(o); | ||
return result === FAKENULL ? null : result; | ||
}; | ||
Object.setPrototypeOf = function(o, p) { | ||
if (p === null) { p = FAKENULL; } | ||
return spo(o, p); | ||
}; | ||
Object.setPrototypeOf.polyfill = false; | ||
})(); | ||
} | ||
defineProperties(Object, { | ||
@@ -765,2 +897,11 @@ getOwnPropertyKeys: function(subject) { | ||
try { | ||
Object.keys('foo'); | ||
} catch (e) { | ||
var originalObjectKeys = Object.keys; | ||
Object.keys = function (obj) { | ||
return originalObjectKeys(ES.ToObject(obj)); | ||
}; | ||
} | ||
var MathShims = { | ||
@@ -803,2 +944,13 @@ acosh: function(value) { | ||
clz32: function(value) { | ||
// See https://bugs.ecmascript.org/show_bug.cgi?id=2465 | ||
value = Number(value); | ||
if (Number.isNaN(value)) return NaN; | ||
var number = ES.ToUint32(value); | ||
if (number === 0) { | ||
return 32; | ||
} | ||
return 32 - (number).toString(2).length; | ||
}, | ||
cosh: function(value) { | ||
@@ -937,2 +1089,337 @@ value = Number(value); | ||
// Promises | ||
// Simplest possible implementation; use a 3rd-party library if you | ||
// want the best possible speed and/or long stack traces. | ||
var PromiseShim = (function() { | ||
var Promise, Promise$prototype; | ||
ES.IsPromise = function(promise) { | ||
if (!ES.TypeIsObject(promise)) { | ||
return false; | ||
} | ||
if (!promise._promiseConstructor) { | ||
// _promiseConstructor is a bit more unique than _status, so we'll | ||
// check that instead of the [[PromiseStatus]] internal field. | ||
return false; | ||
} | ||
if (promise._status === undefined) { | ||
return false; // uninitialized | ||
} | ||
return true; | ||
}; | ||
// "PromiseCapability" in the spec is what most promise implementations | ||
// call a "deferred". | ||
var PromiseCapability = function(C) { | ||
if (!ES.IsCallable(C)) { | ||
throw new TypeError('bad promise constructor'); | ||
} | ||
var capability = this; | ||
var resolver = function(resolve, reject) { | ||
capability.resolve = resolve; | ||
capability.reject = reject; | ||
}; | ||
capability.promise = ES.Construct(C, [resolver]); | ||
if (!(ES.IsCallable(capability.resolve) && | ||
ES.IsCallable(capability.reject))) { | ||
throw new TypeError('bad promise constructor'); | ||
} | ||
}; | ||
// find an appropriate setImmediate-alike | ||
var setTimeout = globals.setTimeout; | ||
var makeZeroTimeout = function() { | ||
// from http://dbaron.org/log/20100309-faster-timeouts | ||
var timeouts = []; | ||
var messageName = "zero-timeout-message"; | ||
var setZeroTimeout = function(fn) { | ||
timeouts.push(fn); | ||
window.postMessage(messageName, "*"); | ||
}; | ||
var handleMessage = function(event) { | ||
if (event.source == window && event.data == messageName) { | ||
event.stopPropagation(); | ||
if (timeouts.length === 0) { return; } | ||
var fn = timeouts.shift(); | ||
fn(); | ||
} | ||
}; | ||
window.addEventListener("message", handleMessage, true); | ||
return setZeroTimeout; | ||
}; | ||
var enqueue = ES.IsCallable(globals.setImmediate) ? | ||
globals.setImmediate.bind(globals) : | ||
typeof process === 'object' && process.nextTick ? process.nextTick : | ||
ES.IsCallable(window.postMessage) ? makeZeroTimeout() : | ||
function(task) { setTimeout(task, 0); }; // fallback | ||
var triggerPromiseReactions = function(reactions, x) { | ||
reactions.forEach(function(reaction) { | ||
enqueue(function() { | ||
// PromiseReactionTask | ||
var handler = reaction.handler; | ||
var capability = reaction.capability; | ||
var resolve = capability.resolve; | ||
var reject = capability.reject; | ||
try { | ||
var result = handler(x); | ||
if (result === capability.promise) { | ||
throw new TypeError('self resolution'); | ||
} | ||
var updateResult = | ||
updatePromiseFromPotentialThenable(result, capability); | ||
if (!updateResult) { | ||
resolve(result); | ||
} | ||
} catch (e) { | ||
reject(e); | ||
} | ||
}); | ||
}); | ||
}; | ||
var updatePromiseFromPotentialThenable = function(x, capability) { | ||
if (!ES.TypeIsObject(x)) { | ||
return false; | ||
} | ||
var resolve = capability.resolve; | ||
var reject = capability.reject; | ||
try { | ||
var then = x.then; // only one invocation of accessor | ||
if (!ES.IsCallable(then)) { return false; } | ||
then.call(x, resolve, reject); | ||
} catch(e) { | ||
reject(e); | ||
} | ||
return true; | ||
}; | ||
var promiseResolutionHandler = function(promise, onFulfilled, onRejected){ | ||
return function(x) { | ||
if (x === promise) { | ||
return onRejected(new TypeError('self resolution')); | ||
} | ||
var C = promise._promiseConstructor; | ||
var capability = new PromiseCapability(C); | ||
var updateResult = updatePromiseFromPotentialThenable(x, capability); | ||
if (updateResult) { | ||
return capability.promise.then(onFulfilled, onRejected); | ||
} else { | ||
return onFulfilled(x); | ||
} | ||
}; | ||
}; | ||
Promise = function(resolver) { | ||
var promise = this; | ||
promise = emulateES6construct(promise); | ||
if (!promise._promiseConstructor) { | ||
// we use _promiseConstructor as a stand-in for the internal | ||
// [[PromiseStatus]] field; it's a little more unique. | ||
throw new TypeError('bad promise'); | ||
} | ||
if (promise._status !== undefined) { | ||
throw new TypeError('promise already initialized'); | ||
} | ||
// see https://bugs.ecmascript.org/show_bug.cgi?id=2482 | ||
if (!ES.IsCallable(resolver)) { | ||
throw new TypeError('not a valid resolver'); | ||
} | ||
promise._status = 'unresolved'; | ||
promise._resolveReactions = []; | ||
promise._rejectReactions = []; | ||
var resolve = function(resolution) { | ||
if (promise._status !== 'unresolved') { return; } | ||
var reactions = promise._resolveReactions; | ||
promise._result = resolution; | ||
promise._resolveReactions = undefined; | ||
promise._rejectReactions = undefined; | ||
promise._status = 'has-resolution'; | ||
triggerPromiseReactions(reactions, resolution); | ||
}; | ||
var reject = function(reason) { | ||
if (promise._status !== 'unresolved') { return; } | ||
var reactions = promise._rejectReactions; | ||
promise._result = reason; | ||
promise._resolveReactions = undefined; | ||
promise._rejectReactions = undefined; | ||
promise._status = 'has-rejection'; | ||
triggerPromiseReactions(reactions, reason); | ||
}; | ||
try { | ||
resolver(resolve, reject); | ||
} catch (e) { | ||
reject(e); | ||
} | ||
return promise; | ||
}; | ||
Promise$prototype = Promise.prototype; | ||
defineProperties(Promise, { | ||
'@@create': function(obj) { | ||
var constructor = this; | ||
// AllocatePromise | ||
// The `obj` parameter is a hack we use for es5 | ||
// compatibility. | ||
var prototype = constructor.prototype || Promise$prototype; | ||
obj = obj || Object.create(prototype); | ||
defineProperties(obj, { | ||
_status: undefined, | ||
_result: undefined, | ||
_resolveReactions: undefined, | ||
_rejectReactions: undefined, | ||
_promiseConstructor: undefined | ||
}); | ||
obj._promiseConstructor = constructor; | ||
return obj; | ||
} | ||
}); | ||
var _promiseAllResolver = function(index, values, capability, remaining) { | ||
var done = false; | ||
return function(x) { | ||
if (done) { return; } // protect against being called multiple times | ||
done = true; | ||
values[index] = x; | ||
if ((--remaining.count) === 0) { | ||
var resolve = capability.resolve; | ||
resolve(values); // call w/ this===undefined | ||
} | ||
}; | ||
}; | ||
Promise.all = function(iterable) { | ||
var C = this; | ||
var capability = new PromiseCapability(C); | ||
var resolve = capability.resolve; | ||
var reject = capability.reject; | ||
try { | ||
if (!ES.IsIterable(iterable)) { | ||
throw new TypeError('bad iterable'); | ||
} | ||
var it = ES.GetIterator(iterable); | ||
var values = [], remaining = { count: 1 }; | ||
for (var index = 0; ; index++) { | ||
var next = ES.IteratorNext(it); | ||
if (next.done) { | ||
break; | ||
} | ||
var nextPromise = C.resolve(next.value); | ||
var resolveElement = _promiseAllResolver( | ||
index, values, capability, remaining | ||
); | ||
remaining.count++; | ||
nextPromise.then(resolveElement, capability.reject); | ||
} | ||
if ((--remaining.count) === 0) { | ||
resolve(values); // call w/ this===undefined | ||
} | ||
} catch (e) { | ||
reject(e); | ||
} | ||
return capability.promise; | ||
}; | ||
Promise.race = function(iterable) { | ||
var C = this; | ||
var capability = new PromiseCapability(C); | ||
var resolve = capability.resolve; | ||
var reject = capability.reject; | ||
try { | ||
if (!ES.IsIterable(iterable)) { | ||
throw new TypeError('bad iterable'); | ||
} | ||
var it = ES.GetIterator(iterable); | ||
while (true) { | ||
var next = ES.IteratorNext(it); | ||
if (next.done) { | ||
// If iterable has no items, resulting promise will never | ||
// resolve; see: | ||
// https://github.com/domenic/promises-unwrapping/issues/75 | ||
// https://bugs.ecmascript.org/show_bug.cgi?id=2515 | ||
break; | ||
} | ||
var nextPromise = C.resolve(next.value); | ||
nextPromise.then(resolve, reject); | ||
} | ||
} catch (e) { | ||
reject(e); | ||
} | ||
return capability.promise; | ||
}; | ||
Promise.reject = function(reason) { | ||
var C = this; | ||
var capability = new PromiseCapability(C); | ||
var reject = capability.reject; | ||
reject(reason); // call with this===undefined | ||
return capability.promise; | ||
}; | ||
Promise.resolve = function(v) { | ||
var C = this; | ||
if (ES.IsPromise(v)) { | ||
var constructor = v._promiseConstructor; | ||
if (constructor === C) { return v; } | ||
} | ||
var capability = new PromiseCapability(C); | ||
var resolve = capability.resolve; | ||
resolve(v); // call with this===undefined | ||
return capability.promise; | ||
}; | ||
Promise.prototype['catch'] = function( onRejected ) { | ||
return this.then(undefined, onRejected); | ||
}; | ||
Promise.prototype.then = function( onFulfilled, onRejected ) { | ||
var promise = this; | ||
if (!ES.IsPromise(promise)) { throw new TypeError('not a promise'); } | ||
// this.constructor not this._promiseConstructor; see | ||
// https://bugs.ecmascript.org/show_bug.cgi?id=2513 | ||
var C = this.constructor; | ||
var capability = new PromiseCapability(C); | ||
if (!ES.IsCallable(onRejected)) { | ||
onRejected = function(e) { throw e; }; | ||
} | ||
if (!ES.IsCallable(onFulfilled)) { | ||
onFulfilled = function(x) { return x; }; | ||
} | ||
var resolutionHandler = | ||
promiseResolutionHandler(promise, onFulfilled, onRejected); | ||
var resolveReaction = | ||
{ capability: capability, handler: resolutionHandler }; | ||
var rejectReaction = | ||
{ capability: capability, handler: onRejected }; | ||
switch (promise._status) { | ||
case 'unresolved': | ||
promise._resolveReactions.push(resolveReaction); | ||
promise._rejectReactions.push(rejectReaction); | ||
break; | ||
case 'has-resolution': | ||
triggerPromiseReactions([resolveReaction], promise._result); | ||
break; | ||
case 'has-rejection': | ||
triggerPromiseReactions([rejectReaction], promise._result); | ||
break; | ||
default: | ||
throw new TypeError('unexpected'); | ||
} | ||
return capability.promise; | ||
}; | ||
return Promise; | ||
})(); | ||
// export the Promise constructor. | ||
defineProperties(globals, { Promise: PromiseShim }); | ||
// In Chrome 33 (and thereabouts) Promise is defined, but the | ||
// implementation is buggy in a number of ways. Let's check subclassing | ||
// support to see if we have a buggy implementation. | ||
if (!supportsSubclassing(globals.Promise, function(S) { | ||
return S.resolve(42) instanceof S; | ||
})) { | ||
globals.Promise = PromiseShim; | ||
} | ||
// Map and Set require a true ES5 environment | ||
@@ -1012,3 +1499,7 @@ if (supportsDescriptors) { | ||
function Map() { | ||
if (!(this instanceof Map)) throw new TypeError('Map must be called with "new"'); | ||
var map = this; | ||
map = emulateES6construct(map); | ||
if (!map._es6map) { | ||
throw new TypeError('bad map'); | ||
} | ||
@@ -1019,3 +1510,3 @@ var head = new MapEntry(null, null); | ||
defineProperties(this, { | ||
defineProperties(map, { | ||
'_head': head, | ||
@@ -1025,3 +1516,31 @@ '_storage': emptyObject(), | ||
}); | ||
// Optionally initialize map from iterable | ||
var iterable = arguments[0]; | ||
if (iterable !== undefined && iterable !== null) { | ||
var it = ES.GetIterator(iterable); | ||
var adder = map.set; | ||
if (!ES.IsCallable(adder)) { throw new TypeError('bad map'); } | ||
while (true) { | ||
var next = ES.IteratorNext(it); | ||
if (next.done) { break; } | ||
var nextItem = next.value; | ||
if (!ES.TypeIsObject(nextItem)) { | ||
throw new TypeError('expected iterable of pairs'); | ||
} | ||
adder.call(map, nextItem[0], nextItem[1]); | ||
} | ||
} | ||
return map; | ||
} | ||
var Map$prototype = Map.prototype; | ||
defineProperties(Map, { | ||
'@@create': function(obj) { | ||
var constructor = this; | ||
var prototype = constructor.prototype || Map$prototype; | ||
obj = obj || Object.create(prototype); | ||
defineProperties(obj, { _es6map: true }); | ||
return obj; | ||
} | ||
}); | ||
@@ -1169,8 +1688,38 @@ Object.defineProperty(Map.prototype, 'size', { | ||
var SetShim = function Set() { | ||
if (!(this instanceof SetShim)) throw new TypeError('Set must be called with "new"'); | ||
defineProperties(this, { | ||
var set = this; | ||
set = emulateES6construct(set); | ||
if (!set._es6set) { | ||
throw new TypeError('bad set'); | ||
} | ||
defineProperties(set, { | ||
'[[SetData]]': null, | ||
'_storage': emptyObject() | ||
}); | ||
// Optionally initialize map from iterable | ||
var iterable = arguments[0]; | ||
if (iterable !== undefined && iterable !== null) { | ||
var it = ES.GetIterator(iterable); | ||
var adder = set.add; | ||
if (!ES.IsCallable(adder)) { throw new TypeError('bad set'); } | ||
while (true) { | ||
var next = ES.IteratorNext(it); | ||
if (next.done) { break; } | ||
var nextItem = next.value; | ||
adder.call(set, nextItem); | ||
} | ||
} | ||
return set; | ||
}; | ||
var Set$prototype = SetShim.prototype; | ||
defineProperties(SetShim, { | ||
'@@create': function(obj) { | ||
var constructor = this; | ||
var prototype = constructor.prototype || Set$prototype; | ||
obj = obj || Object.create(prototype); | ||
defineProperties(obj, { _es6set: true }); | ||
return obj; | ||
} | ||
}); | ||
@@ -1292,3 +1841,6 @@ // Switch from the object backing storage to a full Map. | ||
isCallableWithoutNew(globals.Map) || | ||
isCallableWithoutNew(globals.Set) | ||
isCallableWithoutNew(globals.Set) || | ||
!supportsSubclassing(globals.Map, function(M) { | ||
return (new M([])) instanceof M; | ||
}) | ||
) { | ||
@@ -1295,0 +1847,0 @@ globals.Map = collectionShims.Map; |
{ | ||
"author": "Paul Miller (http://paulmillr.com)", | ||
"name": "es6-shim", | ||
"version": "0.10.0", | ||
"description": "ECMAScript 6 (Harmony) compatibility shims for legacy JavaScript engines", | ||
"keywords": ["ecmascript", "harmony", "es6", "shim"], | ||
"version": "0.9.3", | ||
"keywords": [ | ||
"ecmascript", | ||
"harmony", | ||
"es6", | ||
"shim", | ||
"promise", | ||
"promises", | ||
"setPrototypeOf", | ||
"map", | ||
"set", | ||
"__proto__" | ||
], | ||
"homepage": "https://github.com/paulmillr/es6-shim/", | ||
@@ -14,3 +25,3 @@ "repository": { | ||
"scripts": { | ||
"test": "mocha" | ||
"test": "jshint es6-shim.js && mocha test/*.js test/*/*.js" | ||
}, | ||
@@ -38,4 +49,6 @@ "testling": { | ||
"chai": "~1.9.0", | ||
"es5-shim": "~2.3.0" | ||
"es5-shim": "~2.3.0", | ||
"jshint": "~2.4.3", | ||
"promises-aplus-tests": "~2.0.3" | ||
} | ||
} |
@@ -21,5 +21,10 @@ # ES6 Shim | ||
In both browser and node you may also want to include `unorm`; see the | ||
[`String.prototype.normalize`](#stringprototypenormalize) section for | ||
details. | ||
## Safe shims | ||
* `Map`, `Set` (requires ES5) | ||
* `Promise` | ||
* `String`: | ||
@@ -36,2 +41,3 @@ * `fromCodePoint()` ([a standalone shim is also available](http://mths.be/fromcodepoint)) | ||
* `MAX_SAFE_INTEGER` | ||
* `MIN_SAFE_INTEGER` | ||
* `EPSILON` | ||
@@ -41,6 +47,5 @@ * `parseInt()` | ||
* `isNaN()`([a standalone shim is also available](https://npmjs.org/package/is-nan)) | ||
* `isInteger()` | ||
* `isSafeInteger()` | ||
* `isFinite()` | ||
* `Number.prototype`: | ||
* `clz()` | ||
* `Array`: | ||
@@ -50,2 +55,4 @@ * `from()` | ||
* `Array.prototype`: | ||
* `copyWithin()` | ||
* `fill()` | ||
* `find()` ([a standalone shim is also available](https://github.com/paulmillr/Array.prototype.find)) | ||
@@ -60,22 +67,53 @@ * `findIndex()` ([a standalone shim is also available](https://github.com/paulmillr/Array.prototype.findIndex)) | ||
* `getPropertyNames()` (ES5) | ||
* `is()` | ||
* `getPropertyKeys()` (ES5) | ||
* `keys()` (ES5) | ||
* `is()` ([a standalone shim is also available](https://github.com/ljharb/object-is)) | ||
* `assign()` | ||
* `setPrototypeOf()` (IE >= 11) | ||
* `Math`: | ||
* `sign()` | ||
* `acosh()` | ||
* `asinh()` | ||
* `atanh()` | ||
* `cbrt()` | ||
* `clz32()` | ||
* `cosh()` | ||
* `expm1()` | ||
* `hypot()` | ||
* `log2()` | ||
* `log10()` | ||
* `log2()` | ||
* `log1p()` | ||
* `expm1()` | ||
* `cosh()` | ||
* `sign()` | ||
* `sinh()` | ||
* `tanh()` | ||
* `acosh()` | ||
* `asinh()` | ||
* `atanh()` | ||
* `hypot()` | ||
* `trunc()` | ||
* `imul()` | ||
* `fround()` | ||
Math functions accuracy is 1e-11. | ||
## Subclassing | ||
The `Map`, `Set`, and `Promise` implementations are subclassable. | ||
You should use the following pattern to create a subclass in ES5 which | ||
will continue to work in ES6: | ||
```javascript | ||
function MyPromise(exec) { | ||
Promise.call(this, exec); | ||
// ... | ||
} | ||
Object.setPrototypeOf(MyPromise, Promise); | ||
MyPromise.prototype = Object.create(Promise.prototype, { | ||
constructor: { value: MyPromise } | ||
}); | ||
``` | ||
## String.prototype.normalize | ||
Including a proper shim for `String.prototype.normalize` would | ||
increase the size of this library by a factor of more than 4. | ||
So instead we recommend that you install the | ||
[`unorm`](https://github.com/walling/unorm) | ||
package alongside `es6-shim` if you need `String.prototype.normalize`. | ||
See https://github.com/paulmillr/es6-shim/issues/134 for more | ||
discussion. | ||
## WeakMap shim | ||
@@ -103,3 +141,2 @@ It is not possible to implement WeakMap in pure javascript. | ||
Number.isFinite('asd') // false. Global isFinite() will give true. | ||
Number.toInteger(2.4) // 2. converts values to IEEE754 double precision integers | ||
// Tests if value is a number, finite, | ||
@@ -133,4 +170,20 @@ // >= -9007199254740992 && <= 9007199254740992 and floor(value) === value | ||
set.delete(5) | ||
// Promises, see | ||
// http://www.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript | ||
// https://github.com/petkaantonov/bluebird/#what-are-promises-and-why-should-i-use-them | ||
Promise.resolve(5).then(function(value) { | ||
if ( ... ) throw new Error("whoops!"); | ||
// do some stuff | ||
return anotherPromise(); | ||
}).catch(function(e) { | ||
// any errors thrown asynchronously end up here | ||
}); | ||
``` | ||
Note that the ES6 `Promise` specification includes very few methods. | ||
For a more useful set of utility methods | ||
(`map`/`reduce`/`bind`/`guard`/etc), you might want to look into the | ||
[`prfun`](https://github.com/cscott/prfun) package. | ||
Other stuff: | ||
@@ -144,5 +197,7 @@ | ||
Current maintainers are: [Paul Miller](http://paulmillr.com), [Jordan Harband](https://github.com/ljharb) and [C. Scott Ananian](http://cscott.net). | ||
The MIT License (MIT) | ||
Copyright (c) 2013 Paul Miller (http://paulmillr.com) | ||
Copyright (c) 2013-2014 Paul Miller (http://paulmillr.com) | ||
@@ -149,0 +204,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
76816
1713
221
5