2014-10-28 14:36:39 -04:00
|
|
|
|
/*!
|
|
|
|
|
* https://github.com/paulmillr/es6-shim
|
|
|
|
|
* @license es6-shim Copyright 2013-2014 by Paul Miller (http://paulmillr.com)
|
|
|
|
|
* and contributors, MIT License
|
2015-01-28 15:33:44 -05:00
|
|
|
|
* es6-shim: v0.23.0
|
|
|
|
|
* see https://github.com/paulmillr/es6-shim/blob/0.22.2/LICENSE
|
2014-10-28 14:36:39 -04:00
|
|
|
|
* Details and documentation:
|
|
|
|
|
* https://github.com/paulmillr/es6-shim/
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// UMD (Universal Module Definition)
|
|
|
|
|
// see https://github.com/umdjs/umd/blob/master/returnExports.js
|
|
|
|
|
(function (root, factory) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
/*global define, module, exports */
|
2014-10-28 14:36:39 -04:00
|
|
|
|
if (typeof define === 'function' && define.amd) {
|
|
|
|
|
// AMD. Register as an anonymous module.
|
|
|
|
|
define(factory);
|
|
|
|
|
} else if (typeof exports === 'object') {
|
|
|
|
|
// Node. Does not work with strict CommonJS, but
|
|
|
|
|
// only CommonJS-like enviroments that support module.exports,
|
|
|
|
|
// like Node.
|
|
|
|
|
module.exports = factory();
|
|
|
|
|
} else {
|
|
|
|
|
// Browser globals (root is window)
|
|
|
|
|
root.returnExports = factory();
|
|
|
|
|
}
|
2014-11-25 14:23:08 -05:00
|
|
|
|
}(this, function () {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
var isCallableWithoutNew = function (func) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
try {
|
|
|
|
|
func();
|
|
|
|
|
} catch (e) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2014-10-28 14:36:39 -04:00
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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 () {
|
|
|
|
|
try {
|
|
|
|
|
Object.defineProperty({}, 'x', {});
|
|
|
|
|
return true;
|
|
|
|
|
} catch (e) { /* this is IE 8. */
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var startsWithRejectsRegex = function () {
|
|
|
|
|
var rejectsRegex = false;
|
|
|
|
|
if (String.prototype.startsWith) {
|
|
|
|
|
try {
|
|
|
|
|
'/a/'.startsWith(/a/);
|
|
|
|
|
} catch (e) { /* this is spec compliant */
|
|
|
|
|
rejectsRegex = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return rejectsRegex;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*jshint evil: true */
|
|
|
|
|
var getGlobal = new Function('return this;');
|
|
|
|
|
/*jshint evil: false */
|
|
|
|
|
|
|
|
|
|
var globals = getGlobal();
|
|
|
|
|
var global_isFinite = globals.isFinite;
|
|
|
|
|
var supportsDescriptors = !!Object.defineProperty && arePropertyDescriptorsSupported();
|
|
|
|
|
var startsWithIsCompliant = startsWithRejectsRegex();
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var _indexOf = Function.call.bind(String.prototype.indexOf);
|
|
|
|
|
var _toString = Function.call.bind(Object.prototype.toString);
|
|
|
|
|
var _hasOwnProperty = Function.call.bind(Object.prototype.hasOwnProperty);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
var ArrayIterator; // make our implementation private
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var noop = function () {};
|
|
|
|
|
|
|
|
|
|
var Symbol = globals.Symbol || {};
|
|
|
|
|
var symbolSpecies = Symbol.species || '@@species';
|
|
|
|
|
var Type = {
|
|
|
|
|
string: function (x) { return _toString(x) === '[object String]'; },
|
|
|
|
|
regex: function (x) { return _toString(x) === '[object RegExp]'; },
|
|
|
|
|
symbol: function (x) {
|
|
|
|
|
/*jshint notypeof: true */
|
|
|
|
|
return typeof globals.Symbol === 'function' && typeof x === 'symbol';
|
|
|
|
|
/*jshint notypeof: false */
|
|
|
|
|
}
|
|
|
|
|
};
|
2014-10-28 14:36:39 -04:00
|
|
|
|
|
|
|
|
|
var defineProperty = function (object, name, value, force) {
|
|
|
|
|
if (!force && name in object) { return; }
|
|
|
|
|
if (supportsDescriptors) {
|
|
|
|
|
Object.defineProperty(object, name, {
|
|
|
|
|
configurable: true,
|
|
|
|
|
enumerable: false,
|
|
|
|
|
writable: true,
|
|
|
|
|
value: value
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
object[name] = value;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var Value = {
|
|
|
|
|
getter: function (object, name, getter) {
|
|
|
|
|
if (!supportsDescriptors) {
|
|
|
|
|
throw new TypeError('getters require true ES5 support');
|
|
|
|
|
}
|
|
|
|
|
Object.defineProperty(object, name, {
|
|
|
|
|
configurable: true,
|
|
|
|
|
enumerable: false,
|
|
|
|
|
get: getter
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
proxy: function (originalObject, key, targetObject) {
|
|
|
|
|
if (!supportsDescriptors) {
|
|
|
|
|
throw new TypeError('getters require true ES5 support');
|
|
|
|
|
}
|
|
|
|
|
var originalDescriptor = Object.getOwnPropertyDescriptor(originalObject, key);
|
|
|
|
|
Object.defineProperty(targetObject, key, {
|
|
|
|
|
configurable: originalDescriptor.configurable,
|
|
|
|
|
enumerable: originalDescriptor.enumerable,
|
|
|
|
|
get: function getKey() { return originalObject[key]; },
|
|
|
|
|
set: function setKey(value) { originalObject[key] = value; }
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
redefine: function (object, property, newValue) {
|
|
|
|
|
if (supportsDescriptors) {
|
|
|
|
|
var descriptor = Object.getOwnPropertyDescriptor(object, property);
|
|
|
|
|
descriptor.value = newValue;
|
|
|
|
|
Object.defineProperty(object, property, descriptor);
|
|
|
|
|
} else {
|
|
|
|
|
object[property] = newValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2014-10-28 14:36:39 -04:00
|
|
|
|
// Define configurable, writable and non-enumerable props
|
|
|
|
|
// if they don’t exist.
|
|
|
|
|
var defineProperties = function (object, map) {
|
|
|
|
|
Object.keys(map).forEach(function (name) {
|
|
|
|
|
var method = map[name];
|
|
|
|
|
defineProperty(object, name, method, false);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Simple shim for Object.create on ES3 browsers
|
|
|
|
|
// (unlike real shim, no attempt to support `prototype === null`)
|
|
|
|
|
var create = Object.create || function (prototype, properties) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
function Prototype() {}
|
|
|
|
|
Prototype.prototype = prototype;
|
|
|
|
|
var object = new Prototype();
|
2014-10-28 14:36:39 -04:00
|
|
|
|
if (typeof properties !== 'undefined') {
|
|
|
|
|
defineProperties(object, properties);
|
|
|
|
|
}
|
|
|
|
|
return object;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// This is a private name in the es6 spec, equal to '[Symbol.iterator]'
|
|
|
|
|
// we're going to use an arbitrary _-prefixed name to make our shims
|
|
|
|
|
// work properly with each other, even though we don't have full Iterator
|
|
|
|
|
// support. That is, `Array.from(map.keys())` will work, but we don't
|
|
|
|
|
// pretend to export a "real" Iterator interface.
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var $iterator$ = Type.symbol(Symbol.iterator) ? Symbol.iterator : '_es6-shim iterator_';
|
2014-10-28 14:36:39 -04:00
|
|
|
|
// Firefox ships a partial implementation using the name @@iterator.
|
|
|
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=907077#c14
|
|
|
|
|
// So use that name if we detect it.
|
|
|
|
|
if (globals.Set && typeof new globals.Set()['@@iterator'] === 'function') {
|
|
|
|
|
$iterator$ = '@@iterator';
|
|
|
|
|
}
|
|
|
|
|
var addIterator = function (prototype, impl) {
|
|
|
|
|
if (!impl) { impl = function iterator() { return this; }; }
|
|
|
|
|
var o = {};
|
|
|
|
|
o[$iterator$] = impl;
|
|
|
|
|
defineProperties(prototype, o);
|
2015-01-28 15:33:44 -05:00
|
|
|
|
if (!prototype[$iterator$] && Type.symbol($iterator$)) {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
// implementations are buggy when $iterator$ is a Symbol
|
|
|
|
|
prototype[$iterator$] = impl;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 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) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var str = _toString(value);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
var result = str === '[object Arguments]';
|
|
|
|
|
if (!result) {
|
|
|
|
|
result = str !== '[object Array]' &&
|
|
|
|
|
value !== null &&
|
|
|
|
|
typeof value === 'object' &&
|
|
|
|
|
typeof value.length === 'number' &&
|
|
|
|
|
value.length >= 0 &&
|
2015-01-28 15:33:44 -05:00
|
|
|
|
_toString(value.callee) === '[object Function]';
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var ES = {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
RequireObjectCoercible: function (x, optMessage) {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
/* jshint eqnull:true */
|
|
|
|
|
if (x == null) {
|
|
|
|
|
throw new TypeError(optMessage || 'Cannot call method on ' + 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) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
ES.RequireObjectCoercible(o, optMessage);
|
|
|
|
|
return Object(o);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
IsCallable: function (x) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
// some versions of IE say that typeof /abc/ === 'function'
|
|
|
|
|
return typeof x === 'function' && _toString(x) === '[object Function]';
|
2014-10-28 14:36:39 -04:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
ToInt32: function (x) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
return ES.ToNumber(x) >> 0;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
ToUint32: function (x) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
return ES.ToNumber(x) >>> 0;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
ToNumber: function (value) {
|
|
|
|
|
if (_toString(value) === '[object Symbol]') {
|
|
|
|
|
throw new TypeError('Cannot convert a Symbol value to a number');
|
|
|
|
|
}
|
|
|
|
|
return +value;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
ToInteger: function (value) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var number = ES.ToNumber(value);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
if (Number.isNaN(number)) { return 0; }
|
|
|
|
|
if (number === 0 || !Number.isFinite(number)) { return number; }
|
|
|
|
|
return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
if (a === b) {
|
|
|
|
|
// 0 === -0, but they are not identical.
|
|
|
|
|
if (a === 0) { return 1 / a === 1 / b; }
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return Number.isNaN(a) && Number.isNaN(b);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
SameValueZero: function (a, b) {
|
|
|
|
|
// same as SameValue except for SameValueZero(+0, -0) == true
|
|
|
|
|
return (a === b) || (Number.isNaN(a) && Number.isNaN(b));
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
IsIterable: function (o) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
return ES.TypeIsObject(o) && (typeof o[$iterator$] !== 'undefined' || isArguments(o));
|
2014-10-28 14:36:39 -04:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
GetIterator: function (o) {
|
|
|
|
|
if (isArguments(o)) {
|
|
|
|
|
// special case support for `arguments`
|
|
|
|
|
return new ArrayIterator(o, 'value');
|
|
|
|
|
}
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var itFn = o[$iterator$];
|
|
|
|
|
if (!ES.IsCallable(itFn)) {
|
|
|
|
|
throw new TypeError('value is not an iterable');
|
|
|
|
|
}
|
|
|
|
|
var it = itFn.call(o);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
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;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
if (ES.IsCallable(C[symbolSpecies])) {
|
|
|
|
|
obj = C[symbolSpecies]();
|
2014-10-28 14:36:39 -04:00
|
|
|
|
} else {
|
|
|
|
|
// OrdinaryCreateFromConstructor
|
|
|
|
|
obj = 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;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2015-01-28 15:33:44 -05:00
|
|
|
|
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.@@species to allocation/initialize the new object.
|
|
|
|
|
// In es5 we just get the plain object. So if we detect an
|
|
|
|
|
// uninitialized object, invoke o.constructor.@@species
|
|
|
|
|
if (!o._es6construct) {
|
|
|
|
|
if (o.constructor && ES.IsCallable(o.constructor[symbolSpecies])) {
|
|
|
|
|
o = o.constructor[symbolSpecies](o);
|
|
|
|
|
}
|
|
|
|
|
defineProperties(o, { _es6construct: true });
|
|
|
|
|
}
|
|
|
|
|
return o;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2014-10-28 14:36:39 -04:00
|
|
|
|
var numberConversion = (function () {
|
|
|
|
|
// from https://github.com/inexorabletash/polyfill/blob/master/typedarray.js#L176-L266
|
|
|
|
|
// with permission and license, per https://twitter.com/inexorabletash/status/372206509540659200
|
|
|
|
|
|
|
|
|
|
function roundToEven(n) {
|
|
|
|
|
var w = Math.floor(n), f = n - w;
|
|
|
|
|
if (f < 0.5) {
|
|
|
|
|
return w;
|
|
|
|
|
}
|
|
|
|
|
if (f > 0.5) {
|
|
|
|
|
return w + 1;
|
|
|
|
|
}
|
|
|
|
|
return w % 2 ? w + 1 : w;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function packIEEE754(v, ebits, fbits) {
|
|
|
|
|
var bias = (1 << (ebits - 1)) - 1,
|
2015-01-28 15:33:44 -05:00
|
|
|
|
s, e, f,
|
2014-10-28 14:36:39 -04:00
|
|
|
|
i, bits, str, bytes;
|
|
|
|
|
|
|
|
|
|
// Compute sign, exponent, fraction
|
|
|
|
|
if (v !== v) {
|
|
|
|
|
// NaN
|
|
|
|
|
// http://dev.w3.org/2006/webapi/WebIDL/#es-type-mapping
|
|
|
|
|
e = (1 << ebits) - 1;
|
|
|
|
|
f = Math.pow(2, fbits - 1);
|
|
|
|
|
s = 0;
|
|
|
|
|
} else if (v === Infinity || v === -Infinity) {
|
|
|
|
|
e = (1 << ebits) - 1;
|
|
|
|
|
f = 0;
|
|
|
|
|
s = (v < 0) ? 1 : 0;
|
|
|
|
|
} else if (v === 0) {
|
|
|
|
|
e = 0;
|
|
|
|
|
f = 0;
|
|
|
|
|
s = (1 / v === -Infinity) ? 1 : 0;
|
|
|
|
|
} else {
|
|
|
|
|
s = v < 0;
|
|
|
|
|
v = Math.abs(v);
|
|
|
|
|
|
|
|
|
|
if (v >= Math.pow(2, 1 - bias)) {
|
|
|
|
|
e = Math.min(Math.floor(Math.log(v) / Math.LN2), 1023);
|
|
|
|
|
f = roundToEven(v / Math.pow(2, e) * Math.pow(2, fbits));
|
|
|
|
|
if (f / Math.pow(2, fbits) >= 2) {
|
|
|
|
|
e = e + 1;
|
|
|
|
|
f = 1;
|
|
|
|
|
}
|
|
|
|
|
if (e > bias) {
|
|
|
|
|
// Overflow
|
|
|
|
|
e = (1 << ebits) - 1;
|
|
|
|
|
f = 0;
|
|
|
|
|
} else {
|
|
|
|
|
// Normal
|
|
|
|
|
e = e + bias;
|
|
|
|
|
f = f - Math.pow(2, fbits);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Subnormal
|
|
|
|
|
e = 0;
|
|
|
|
|
f = roundToEven(v / Math.pow(2, 1 - bias - fbits));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Pack sign, exponent, fraction
|
|
|
|
|
bits = [];
|
|
|
|
|
for (i = fbits; i; i -= 1) {
|
|
|
|
|
bits.push(f % 2 ? 1 : 0);
|
|
|
|
|
f = Math.floor(f / 2);
|
|
|
|
|
}
|
|
|
|
|
for (i = ebits; i; i -= 1) {
|
|
|
|
|
bits.push(e % 2 ? 1 : 0);
|
|
|
|
|
e = Math.floor(e / 2);
|
|
|
|
|
}
|
|
|
|
|
bits.push(s ? 1 : 0);
|
|
|
|
|
bits.reverse();
|
|
|
|
|
str = bits.join('');
|
|
|
|
|
|
|
|
|
|
// Bits to bytes
|
|
|
|
|
bytes = [];
|
|
|
|
|
while (str.length) {
|
|
|
|
|
bytes.push(parseInt(str.slice(0, 8), 2));
|
|
|
|
|
str = str.slice(8);
|
|
|
|
|
}
|
|
|
|
|
return bytes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function unpackIEEE754(bytes, ebits, fbits) {
|
|
|
|
|
// Bytes to bits
|
|
|
|
|
var bits = [], i, j, b, str,
|
|
|
|
|
bias, s, e, f;
|
|
|
|
|
|
|
|
|
|
for (i = bytes.length; i; i -= 1) {
|
|
|
|
|
b = bytes[i - 1];
|
|
|
|
|
for (j = 8; j; j -= 1) {
|
|
|
|
|
bits.push(b % 2 ? 1 : 0);
|
|
|
|
|
b = b >> 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
bits.reverse();
|
|
|
|
|
str = bits.join('');
|
|
|
|
|
|
|
|
|
|
// Unpack sign, exponent, fraction
|
|
|
|
|
bias = (1 << (ebits - 1)) - 1;
|
|
|
|
|
s = parseInt(str.slice(0, 1), 2) ? -1 : 1;
|
|
|
|
|
e = parseInt(str.slice(1, 1 + ebits), 2);
|
|
|
|
|
f = parseInt(str.slice(1 + ebits), 2);
|
|
|
|
|
|
|
|
|
|
// Produce number
|
|
|
|
|
if (e === (1 << ebits) - 1) {
|
|
|
|
|
return f !== 0 ? NaN : s * Infinity;
|
|
|
|
|
} else if (e > 0) {
|
|
|
|
|
// Normalized
|
|
|
|
|
return s * Math.pow(2, e - bias) * (1 + f / Math.pow(2, fbits));
|
|
|
|
|
} else if (f !== 0) {
|
|
|
|
|
// Denormalized
|
|
|
|
|
return s * Math.pow(2, -(bias - 1)) * (f / Math.pow(2, fbits));
|
|
|
|
|
} else {
|
|
|
|
|
return s < 0 ? -0 : 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function unpackFloat64(b) { return unpackIEEE754(b, 11, 52); }
|
|
|
|
|
function packFloat64(v) { return packIEEE754(v, 11, 52); }
|
|
|
|
|
function unpackFloat32(b) { return unpackIEEE754(b, 8, 23); }
|
|
|
|
|
function packFloat32(v) { return packIEEE754(v, 8, 23); }
|
|
|
|
|
|
|
|
|
|
var conversions = {
|
|
|
|
|
toFloat32: function (num) { return unpackFloat32(packFloat32(num)); }
|
|
|
|
|
};
|
|
|
|
|
if (typeof Float32Array !== 'undefined') {
|
|
|
|
|
var float32array = new Float32Array(1);
|
|
|
|
|
conversions.toFloat32 = function (num) {
|
|
|
|
|
float32array[0] = num;
|
|
|
|
|
return float32array[0];
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return conversions;
|
|
|
|
|
}());
|
|
|
|
|
|
|
|
|
|
defineProperties(String, {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
fromCodePoint: function fromCodePoint(codePoints) {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
var result = [];
|
|
|
|
|
var next;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
for (var i = 0, length = arguments.length; i < length; i++) {
|
|
|
|
|
next = Number(arguments[i]);
|
|
|
|
|
if (!ES.SameValue(next, ES.ToInteger(next)) || next < 0 || next > 0x10FFFF) {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
throw new RangeError('Invalid code point ' + next);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (next < 0x10000) {
|
|
|
|
|
result.push(String.fromCharCode(next));
|
|
|
|
|
} else {
|
|
|
|
|
next -= 0x10000;
|
|
|
|
|
result.push(String.fromCharCode((next >> 10) + 0xD800));
|
|
|
|
|
result.push(String.fromCharCode((next % 0x400) + 0xDC00));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result.join('');
|
|
|
|
|
},
|
|
|
|
|
|
2015-01-28 15:33:44 -05:00
|
|
|
|
raw: function raw(callSite) {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
var cooked = ES.ToObject(callSite, 'bad callSite');
|
|
|
|
|
var rawValue = cooked.raw;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var rawString = ES.ToObject(rawValue, 'bad raw value');
|
|
|
|
|
var len = rawString.length;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
var literalsegments = ES.ToLength(len);
|
2015-01-28 15:33:44 -05:00
|
|
|
|
if (literalsegments <= 0) {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var stringElements = [];
|
|
|
|
|
var nextIndex = 0;
|
|
|
|
|
var nextKey, next, nextSeg, nextSub;
|
|
|
|
|
while (nextIndex < literalsegments) {
|
|
|
|
|
nextKey = String(nextIndex);
|
2015-01-28 15:33:44 -05:00
|
|
|
|
next = rawString[nextKey];
|
2014-10-28 14:36:39 -04:00
|
|
|
|
nextSeg = String(next);
|
|
|
|
|
stringElements.push(nextSeg);
|
|
|
|
|
if (nextIndex + 1 >= literalsegments) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2015-01-28 15:33:44 -05:00
|
|
|
|
next = nextIndex + 1 < arguments.length ? arguments[nextIndex + 1] : '';
|
2014-10-28 14:36:39 -04:00
|
|
|
|
nextSub = String(next);
|
|
|
|
|
stringElements.push(nextSub);
|
|
|
|
|
nextIndex++;
|
|
|
|
|
}
|
|
|
|
|
return stringElements.join('');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Firefox 31 reports this function's length as 0
|
|
|
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1062484
|
|
|
|
|
if (String.fromCodePoint.length !== 1) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var originalFromCodePoint = Function.apply.bind(String.fromCodePoint);
|
|
|
|
|
defineProperty(String, 'fromCodePoint', function fromCodePoint(codePoints) { return originalFromCodePoint(this, arguments); }, true);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var StringShims = {
|
|
|
|
|
// Fast repeat, uses the `Exponentiation by squaring` algorithm.
|
|
|
|
|
// Perf: http://jsperf.com/string-repeat2/2
|
|
|
|
|
repeat: (function () {
|
|
|
|
|
var repeat = function (s, times) {
|
|
|
|
|
if (times < 1) { return ''; }
|
|
|
|
|
if (times % 2) { return repeat(s, times - 1) + s; }
|
|
|
|
|
var half = repeat(s, times / 2);
|
|
|
|
|
return half + half;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return function (times) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
ES.RequireObjectCoercible(this);
|
|
|
|
|
var thisStr = String(this);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
times = ES.ToInteger(times);
|
|
|
|
|
if (times < 0 || times === Infinity) {
|
|
|
|
|
throw new RangeError('Invalid String#repeat value');
|
|
|
|
|
}
|
|
|
|
|
return repeat(thisStr, times);
|
|
|
|
|
};
|
2015-01-28 15:33:44 -05:00
|
|
|
|
}()),
|
2014-10-28 14:36:39 -04:00
|
|
|
|
|
|
|
|
|
startsWith: function (searchStr) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
ES.RequireObjectCoercible(this);
|
|
|
|
|
var thisStr = String(this);
|
|
|
|
|
if (Type.regex(searchStr)) {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
throw new TypeError('Cannot call method "startsWith" with a regex');
|
|
|
|
|
}
|
|
|
|
|
searchStr = String(searchStr);
|
2014-11-25 14:23:08 -05:00
|
|
|
|
var startArg = arguments.length > 1 ? arguments[1] : void 0;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
var start = Math.max(ES.ToInteger(startArg), 0);
|
|
|
|
|
return thisStr.slice(start, start + searchStr.length) === searchStr;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
endsWith: function (searchStr) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
ES.RequireObjectCoercible(this);
|
|
|
|
|
var thisStr = String(this);
|
|
|
|
|
if (Type.regex(searchStr)) {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
throw new TypeError('Cannot call method "endsWith" with a regex');
|
|
|
|
|
}
|
|
|
|
|
searchStr = String(searchStr);
|
|
|
|
|
var thisLen = thisStr.length;
|
2014-11-25 14:23:08 -05:00
|
|
|
|
var posArg = arguments.length > 1 ? arguments[1] : void 0;
|
|
|
|
|
var pos = typeof posArg === 'undefined' ? thisLen : ES.ToInteger(posArg);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
var end = Math.min(Math.max(pos, 0), thisLen);
|
|
|
|
|
return thisStr.slice(end - searchStr.length, end) === searchStr;
|
|
|
|
|
},
|
|
|
|
|
|
2015-01-28 15:33:44 -05:00
|
|
|
|
includes: function includes(searchString) {
|
2014-11-25 14:23:08 -05:00
|
|
|
|
var position = arguments.length > 1 ? arguments[1] : void 0;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
// Somehow this trick makes method 100% compat with the spec.
|
2015-01-28 15:33:44 -05:00
|
|
|
|
return _indexOf(this, searchString, position) !== -1;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
codePointAt: function (pos) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
ES.RequireObjectCoercible(this);
|
|
|
|
|
var thisStr = String(this);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
var position = ES.ToInteger(pos);
|
|
|
|
|
var length = thisStr.length;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
if (position >= 0 && position < length) {
|
|
|
|
|
var first = thisStr.charCodeAt(position);
|
|
|
|
|
var isEnd = (position + 1 === length);
|
|
|
|
|
if (first < 0xD800 || first > 0xDBFF || isEnd) { return first; }
|
|
|
|
|
var second = thisStr.charCodeAt(position + 1);
|
|
|
|
|
if (second < 0xDC00 || second > 0xDFFF) { return first; }
|
|
|
|
|
return ((first - 0xD800) * 1024) + (second - 0xDC00) + 0x10000;
|
|
|
|
|
}
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
defineProperties(String.prototype, StringShims);
|
|
|
|
|
|
|
|
|
|
var hasStringTrimBug = '\u0085'.trim().length !== 1;
|
|
|
|
|
if (hasStringTrimBug) {
|
|
|
|
|
delete String.prototype.trim;
|
|
|
|
|
// whitespace from: http://es5.github.io/#x15.5.4.20
|
|
|
|
|
// implementation from https://github.com/es-shims/es5-shim/blob/v3.4.0/es5-shim.js#L1304-L1324
|
|
|
|
|
var ws = [
|
|
|
|
|
'\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003',
|
|
|
|
|
'\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028',
|
|
|
|
|
'\u2029\uFEFF'
|
|
|
|
|
].join('');
|
|
|
|
|
var trimRegexp = new RegExp('(^[' + ws + ']+)|([' + ws + ']+$)', 'g');
|
|
|
|
|
defineProperties(String.prototype, {
|
|
|
|
|
trim: function () {
|
2014-11-25 14:23:08 -05:00
|
|
|
|
if (typeof this === 'undefined' || this === null) {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
throw new TypeError("can't convert " + this + ' to object');
|
|
|
|
|
}
|
|
|
|
|
return String(this).replace(trimRegexp, '');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// see https://people.mozilla.org/~jorendorff/es6-draft.html#sec-string.prototype-@@iterator
|
|
|
|
|
var StringIterator = function (s) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
ES.RequireObjectCoercible(s);
|
|
|
|
|
this._s = String(s);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
this._i = 0;
|
|
|
|
|
};
|
|
|
|
|
StringIterator.prototype.next = function () {
|
|
|
|
|
var s = this._s, i = this._i;
|
2014-11-25 14:23:08 -05:00
|
|
|
|
if (typeof s === 'undefined' || i >= s.length) {
|
|
|
|
|
this._s = void 0;
|
|
|
|
|
return { value: void 0, done: true };
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
|
|
|
|
var first = s.charCodeAt(i), second, len;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
if (first < 0xD800 || first > 0xDBFF || (i + 1) === s.length) {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
len = 1;
|
|
|
|
|
} else {
|
|
|
|
|
second = s.charCodeAt(i + 1);
|
|
|
|
|
len = (second < 0xDC00 || second > 0xDFFF) ? 1 : 2;
|
|
|
|
|
}
|
|
|
|
|
this._i = i + len;
|
|
|
|
|
return { value: s.substr(i, len), done: false };
|
|
|
|
|
};
|
|
|
|
|
addIterator(StringIterator.prototype);
|
|
|
|
|
addIterator(String.prototype, function () {
|
|
|
|
|
return new StringIterator(this);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!startsWithIsCompliant) {
|
|
|
|
|
// Firefox has a noncompliant startsWith implementation
|
2015-01-28 15:33:44 -05:00
|
|
|
|
defineProperties(String.prototype, {
|
|
|
|
|
startsWith: StringShims.startsWith,
|
|
|
|
|
endsWith: StringShims.endsWith
|
|
|
|
|
});
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var ArrayShims = {
|
|
|
|
|
from: function (iterable) {
|
2014-11-25 14:23:08 -05:00
|
|
|
|
var mapFn = arguments.length > 1 ? arguments[1] : void 0;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
|
|
|
|
|
var list = ES.ToObject(iterable, 'bad iterable');
|
2014-11-25 14:23:08 -05:00
|
|
|
|
if (typeof mapFn !== 'undefined' && !ES.IsCallable(mapFn)) {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
throw new TypeError('Array.from: when provided, the second argument must be a function');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var hasThisArg = arguments.length > 2;
|
2014-11-25 14:23:08 -05:00
|
|
|
|
var thisArg = hasThisArg ? arguments[2] : void 0;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
var result, i, value;
|
|
|
|
|
if (usingIterator) {
|
|
|
|
|
i = 0;
|
|
|
|
|
result = ES.IsCallable(this) ? Object(new this()) : [];
|
|
|
|
|
var it = usingIterator ? ES.GetIterator(list) : null;
|
|
|
|
|
var iterationValue;
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
iterationValue = ES.IteratorNext(it);
|
|
|
|
|
if (!iterationValue.done) {
|
|
|
|
|
value = iterationValue.value;
|
|
|
|
|
if (mapFn) {
|
|
|
|
|
result[i] = hasThisArg ? mapFn.call(thisArg, value, i) : mapFn(value, i);
|
|
|
|
|
} else {
|
|
|
|
|
result[i] = value;
|
|
|
|
|
}
|
|
|
|
|
i += 1;
|
|
|
|
|
}
|
|
|
|
|
} while (!iterationValue.done);
|
|
|
|
|
length = i;
|
|
|
|
|
} else {
|
|
|
|
|
length = ES.ToLength(list.length);
|
|
|
|
|
result = ES.IsCallable(this) ? Object(new this(length)) : new Array(length);
|
|
|
|
|
for (i = 0; i < length; ++i) {
|
|
|
|
|
value = list[i];
|
|
|
|
|
if (mapFn) {
|
|
|
|
|
result[i] = hasThisArg ? mapFn.call(thisArg, value, i) : mapFn(value, i);
|
|
|
|
|
} else {
|
|
|
|
|
result[i] = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result.length = length;
|
|
|
|
|
return result;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
of: function () {
|
|
|
|
|
return Array.from(arguments);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
defineProperties(Array, ArrayShims);
|
|
|
|
|
|
|
|
|
|
var arrayFromSwallowsNegativeLengths = function () {
|
|
|
|
|
try {
|
|
|
|
|
return Array.from({ length: -1 }).length === 0;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
// Fixes a Firefox bug in v32
|
|
|
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1063993
|
|
|
|
|
if (!arrayFromSwallowsNegativeLengths()) {
|
|
|
|
|
defineProperty(Array, 'from', ArrayShims.from, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Our ArrayIterator is private; see
|
|
|
|
|
// https://github.com/paulmillr/es6-shim/issues/252
|
|
|
|
|
ArrayIterator = function (array, kind) {
|
|
|
|
|
this.i = 0;
|
|
|
|
|
this.array = array;
|
|
|
|
|
this.kind = kind;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
defineProperties(ArrayIterator.prototype, {
|
|
|
|
|
next: function () {
|
|
|
|
|
var i = this.i, array = this.array;
|
|
|
|
|
if (!(this instanceof ArrayIterator)) {
|
|
|
|
|
throw new TypeError('Not an ArrayIterator');
|
|
|
|
|
}
|
2014-11-25 14:23:08 -05:00
|
|
|
|
if (typeof array !== 'undefined') {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
var len = ES.ToLength(array.length);
|
|
|
|
|
for (; i < len; i++) {
|
|
|
|
|
var kind = this.kind;
|
|
|
|
|
var retval;
|
|
|
|
|
if (kind === 'key') {
|
|
|
|
|
retval = i;
|
|
|
|
|
} else if (kind === 'value') {
|
|
|
|
|
retval = array[i];
|
|
|
|
|
} else if (kind === 'entry') {
|
|
|
|
|
retval = [i, array[i]];
|
|
|
|
|
}
|
|
|
|
|
this.i = i + 1;
|
|
|
|
|
return { value: retval, done: false };
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-11-25 14:23:08 -05:00
|
|
|
|
this.array = void 0;
|
|
|
|
|
return { value: void 0, done: true };
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
addIterator(ArrayIterator.prototype);
|
|
|
|
|
|
|
|
|
|
var ArrayPrototypeShims = {
|
|
|
|
|
copyWithin: function (target, start) {
|
|
|
|
|
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);
|
2014-11-25 14:23:08 -05:00
|
|
|
|
end = typeof end === 'undefined' ? len : ES.ToInteger(end);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
var fin = end < 0 ? Math.max(len + end, 0) : Math.min(end, len);
|
|
|
|
|
var count = Math.min(fin - from, len - to);
|
|
|
|
|
var direction = 1;
|
|
|
|
|
if (from < to && to < (from + count)) {
|
|
|
|
|
direction = -1;
|
|
|
|
|
from += count - 1;
|
|
|
|
|
to += count - 1;
|
|
|
|
|
}
|
|
|
|
|
while (count > 0) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
if (_hasOwnProperty(o, from)) {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
o[to] = o[from];
|
|
|
|
|
} else {
|
|
|
|
|
delete o[from];
|
|
|
|
|
}
|
|
|
|
|
from += direction;
|
|
|
|
|
to += direction;
|
|
|
|
|
count -= 1;
|
|
|
|
|
}
|
|
|
|
|
return o;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
fill: function (value) {
|
2014-11-25 14:23:08 -05:00
|
|
|
|
var start = arguments.length > 1 ? arguments[1] : void 0;
|
|
|
|
|
var end = arguments.length > 2 ? arguments[2] : void 0;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
var O = ES.ToObject(this);
|
|
|
|
|
var len = ES.ToLength(O.length);
|
2014-11-25 14:23:08 -05:00
|
|
|
|
start = ES.ToInteger(typeof start === 'undefined' ? 0 : start);
|
|
|
|
|
end = ES.ToInteger(typeof end === 'undefined' ? len : end);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
|
|
|
|
|
var relativeStart = start < 0 ? Math.max(len + start, 0) : Math.min(start, len);
|
|
|
|
|
var relativeEnd = end < 0 ? len + end : end;
|
|
|
|
|
|
|
|
|
|
for (var i = relativeStart; i < len && i < relativeEnd; ++i) {
|
|
|
|
|
O[i] = value;
|
|
|
|
|
}
|
|
|
|
|
return O;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
find: function find(predicate) {
|
|
|
|
|
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');
|
|
|
|
|
}
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var thisArg = arguments.length > 1 ? arguments[1] : null;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
for (var i = 0, value; i < length; i++) {
|
|
|
|
|
value = list[i];
|
2015-01-28 15:33:44 -05:00
|
|
|
|
if (thisArg) {
|
|
|
|
|
if (predicate.call(thisArg, value, i, list)) { return value; }
|
|
|
|
|
} else if (predicate(value, i, list)) {
|
|
|
|
|
return value;
|
|
|
|
|
}
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
findIndex: function findIndex(predicate) {
|
|
|
|
|
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');
|
|
|
|
|
}
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var thisArg = arguments.length > 1 ? arguments[1] : null;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
for (var i = 0; i < length; i++) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
if (thisArg) {
|
|
|
|
|
if (predicate.call(thisArg, list[i], i, list)) { return i; }
|
|
|
|
|
} else if (predicate(list[i], i, list)) {
|
|
|
|
|
return i;
|
|
|
|
|
}
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
keys: function () {
|
|
|
|
|
return new ArrayIterator(this, 'key');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
values: function () {
|
|
|
|
|
return new ArrayIterator(this, 'value');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
entries: function () {
|
|
|
|
|
return new ArrayIterator(this, 'entry');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
// Safari 7.1 defines Array#keys and Array#entries natively,
|
|
|
|
|
// but the resulting ArrayIterator objects don't have a "next" method.
|
|
|
|
|
if (Array.prototype.keys && !ES.IsCallable([1].keys().next)) {
|
|
|
|
|
delete Array.prototype.keys;
|
|
|
|
|
}
|
|
|
|
|
if (Array.prototype.entries && !ES.IsCallable([1].entries().next)) {
|
|
|
|
|
delete Array.prototype.entries;
|
|
|
|
|
}
|
2015-01-28 15:33:44 -05:00
|
|
|
|
|
|
|
|
|
// Chrome 38 defines Array#keys and Array#entries, and Array#@@iterator, but not Array#values
|
|
|
|
|
if (Array.prototype.keys && Array.prototype.entries && !Array.prototype.values && Array.prototype[$iterator$]) {
|
|
|
|
|
defineProperties(Array.prototype, {
|
|
|
|
|
values: Array.prototype[$iterator$]
|
|
|
|
|
});
|
|
|
|
|
if (Type.symbol(Symbol.unscopables)) {
|
|
|
|
|
Array.prototype[Symbol.unscopables].values = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-10-28 14:36:39 -04:00
|
|
|
|
defineProperties(Array.prototype, ArrayPrototypeShims);
|
|
|
|
|
|
|
|
|
|
addIterator(Array.prototype, function () { return this.values(); });
|
|
|
|
|
// Chrome defines keys/values/entries on Array, but doesn't give us
|
|
|
|
|
// any way to identify its iterator. So add our own shimmed field.
|
|
|
|
|
if (Object.getPrototypeOf) {
|
|
|
|
|
addIterator(Object.getPrototypeOf([].values()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var maxSafeInteger = Math.pow(2, 53) - 1;
|
|
|
|
|
defineProperties(Number, {
|
|
|
|
|
MAX_SAFE_INTEGER: maxSafeInteger,
|
|
|
|
|
MIN_SAFE_INTEGER: -maxSafeInteger,
|
|
|
|
|
EPSILON: 2.220446049250313e-16,
|
|
|
|
|
|
|
|
|
|
parseInt: globals.parseInt,
|
|
|
|
|
parseFloat: globals.parseFloat,
|
|
|
|
|
|
|
|
|
|
isFinite: function (value) {
|
|
|
|
|
return typeof value === 'number' && global_isFinite(value);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
isInteger: function (value) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
return Number.isFinite(value) && ES.ToInteger(value) === value;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
isSafeInteger: function (value) {
|
|
|
|
|
return Number.isInteger(value) && Math.abs(value) <= Number.MAX_SAFE_INTEGER;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
isNaN: function (value) {
|
|
|
|
|
// NaN !== NaN, but they are identical.
|
|
|
|
|
// NaNs are the only non-reflexive value, i.e., if x !== x,
|
|
|
|
|
// then x is NaN.
|
|
|
|
|
// isNaN is broken: it converts its argument to number, so
|
|
|
|
|
// isNaN('foo') => true
|
|
|
|
|
return value !== value;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Work around bugs in Array#find and Array#findIndex -- early
|
|
|
|
|
// implementations skipped holes in sparse arrays. (Note that the
|
|
|
|
|
// implementations of find/findIndex indirectly use shimmed
|
|
|
|
|
// methods of Number, so this test has to happen down here.)
|
2015-01-28 15:33:44 -05:00
|
|
|
|
/*jshint elision: true */
|
2014-10-28 14:36:39 -04:00
|
|
|
|
if (![, 1].find(function (item, idx) { return idx === 0; })) {
|
|
|
|
|
defineProperty(Array.prototype, 'find', ArrayPrototypeShims.find, true);
|
|
|
|
|
}
|
|
|
|
|
if ([, 1].findIndex(function (item, idx) { return idx === 0; }) !== 0) {
|
|
|
|
|
defineProperty(Array.prototype, 'findIndex', ArrayPrototypeShims.findIndex, true);
|
|
|
|
|
}
|
2015-01-28 15:33:44 -05:00
|
|
|
|
/*jshint elision: false */
|
2014-10-28 14:36:39 -04:00
|
|
|
|
|
|
|
|
|
if (supportsDescriptors) {
|
|
|
|
|
defineProperties(Object, {
|
|
|
|
|
// 19.1.3.1
|
|
|
|
|
assign: function (target, source) {
|
|
|
|
|
if (!ES.TypeIsObject(target)) {
|
|
|
|
|
throw new TypeError('target must be an object');
|
|
|
|
|
}
|
|
|
|
|
return Array.prototype.reduce.call(arguments, function (target, source) {
|
|
|
|
|
return Object.keys(Object(source)).reduce(function (target, key) {
|
|
|
|
|
target[key] = source[key];
|
|
|
|
|
return target;
|
|
|
|
|
}, target);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
is: function (a, b) {
|
|
|
|
|
return ES.SameValue(a, b);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 19.1.3.9
|
|
|
|
|
// shim from https://gist.github.com/WebReflection/5593554
|
|
|
|
|
setPrototypeOf: (function (Object, magic) {
|
|
|
|
|
var set;
|
|
|
|
|
|
|
|
|
|
var checkArgs = function (O, proto) {
|
|
|
|
|
if (!ES.TypeIsObject(O)) {
|
|
|
|
|
throw new TypeError('cannot set prototype on a non-object');
|
|
|
|
|
}
|
|
|
|
|
if (!(proto === null || ES.TypeIsObject(proto))) {
|
|
|
|
|
throw new TypeError('can only set prototype to an object or null' + proto);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var setPrototypeOf = function (O, proto) {
|
|
|
|
|
checkArgs(O, proto);
|
|
|
|
|
set.call(O, proto);
|
|
|
|
|
return O;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// this works already in Firefox and Safari
|
|
|
|
|
set = Object.getOwnPropertyDescriptor(Object.prototype, magic).set;
|
|
|
|
|
set.call({}, null);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
if (Object.prototype !== {}[magic]) {
|
|
|
|
|
// IE < 11 cannot be shimmed
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// probably Chrome or some old Mobile stock browser
|
|
|
|
|
set = function (proto) {
|
|
|
|
|
this[magic] = proto;
|
|
|
|
|
};
|
|
|
|
|
// please note that this will **not** work
|
|
|
|
|
// in those browsers that do not inherit
|
|
|
|
|
// __proto__ by mistake from Object.prototype
|
|
|
|
|
// in these cases we should probably throw an error
|
|
|
|
|
// or at least be informed about the issue
|
|
|
|
|
setPrototypeOf.polyfill = setPrototypeOf(
|
|
|
|
|
setPrototypeOf({}, null),
|
|
|
|
|
Object.prototype
|
|
|
|
|
) instanceof Object;
|
|
|
|
|
// setPrototypeOf.polyfill === true means it works as meant
|
|
|
|
|
// setPrototypeOf.polyfill === false means it's not 100% reliable
|
|
|
|
|
// setPrototypeOf.polyfill === undefined
|
|
|
|
|
// or
|
|
|
|
|
// setPrototypeOf.polyfill == null means it's not a polyfill
|
|
|
|
|
// which means it works as expected
|
|
|
|
|
// we can even delete Object.prototype.__proto__;
|
|
|
|
|
}
|
|
|
|
|
return setPrototypeOf;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
}(Object, '__proto__'))
|
2014-10-28 14:36:39 -04:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
}());
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
Object.keys('foo');
|
|
|
|
|
} catch (e) {
|
|
|
|
|
var originalObjectKeys = Object.keys;
|
|
|
|
|
Object.keys = function (obj) {
|
|
|
|
|
return originalObjectKeys(ES.ToObject(obj));
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-28 15:33:44 -05:00
|
|
|
|
if (!RegExp.prototype.flags && supportsDescriptors) {
|
|
|
|
|
var regExpFlagsGetter = function flags() {
|
|
|
|
|
if (!ES.TypeIsObject(this)) {
|
|
|
|
|
throw new TypeError('Method called on incompatible type: must be an object.');
|
|
|
|
|
}
|
|
|
|
|
var result = '';
|
|
|
|
|
if (this.global) {
|
|
|
|
|
result += 'g';
|
|
|
|
|
}
|
|
|
|
|
if (this.ignoreCase) {
|
|
|
|
|
result += 'i';
|
|
|
|
|
}
|
|
|
|
|
if (this.multiline) {
|
|
|
|
|
result += 'm';
|
|
|
|
|
}
|
|
|
|
|
if (this.unicode) {
|
|
|
|
|
result += 'u';
|
|
|
|
|
}
|
|
|
|
|
if (this.sticky) {
|
|
|
|
|
result += 'y';
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Value.getter(RegExp.prototype, 'flags', regExpFlagsGetter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var regExpSupportsFlagsWithRegex = (function () {
|
|
|
|
|
try {
|
|
|
|
|
return String(new RegExp(/a/g, 'i')) === '/a/i';
|
|
|
|
|
} catch (e) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}());
|
|
|
|
|
|
|
|
|
|
if (!regExpSupportsFlagsWithRegex && supportsDescriptors) {
|
|
|
|
|
var OrigRegExp = RegExp;
|
|
|
|
|
var RegExpShim = function RegExp(pattern, flags) {
|
|
|
|
|
if (Type.regex(pattern) && Type.string(flags)) {
|
|
|
|
|
return new RegExp(pattern.source, flags);
|
|
|
|
|
}
|
|
|
|
|
return new OrigRegExp(pattern, flags);
|
|
|
|
|
};
|
|
|
|
|
defineProperty(RegExpShim, 'toString', OrigRegExp.toString.bind(OrigRegExp), true);
|
|
|
|
|
if (Object.setPrototypeOf) {
|
|
|
|
|
// sets up proper prototype chain where possible
|
|
|
|
|
Object.setPrototypeOf(OrigRegExp, RegExpShim);
|
|
|
|
|
}
|
|
|
|
|
Object.getOwnPropertyNames(OrigRegExp).forEach(function (key) {
|
|
|
|
|
if (key === '$input') { return; } // Chrome < v39 & Opera < 26 have a nonstandard "$input" property
|
|
|
|
|
if (key in noop) { return; }
|
|
|
|
|
Value.proxy(OrigRegExp, key, RegExpShim);
|
|
|
|
|
});
|
|
|
|
|
RegExpShim.prototype = OrigRegExp.prototype;
|
|
|
|
|
Value.redefine(OrigRegExp.prototype, 'constructor', RegExpShim);
|
|
|
|
|
/*globals RegExp: true */
|
|
|
|
|
RegExp = RegExpShim;
|
|
|
|
|
Value.redefine(globals, 'RegExp', RegExpShim);
|
|
|
|
|
/*globals RegExp: false */
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-28 14:36:39 -04:00
|
|
|
|
var MathShims = {
|
|
|
|
|
acosh: function (value) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var x = Number(value);
|
|
|
|
|
if (Number.isNaN(x) || value < 1) { return NaN; }
|
|
|
|
|
if (x === 1) { return 0; }
|
|
|
|
|
if (x === Infinity) { return x; }
|
|
|
|
|
return Math.log(x / Math.E + Math.sqrt(x + 1) * Math.sqrt(x - 1) / Math.E) + 1;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
asinh: function (value) {
|
|
|
|
|
value = Number(value);
|
|
|
|
|
if (value === 0 || !global_isFinite(value)) {
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
return value < 0 ? -Math.asinh(-value) : Math.log(value + Math.sqrt(value * value + 1));
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
atanh: function (value) {
|
|
|
|
|
value = Number(value);
|
|
|
|
|
if (Number.isNaN(value) || value < -1 || value > 1) {
|
|
|
|
|
return NaN;
|
|
|
|
|
}
|
|
|
|
|
if (value === -1) { return -Infinity; }
|
|
|
|
|
if (value === 1) { return Infinity; }
|
|
|
|
|
if (value === 0) { return value; }
|
|
|
|
|
return 0.5 * Math.log((1 + value) / (1 - value));
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
cbrt: function (value) {
|
|
|
|
|
value = Number(value);
|
|
|
|
|
if (value === 0) { return value; }
|
|
|
|
|
var negate = value < 0, result;
|
|
|
|
|
if (negate) { value = -value; }
|
|
|
|
|
result = Math.pow(value, 1 / 3);
|
|
|
|
|
return negate ? -result : result;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
clz32: function (value) {
|
|
|
|
|
// See https://bugs.ecmascript.org/show_bug.cgi?id=2465
|
|
|
|
|
value = Number(value);
|
|
|
|
|
var number = ES.ToUint32(value);
|
|
|
|
|
if (number === 0) {
|
|
|
|
|
return 32;
|
|
|
|
|
}
|
|
|
|
|
return 32 - (number).toString(2).length;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
cosh: function (value) {
|
|
|
|
|
value = Number(value);
|
|
|
|
|
if (value === 0) { return 1; } // +0 or -0
|
|
|
|
|
if (Number.isNaN(value)) { return NaN; }
|
|
|
|
|
if (!global_isFinite(value)) { return Infinity; }
|
|
|
|
|
if (value < 0) { value = -value; }
|
|
|
|
|
if (value > 21) { return Math.exp(value) / 2; }
|
|
|
|
|
return (Math.exp(value) + Math.exp(-value)) / 2;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
expm1: function (value) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var x = Number(value);
|
|
|
|
|
if (x === -Infinity) { return -1; }
|
|
|
|
|
if (!global_isFinite(x) || value === 0) { return x; }
|
|
|
|
|
if (Math.abs(x) > 0.5) {
|
|
|
|
|
return Math.exp(x) - 1;
|
|
|
|
|
}
|
|
|
|
|
// A more precise approximation using Taylor series expansion
|
|
|
|
|
// from https://github.com/paulmillr/es6-shim/issues/314#issuecomment-70293986
|
|
|
|
|
var t = x;
|
|
|
|
|
var sum = 0;
|
|
|
|
|
var n = 1;
|
|
|
|
|
while (sum + t !== sum) {
|
|
|
|
|
sum += t;
|
|
|
|
|
n += 1;
|
|
|
|
|
t *= x / n;
|
|
|
|
|
}
|
|
|
|
|
return sum;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
hypot: function (x, y) {
|
|
|
|
|
var anyNaN = false;
|
|
|
|
|
var allZero = true;
|
|
|
|
|
var anyInfinity = false;
|
|
|
|
|
var numbers = [];
|
|
|
|
|
Array.prototype.every.call(arguments, function (arg) {
|
|
|
|
|
var num = Number(arg);
|
|
|
|
|
if (Number.isNaN(num)) {
|
|
|
|
|
anyNaN = true;
|
|
|
|
|
} else if (num === Infinity || num === -Infinity) {
|
|
|
|
|
anyInfinity = true;
|
|
|
|
|
} else if (num !== 0) {
|
|
|
|
|
allZero = false;
|
|
|
|
|
}
|
|
|
|
|
if (anyInfinity) {
|
|
|
|
|
return false;
|
|
|
|
|
} else if (!anyNaN) {
|
|
|
|
|
numbers.push(Math.abs(num));
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
if (anyInfinity) { return Infinity; }
|
|
|
|
|
if (anyNaN) { return NaN; }
|
|
|
|
|
if (allZero) { return 0; }
|
|
|
|
|
|
|
|
|
|
numbers.sort(function (a, b) { return b - a; });
|
|
|
|
|
var largest = numbers[0];
|
|
|
|
|
var divided = numbers.map(function (number) { return number / largest; });
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var sum = divided.reduce(function (sum, number) { return sum + (number * number); }, 0);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
return largest * Math.sqrt(sum);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
log2: function (value) {
|
|
|
|
|
return Math.log(value) * Math.LOG2E;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
log10: function (value) {
|
|
|
|
|
return Math.log(value) * Math.LOG10E;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
log1p: function (value) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var x = Number(value);
|
|
|
|
|
if (x < -1 || Number.isNaN(x)) { return NaN; }
|
|
|
|
|
if (x === 0 || x === Infinity) { return x; }
|
|
|
|
|
if (x === -1) { return -Infinity; }
|
2014-10-28 14:36:39 -04:00
|
|
|
|
|
2015-01-28 15:33:44 -05:00
|
|
|
|
return (1 + x) - 1 === 0 ? x : x * (Math.log(1 + x) / ((1 + x) - 1));
|
2014-10-28 14:36:39 -04:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
sign: function (value) {
|
|
|
|
|
var number = +value;
|
|
|
|
|
if (number === 0) { return number; }
|
|
|
|
|
if (Number.isNaN(number)) { return number; }
|
|
|
|
|
return number < 0 ? -1 : 1;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
sinh: function (value) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var x = Number(value);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
if (!global_isFinite(value) || value === 0) { return value; }
|
2015-01-28 15:33:44 -05:00
|
|
|
|
|
|
|
|
|
if (Math.abs(x) < 1) {
|
|
|
|
|
return (Math.expm1(x) - Math.expm1(-x)) / 2;
|
|
|
|
|
}
|
|
|
|
|
return (Math.exp(x - 1) - Math.exp(-x - 1)) * Math.E / 2;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
tanh: function (value) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var x = Number(value);
|
|
|
|
|
if (Number.isNaN(value) || x === 0) { return x; }
|
|
|
|
|
if (x === Infinity) { return 1; }
|
|
|
|
|
if (x === -Infinity) { return -1; }
|
|
|
|
|
var a = Math.expm1(x);
|
|
|
|
|
var b = Math.expm1(-x);
|
|
|
|
|
if (a === Infinity) { return 1; }
|
|
|
|
|
if (b === Infinity) { return -1; }
|
|
|
|
|
return (a - b) / (Math.exp(x) + Math.exp(-x));
|
2014-10-28 14:36:39 -04:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
trunc: function (value) {
|
|
|
|
|
var number = Number(value);
|
|
|
|
|
return number < 0 ? -Math.floor(-number) : Math.floor(number);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
imul: function (x, y) {
|
|
|
|
|
// taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul
|
|
|
|
|
x = ES.ToUint32(x);
|
|
|
|
|
y = ES.ToUint32(y);
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var ah = (x >>> 16) & 0xffff;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
var al = x & 0xffff;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var bh = (y >>> 16) & 0xffff;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
var bl = y & 0xffff;
|
|
|
|
|
// the shift by 0 fixes the sign on the high part
|
|
|
|
|
// the final |0 converts the unsigned value into a signed value
|
2015-01-28 15:33:44 -05:00
|
|
|
|
return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0) | 0);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
fround: function (x) {
|
|
|
|
|
if (x === 0 || x === Infinity || x === -Infinity || Number.isNaN(x)) {
|
|
|
|
|
return x;
|
|
|
|
|
}
|
|
|
|
|
var num = Number(x);
|
|
|
|
|
return numberConversion.toFloat32(num);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
defineProperties(Math, MathShims);
|
2015-01-28 15:33:44 -05:00
|
|
|
|
// Chrome 40 has an imprecise Math.tanh with very small numbers
|
|
|
|
|
defineProperty(Math, 'tanh', MathShims.tanh, Math.tanh(-2e-17) !== -2e-17);
|
|
|
|
|
// Chrome 40 loses Math.acosh precision with high numbers
|
|
|
|
|
defineProperty(Math, 'acosh', MathShims.acosh, Math.acosh(Number.MAX_VALUE) === Infinity);
|
|
|
|
|
|
|
|
|
|
var roundHandlesBoundaryConditions = Math.round(0.5 - Number.EPSILON / 4) === 0 && Math.round(-0.5 + Number.EPSILON / 3.99) === 1;
|
|
|
|
|
var origMathRound = Math.round;
|
|
|
|
|
defineProperty(Math, 'round', function round(x) {
|
|
|
|
|
if (-0.5 <= x && x < 0.5 && x !== 0) {
|
|
|
|
|
return Math.sign(x * 0);
|
|
|
|
|
}
|
|
|
|
|
return origMathRound(x);
|
|
|
|
|
}, !roundHandlesBoundaryConditions);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
|
|
|
|
|
if (Math.imul(0xffffffff, 5) !== -5) {
|
|
|
|
|
// Safari 6.1, at least, reports "0" for this value
|
|
|
|
|
Math.imul = MathShims.imul;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
}
|
2014-11-25 14:23:08 -05:00
|
|
|
|
if (typeof promise._status === 'undefined') {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
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]);
|
|
|
|
|
// see https://bugs.ecmascript.org/show_bug.cgi?id=2478
|
|
|
|
|
if (!capability.promise._es6construct) {
|
|
|
|
|
throw new TypeError('bad promise constructor');
|
|
|
|
|
}
|
2015-01-28 15:33:44 -05:00
|
|
|
|
if (!(ES.IsCallable(capability.resolve) && ES.IsCallable(capability.reject))) {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
throw new TypeError('bad promise constructor');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// find an appropriate setImmediate-alike
|
|
|
|
|
var setTimeout = globals.setTimeout;
|
|
|
|
|
var makeZeroTimeout;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
/*global window */
|
2014-10-28 14:36:39 -04:00
|
|
|
|
if (typeof window !== 'undefined' && ES.IsCallable(window.postMessage)) {
|
|
|
|
|
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) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
if (event.source === window && event.data === messageName) {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
event.stopPropagation();
|
|
|
|
|
if (timeouts.length === 0) { return; }
|
|
|
|
|
var fn = timeouts.shift();
|
|
|
|
|
fn();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
window.addEventListener('message', handleMessage, true);
|
|
|
|
|
return setZeroTimeout;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
var makePromiseAsap = function () {
|
|
|
|
|
// An efficient task-scheduler based on a pre-existing Promise
|
|
|
|
|
// implementation, which we can use even if we override the
|
|
|
|
|
// global Promise below (in order to workaround bugs)
|
|
|
|
|
// https://github.com/Raynos/observ-hash/issues/2#issuecomment-35857671
|
|
|
|
|
var P = globals.Promise;
|
|
|
|
|
return P && P.resolve && function (task) {
|
|
|
|
|
return P.resolve().then(task);
|
|
|
|
|
};
|
|
|
|
|
};
|
2015-01-28 15:33:44 -05:00
|
|
|
|
/*global process */
|
2014-10-28 14:36:39 -04:00
|
|
|
|
var enqueue = ES.IsCallable(globals.setImmediate) ?
|
|
|
|
|
globals.setImmediate.bind(globals) :
|
|
|
|
|
typeof process === 'object' && process.nextTick ? process.nextTick :
|
|
|
|
|
makePromiseAsap() ||
|
|
|
|
|
(ES.IsCallable(makeZeroTimeout) ? makeZeroTimeout() :
|
|
|
|
|
function (task) { setTimeout(task, 0); }); // fallback
|
|
|
|
|
|
2015-01-28 15:33:44 -05:00
|
|
|
|
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;
|
|
|
|
|
};
|
|
|
|
|
|
2014-10-28 14:36:39 -04:00
|
|
|
|
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 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');
|
|
|
|
|
}
|
2014-11-25 14:23:08 -05:00
|
|
|
|
if (typeof promise._status !== 'undefined') {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
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;
|
2014-11-25 14:23:08 -05:00
|
|
|
|
promise._resolveReactions = void 0;
|
|
|
|
|
promise._rejectReactions = void 0;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
promise._status = 'has-resolution';
|
|
|
|
|
triggerPromiseReactions(reactions, resolution);
|
|
|
|
|
};
|
|
|
|
|
var reject = function (reason) {
|
|
|
|
|
if (promise._status !== 'unresolved') { return; }
|
|
|
|
|
var reactions = promise._rejectReactions;
|
|
|
|
|
promise._result = reason;
|
2014-11-25 14:23:08 -05:00
|
|
|
|
promise._resolveReactions = void 0;
|
|
|
|
|
promise._rejectReactions = void 0;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
promise._status = 'has-rejection';
|
|
|
|
|
triggerPromiseReactions(reactions, reason);
|
|
|
|
|
};
|
|
|
|
|
try {
|
|
|
|
|
resolver(resolve, reject);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
reject(e);
|
|
|
|
|
}
|
|
|
|
|
return promise;
|
|
|
|
|
};
|
|
|
|
|
Promise$prototype = Promise.prototype;
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2015-01-28 15:33:44 -05:00
|
|
|
|
defineProperty(Promise, symbolSpecies, 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 || create(prototype);
|
|
|
|
|
defineProperties(obj, {
|
|
|
|
|
_status: void 0,
|
|
|
|
|
_result: void 0,
|
|
|
|
|
_resolveReactions: void 0,
|
|
|
|
|
_rejectReactions: void 0,
|
|
|
|
|
_promiseConstructor: void 0
|
|
|
|
|
});
|
|
|
|
|
obj._promiseConstructor = constructor;
|
|
|
|
|
return obj;
|
|
|
|
|
});
|
|
|
|
|
defineProperties(Promise, {
|
|
|
|
|
all: function all(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);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
2015-01-28 15:33:44 -05:00
|
|
|
|
return capability.promise;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
race: function race(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');
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
2015-01-28 15:33:44 -05:00
|
|
|
|
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);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
2015-01-28 15:33:44 -05:00
|
|
|
|
return capability.promise;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
reject: function reject(reason) {
|
|
|
|
|
var C = this;
|
|
|
|
|
var capability = new PromiseCapability(C);
|
|
|
|
|
var rejectPromise = capability.reject;
|
|
|
|
|
rejectPromise(reason); // call with this===undefined
|
|
|
|
|
return capability.promise;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
resolve: function resolve(v) {
|
|
|
|
|
var C = this;
|
|
|
|
|
if (ES.IsPromise(v)) {
|
|
|
|
|
var constructor = v._promiseConstructor;
|
|
|
|
|
if (constructor === C) { return v; }
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var capability = new PromiseCapability(C);
|
|
|
|
|
var resolvePromise = capability.resolve;
|
|
|
|
|
resolvePromise(v); // call with this===undefined
|
|
|
|
|
return capability.promise;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
2015-01-28 15:33:44 -05:00
|
|
|
|
});
|
2014-10-28 14:36:39 -04:00
|
|
|
|
|
2015-01-28 15:33:44 -05:00
|
|
|
|
defineProperties(Promise$prototype, {
|
|
|
|
|
'catch': function (onRejected) {
|
|
|
|
|
return this.then(void 0, onRejected);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
then: function then(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; };
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
2015-01-28 15:33:44 -05:00
|
|
|
|
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);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
break;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
case 'has-resolution':
|
|
|
|
|
triggerPromiseReactions([resolveReaction], promise._result);
|
|
|
|
|
break;
|
|
|
|
|
case 'has-rejection':
|
|
|
|
|
triggerPromiseReactions([rejectReaction], promise._result);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
throw new TypeError('unexpected');
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
2015-01-28 15:33:44 -05:00
|
|
|
|
return capability.promise;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
2015-01-28 15:33:44 -05:00
|
|
|
|
});
|
2014-10-28 14:36:39 -04:00
|
|
|
|
|
2015-01-28 15:33:44 -05:00
|
|
|
|
return Promise;
|
|
|
|
|
}());
|
2014-10-28 14:36:39 -04:00
|
|
|
|
|
2015-01-28 15:33:44 -05:00
|
|
|
|
// Chrome's native Promise has extra methods that it shouldn't have. Let's remove them.
|
|
|
|
|
if (globals.Promise) {
|
|
|
|
|
delete globals.Promise.accept;
|
|
|
|
|
delete globals.Promise.defer;
|
|
|
|
|
delete globals.Promise.prototype.chain;
|
|
|
|
|
}
|
2014-10-28 14:36:39 -04:00
|
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
|
var promiseSupportsSubclassing = supportsSubclassing(globals.Promise, function (S) {
|
|
|
|
|
return S.resolve(42) instanceof S;
|
|
|
|
|
});
|
|
|
|
|
var promiseIgnoresNonFunctionThenCallbacks = (function () {
|
|
|
|
|
try {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
globals.Promise.reject(42).then(null, 5).then(null, noop);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
return true;
|
|
|
|
|
} catch (ex) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}());
|
|
|
|
|
var promiseRequiresObjectContext = (function () {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
/*global Promise */
|
|
|
|
|
try { Promise.call(3, noop); } catch (e) { return true; }
|
2014-10-28 14:36:39 -04:00
|
|
|
|
return false;
|
|
|
|
|
}());
|
|
|
|
|
if (!promiseSupportsSubclassing || !promiseIgnoresNonFunctionThenCallbacks || !promiseRequiresObjectContext) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
/*globals Promise: true */
|
|
|
|
|
Promise = PromiseShim;
|
|
|
|
|
/*globals Promise: false */
|
|
|
|
|
defineProperty(globals, 'Promise', PromiseShim, true);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Map and Set require a true ES5 environment
|
|
|
|
|
// Their fast path also requires that the environment preserve
|
|
|
|
|
// property insertion order, which is not guaranteed by the spec.
|
|
|
|
|
var testOrder = function (a) {
|
|
|
|
|
var b = Object.keys(a.reduce(function (o, k) {
|
|
|
|
|
o[k] = true;
|
|
|
|
|
return o;
|
|
|
|
|
}, {}));
|
|
|
|
|
return a.join(':') === b.join(':');
|
|
|
|
|
};
|
|
|
|
|
var preservesInsertionOrder = testOrder(['z', 'a', 'bb']);
|
|
|
|
|
// some engines (eg, Chrome) only preserve insertion order for string keys
|
|
|
|
|
var preservesNumericInsertionOrder = testOrder(['z', 1, 'a', '3', 2]);
|
|
|
|
|
|
|
|
|
|
if (supportsDescriptors) {
|
|
|
|
|
|
|
|
|
|
var fastkey = function fastkey(key) {
|
|
|
|
|
if (!preservesInsertionOrder) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
var type = typeof key;
|
|
|
|
|
if (type === 'string') {
|
|
|
|
|
return '$' + key;
|
|
|
|
|
} else if (type === 'number') {
|
|
|
|
|
// note that -0 will get coerced to "0" when used as a property key
|
|
|
|
|
if (!preservesNumericInsertionOrder) {
|
|
|
|
|
return 'n' + key;
|
|
|
|
|
}
|
|
|
|
|
return key;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var emptyObject = function emptyObject() {
|
|
|
|
|
// accomodate some older not-quite-ES5 browsers
|
|
|
|
|
return Object.create ? Object.create(null) : {};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var collectionShims = {
|
|
|
|
|
Map: (function () {
|
|
|
|
|
|
|
|
|
|
var empty = {};
|
|
|
|
|
|
|
|
|
|
function MapEntry(key, value) {
|
|
|
|
|
this.key = key;
|
|
|
|
|
this.value = value;
|
|
|
|
|
this.next = null;
|
|
|
|
|
this.prev = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MapEntry.prototype.isRemoved = function () {
|
|
|
|
|
return this.key === empty;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function MapIterator(map, kind) {
|
|
|
|
|
this.head = map._head;
|
|
|
|
|
this.i = this.head;
|
|
|
|
|
this.kind = kind;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MapIterator.prototype = {
|
|
|
|
|
next: function () {
|
|
|
|
|
var i = this.i, kind = this.kind, head = this.head, result;
|
2014-11-25 14:23:08 -05:00
|
|
|
|
if (typeof this.i === 'undefined') {
|
|
|
|
|
return { value: void 0, done: true };
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
|
|
|
|
while (i.isRemoved() && i !== head) {
|
|
|
|
|
// back up off of removed entries
|
|
|
|
|
i = i.prev;
|
|
|
|
|
}
|
|
|
|
|
// advance to next unreturned element.
|
|
|
|
|
while (i.next !== head) {
|
|
|
|
|
i = i.next;
|
|
|
|
|
if (!i.isRemoved()) {
|
|
|
|
|
if (kind === 'key') {
|
|
|
|
|
result = i.key;
|
|
|
|
|
} else if (kind === 'value') {
|
|
|
|
|
result = i.value;
|
|
|
|
|
} else {
|
|
|
|
|
result = [i.key, i.value];
|
|
|
|
|
}
|
|
|
|
|
this.i = i;
|
|
|
|
|
return { value: result, done: false };
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// once the iterator is done, it is done forever.
|
2014-11-25 14:23:08 -05:00
|
|
|
|
this.i = void 0;
|
|
|
|
|
return { value: void 0, done: true };
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
addIterator(MapIterator.prototype);
|
|
|
|
|
|
|
|
|
|
function Map(iterable) {
|
|
|
|
|
var map = this;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
if (!ES.TypeIsObject(map)) {
|
|
|
|
|
throw new TypeError('Map does not accept arguments when called as a function');
|
|
|
|
|
}
|
2014-10-28 14:36:39 -04:00
|
|
|
|
map = emulateES6construct(map);
|
|
|
|
|
if (!map._es6map) {
|
|
|
|
|
throw new TypeError('bad map');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var head = new MapEntry(null, null);
|
|
|
|
|
// circular doubly-linked list.
|
|
|
|
|
head.next = head.prev = head;
|
|
|
|
|
|
|
|
|
|
defineProperties(map, {
|
|
|
|
|
_head: head,
|
|
|
|
|
_storage: emptyObject(),
|
|
|
|
|
_size: 0
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Optionally initialize map from iterable
|
2014-11-25 14:23:08 -05:00
|
|
|
|
if (typeof iterable !== 'undefined' && iterable !== null) {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
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;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
defineProperty(Map, symbolSpecies, function (obj) {
|
|
|
|
|
var constructor = this;
|
|
|
|
|
var prototype = constructor.prototype || Map$prototype;
|
|
|
|
|
obj = obj || create(prototype);
|
|
|
|
|
defineProperties(obj, { _es6map: true });
|
|
|
|
|
return obj;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
});
|
|
|
|
|
|
2015-01-28 15:33:44 -05:00
|
|
|
|
Value.getter(Map.prototype, 'size', function () {
|
|
|
|
|
if (typeof this._size === 'undefined') {
|
|
|
|
|
throw new TypeError('size method called on incompatible Map');
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
2015-01-28 15:33:44 -05:00
|
|
|
|
return this._size;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
defineProperties(Map.prototype, {
|
|
|
|
|
get: function (key) {
|
|
|
|
|
var fkey = fastkey(key);
|
|
|
|
|
if (fkey !== null) {
|
|
|
|
|
// fast O(1) path
|
|
|
|
|
var entry = this._storage[fkey];
|
2014-11-25 14:23:08 -05:00
|
|
|
|
if (entry) {
|
|
|
|
|
return entry.value;
|
|
|
|
|
} else {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
|
|
|
|
var head = this._head, i = head;
|
|
|
|
|
while ((i = i.next) !== head) {
|
|
|
|
|
if (ES.SameValueZero(i.key, key)) {
|
|
|
|
|
return i.value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
has: function (key) {
|
|
|
|
|
var fkey = fastkey(key);
|
|
|
|
|
if (fkey !== null) {
|
|
|
|
|
// fast O(1) path
|
|
|
|
|
return typeof this._storage[fkey] !== 'undefined';
|
|
|
|
|
}
|
|
|
|
|
var head = this._head, i = head;
|
|
|
|
|
while ((i = i.next) !== head) {
|
|
|
|
|
if (ES.SameValueZero(i.key, key)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
set: function (key, value) {
|
|
|
|
|
var head = this._head, i = head, entry;
|
|
|
|
|
var fkey = fastkey(key);
|
|
|
|
|
if (fkey !== null) {
|
|
|
|
|
// fast O(1) path
|
|
|
|
|
if (typeof this._storage[fkey] !== 'undefined') {
|
|
|
|
|
this._storage[fkey].value = value;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
return this;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
} else {
|
|
|
|
|
entry = this._storage[fkey] = new MapEntry(key, value);
|
|
|
|
|
i = head.prev;
|
|
|
|
|
// fall through
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
while ((i = i.next) !== head) {
|
|
|
|
|
if (ES.SameValueZero(i.key, key)) {
|
|
|
|
|
i.value = value;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
return this;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
entry = entry || new MapEntry(key, value);
|
|
|
|
|
if (ES.SameValue(-0, key)) {
|
|
|
|
|
entry.key = +0; // coerce -0 to +0 in entry
|
|
|
|
|
}
|
|
|
|
|
entry.next = this._head;
|
|
|
|
|
entry.prev = this._head.prev;
|
|
|
|
|
entry.prev.next = entry;
|
|
|
|
|
entry.next.prev = entry;
|
|
|
|
|
this._size += 1;
|
|
|
|
|
return this;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
'delete': function (key) {
|
|
|
|
|
var head = this._head, i = head;
|
|
|
|
|
var fkey = fastkey(key);
|
|
|
|
|
if (fkey !== null) {
|
|
|
|
|
// fast O(1) path
|
|
|
|
|
if (typeof this._storage[fkey] === 'undefined') {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
i = this._storage[fkey].prev;
|
|
|
|
|
delete this._storage[fkey];
|
|
|
|
|
// fall through
|
|
|
|
|
}
|
|
|
|
|
while ((i = i.next) !== head) {
|
|
|
|
|
if (ES.SameValueZero(i.key, key)) {
|
|
|
|
|
i.key = i.value = empty;
|
|
|
|
|
i.prev.next = i.next;
|
|
|
|
|
i.next.prev = i.prev;
|
|
|
|
|
this._size -= 1;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
clear: function () {
|
|
|
|
|
this._size = 0;
|
|
|
|
|
this._storage = emptyObject();
|
|
|
|
|
var head = this._head, i = head, p = i.next;
|
|
|
|
|
while ((i = p) !== head) {
|
|
|
|
|
i.key = i.value = empty;
|
|
|
|
|
p = i.next;
|
|
|
|
|
i.next = i.prev = head;
|
|
|
|
|
}
|
|
|
|
|
head.next = head.prev = head;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
keys: function () {
|
|
|
|
|
return new MapIterator(this, 'key');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
values: function () {
|
|
|
|
|
return new MapIterator(this, 'value');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
entries: function () {
|
|
|
|
|
return new MapIterator(this, 'key+value');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
forEach: function (callback) {
|
|
|
|
|
var context = arguments.length > 1 ? arguments[1] : null;
|
|
|
|
|
var it = this.entries();
|
|
|
|
|
for (var entry = it.next(); !entry.done; entry = it.next()) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
if (context) {
|
|
|
|
|
callback.call(context, entry.value[1], entry.value[0], this);
|
|
|
|
|
} else {
|
|
|
|
|
callback(entry.value[1], entry.value[0], this);
|
|
|
|
|
}
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
addIterator(Map.prototype, function () { return this.entries(); });
|
|
|
|
|
|
|
|
|
|
return Map;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
}()),
|
2014-10-28 14:36:39 -04:00
|
|
|
|
|
|
|
|
|
Set: (function () {
|
|
|
|
|
// Creating a Map is expensive. To speed up the common case of
|
|
|
|
|
// Sets containing only string or numeric keys, we use an object
|
|
|
|
|
// as backing storage and lazily create a full Map only when
|
|
|
|
|
// required.
|
|
|
|
|
var SetShim = function Set(iterable) {
|
|
|
|
|
var set = this;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
if (!ES.TypeIsObject(set)) {
|
|
|
|
|
throw new TypeError('Set does not accept arguments when called as a function');
|
|
|
|
|
}
|
2014-10-28 14:36:39 -04:00
|
|
|
|
set = emulateES6construct(set);
|
|
|
|
|
if (!set._es6set) {
|
|
|
|
|
throw new TypeError('bad set');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
defineProperties(set, {
|
|
|
|
|
'[[SetData]]': null,
|
|
|
|
|
_storage: emptyObject()
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Optionally initialize map from iterable
|
2014-11-25 14:23:08 -05:00
|
|
|
|
if (typeof iterable !== 'undefined' && iterable !== null) {
|
2014-10-28 14:36:39 -04:00
|
|
|
|
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;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
defineProperty(SetShim, symbolSpecies, function (obj) {
|
|
|
|
|
var constructor = this;
|
|
|
|
|
var prototype = constructor.prototype || Set$prototype;
|
|
|
|
|
obj = obj || create(prototype);
|
|
|
|
|
defineProperties(obj, { _es6set: true });
|
|
|
|
|
return obj;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Switch from the object backing storage to a full Map.
|
|
|
|
|
var ensureMap = function ensureMap(set) {
|
|
|
|
|
if (!set['[[SetData]]']) {
|
|
|
|
|
var m = set['[[SetData]]'] = new collectionShims.Map();
|
|
|
|
|
Object.keys(set._storage).forEach(function (k) {
|
|
|
|
|
// fast check for leading '$'
|
|
|
|
|
if (k.charCodeAt(0) === 36) {
|
|
|
|
|
k = k.slice(1);
|
|
|
|
|
} else if (k.charAt(0) === 'n') {
|
|
|
|
|
k = +k.slice(1);
|
|
|
|
|
} else {
|
|
|
|
|
k = +k;
|
|
|
|
|
}
|
|
|
|
|
m.set(k, k);
|
|
|
|
|
});
|
|
|
|
|
set._storage = null; // free old backing storage
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2015-01-28 15:33:44 -05:00
|
|
|
|
Value.getter(SetShim.prototype, 'size', function () {
|
|
|
|
|
if (typeof this._storage === 'undefined') {
|
|
|
|
|
// https://github.com/paulmillr/es6-shim/issues/176
|
|
|
|
|
throw new TypeError('size method called on incompatible Set');
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
2015-01-28 15:33:44 -05:00
|
|
|
|
ensureMap(this);
|
|
|
|
|
return this['[[SetData]]'].size;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
defineProperties(SetShim.prototype, {
|
|
|
|
|
has: function (key) {
|
|
|
|
|
var fkey;
|
|
|
|
|
if (this._storage && (fkey = fastkey(key)) !== null) {
|
|
|
|
|
return !!this._storage[fkey];
|
|
|
|
|
}
|
|
|
|
|
ensureMap(this);
|
|
|
|
|
return this['[[SetData]]'].has(key);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
add: function (key) {
|
|
|
|
|
var fkey;
|
|
|
|
|
if (this._storage && (fkey = fastkey(key)) !== null) {
|
|
|
|
|
this._storage[fkey] = true;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
return this;
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
|
|
|
|
ensureMap(this);
|
|
|
|
|
this['[[SetData]]'].set(key, key);
|
|
|
|
|
return this;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
'delete': function (key) {
|
|
|
|
|
var fkey;
|
|
|
|
|
if (this._storage && (fkey = fastkey(key)) !== null) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
var hasFKey = _hasOwnProperty(this._storage, fkey);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
return (delete this._storage[fkey]) && hasFKey;
|
|
|
|
|
}
|
|
|
|
|
ensureMap(this);
|
|
|
|
|
return this['[[SetData]]']['delete'](key);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
clear: function () {
|
|
|
|
|
if (this._storage) {
|
|
|
|
|
this._storage = emptyObject();
|
2015-01-28 15:33:44 -05:00
|
|
|
|
} else {
|
|
|
|
|
this['[[SetData]]'].clear();
|
2014-10-28 14:36:39 -04:00
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
values: function () {
|
|
|
|
|
ensureMap(this);
|
|
|
|
|
return this['[[SetData]]'].values();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
entries: function () {
|
|
|
|
|
ensureMap(this);
|
|
|
|
|
return this['[[SetData]]'].entries();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
forEach: function (callback) {
|
|
|
|
|
var context = arguments.length > 1 ? arguments[1] : null;
|
|
|
|
|
var entireSet = this;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
ensureMap(entireSet);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
this['[[SetData]]'].forEach(function (value, key) {
|
2015-01-28 15:33:44 -05:00
|
|
|
|
if (context) {
|
|
|
|
|
callback.call(context, key, key, entireSet);
|
|
|
|
|
} else {
|
|
|
|
|
callback(key, key, entireSet);
|
|
|
|
|
}
|
2014-10-28 14:36:39 -04:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
2015-01-28 15:33:44 -05:00
|
|
|
|
defineProperty(SetShim, 'keys', SetShim.values, true);
|
2014-10-28 14:36:39 -04:00
|
|
|
|
addIterator(SetShim.prototype, function () { return this.values(); });
|
|
|
|
|
|
|
|
|
|
return SetShim;
|
2015-01-28 15:33:44 -05:00
|
|
|
|
}())
|
2014-10-28 14:36:39 -04:00
|
|
|
|
};
|
|
|
|
|
defineProperties(globals, collectionShims);
|
|
|
|
|
|
|
|
|
|
if (globals.Map || globals.Set) {
|
|
|
|
|
/*
|
|
|
|
|
- In Firefox < 23, Map#size is a function.
|
|
|
|
|
- In all current Firefox, Set#entries/keys/values & Map#clear do not exist
|
|
|
|
|
- https://bugzilla.mozilla.org/show_bug.cgi?id=869996
|
|
|
|
|
- In Firefox 24, Map and Set do not implement forEach
|
|
|
|
|
- In Firefox 25 at least, Map and Set are callable without "new"
|
|
|
|
|
*/
|
|
|
|
|
if (
|
|
|
|
|
typeof globals.Map.prototype.clear !== 'function' ||
|
|
|
|
|
new globals.Set().size !== 0 ||
|
|
|
|
|
new globals.Map().size !== 0 ||
|
|
|
|
|
typeof globals.Map.prototype.keys !== 'function' ||
|
|
|
|
|
typeof globals.Set.prototype.keys !== 'function' ||
|
|
|
|
|
typeof globals.Map.prototype.forEach !== 'function' ||
|
|
|
|
|
typeof globals.Set.prototype.forEach !== 'function' ||
|
|
|
|
|
isCallableWithoutNew(globals.Map) ||
|
|
|
|
|
isCallableWithoutNew(globals.Set) ||
|
|
|
|
|
!supportsSubclassing(globals.Map, function (M) {
|
|
|
|
|
var m = new M([]);
|
|
|
|
|
// Firefox 32 is ok with the instantiating the subclass but will
|
|
|
|
|
// throw when the map is used.
|
|
|
|
|
m.set(42, 42);
|
|
|
|
|
return m instanceof M;
|
|
|
|
|
})
|
|
|
|
|
) {
|
|
|
|
|
globals.Map = collectionShims.Map;
|
|
|
|
|
globals.Set = collectionShims.Set;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-01-28 15:33:44 -05:00
|
|
|
|
if (globals.Set.prototype.keys !== globals.Set.prototype.values) {
|
|
|
|
|
defineProperty(globals.Set.prototype, 'keys', globals.Set.prototype.values, true);
|
|
|
|
|
}
|
2014-10-28 14:36:39 -04:00
|
|
|
|
// Shim incomplete iterator implementations.
|
|
|
|
|
addIterator(Object.getPrototypeOf((new globals.Map()).keys()));
|
|
|
|
|
addIterator(Object.getPrototypeOf((new globals.Set()).keys()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return globals;
|
|
|
|
|
}));
|