|
|
- 'use strict';
-
- var GetIntrinsic = require('./GetIntrinsic');
-
- var $Object = GetIntrinsic('%Object%');
- var $EvalError = GetIntrinsic('%EvalError%');
- var $TypeError = GetIntrinsic('%TypeError%');
- var $String = GetIntrinsic('%String%');
- var $Date = GetIntrinsic('%Date%');
- var $Number = GetIntrinsic('%Number%');
- var $floor = GetIntrinsic('%Math.floor%');
- var $DateUTC = GetIntrinsic('%Date.UTC%');
- var $abs = GetIntrinsic('%Math.abs%');
-
- var assertRecord = require('./helpers/assertRecord');
- var isPropertyDescriptor = require('./helpers/isPropertyDescriptor');
- var $isNaN = require('./helpers/isNaN');
- var $isFinite = require('./helpers/isFinite');
- var sign = require('./helpers/sign');
- var mod = require('./helpers/mod');
- var isPrefixOf = require('./helpers/isPrefixOf');
- var callBound = require('./helpers/callBound');
-
- var IsCallable = require('is-callable');
- var toPrimitive = require('es-to-primitive/es5');
-
- var has = require('has');
-
- var $getUTCFullYear = callBound('Date.prototype.getUTCFullYear');
-
- var HoursPerDay = 24;
- var MinutesPerHour = 60;
- var SecondsPerMinute = 60;
- var msPerSecond = 1e3;
- var msPerMinute = msPerSecond * SecondsPerMinute;
- var msPerHour = msPerMinute * MinutesPerHour;
- var msPerDay = 86400000;
-
- // https://es5.github.io/#x9
- var ES5 = {
- ToPrimitive: toPrimitive,
-
- ToBoolean: function ToBoolean(value) {
- return !!value;
- },
- ToNumber: function ToNumber(value) {
- return +value; // eslint-disable-line no-implicit-coercion
- },
- ToInteger: function ToInteger(value) {
- var number = this.ToNumber(value);
- if ($isNaN(number)) { return 0; }
- if (number === 0 || !$isFinite(number)) { return number; }
- return sign(number) * Math.floor(Math.abs(number));
- },
- ToInt32: function ToInt32(x) {
- return this.ToNumber(x) >> 0;
- },
- ToUint32: function ToUint32(x) {
- return this.ToNumber(x) >>> 0;
- },
- ToUint16: function ToUint16(value) {
- var number = this.ToNumber(value);
- if ($isNaN(number) || number === 0 || !$isFinite(number)) { return 0; }
- var posInt = sign(number) * Math.floor(Math.abs(number));
- return mod(posInt, 0x10000);
- },
- ToString: function ToString(value) {
- return $String(value);
- },
- ToObject: function ToObject(value) {
- this.CheckObjectCoercible(value);
- return $Object(value);
- },
- CheckObjectCoercible: function CheckObjectCoercible(value, optMessage) {
- /* jshint eqnull:true */
- if (value == null) {
- throw new $TypeError(optMessage || 'Cannot call method on ' + value);
- }
- return value;
- },
- IsCallable: IsCallable,
- SameValue: function SameValue(x, y) {
- if (x === y) { // 0 === -0, but they are not identical.
- if (x === 0) { return 1 / x === 1 / y; }
- return true;
- }
- return $isNaN(x) && $isNaN(y);
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-8
- Type: function Type(x) {
- if (x === null) {
- return 'Null';
- }
- if (typeof x === 'undefined') {
- return 'Undefined';
- }
- if (typeof x === 'function' || typeof x === 'object') {
- return 'Object';
- }
- if (typeof x === 'number') {
- return 'Number';
- }
- if (typeof x === 'boolean') {
- return 'Boolean';
- }
- if (typeof x === 'string') {
- return 'String';
- }
- },
-
- // https://ecma-international.org/ecma-262/6.0/#sec-property-descriptor-specification-type
- IsPropertyDescriptor: function IsPropertyDescriptor(Desc) {
- return isPropertyDescriptor(this, Desc);
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-8.10.1
- IsAccessorDescriptor: function IsAccessorDescriptor(Desc) {
- if (typeof Desc === 'undefined') {
- return false;
- }
-
- assertRecord(this, 'Property Descriptor', 'Desc', Desc);
-
- if (!has(Desc, '[[Get]]') && !has(Desc, '[[Set]]')) {
- return false;
- }
-
- return true;
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-8.10.2
- IsDataDescriptor: function IsDataDescriptor(Desc) {
- if (typeof Desc === 'undefined') {
- return false;
- }
-
- assertRecord(this, 'Property Descriptor', 'Desc', Desc);
-
- if (!has(Desc, '[[Value]]') && !has(Desc, '[[Writable]]')) {
- return false;
- }
-
- return true;
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-8.10.3
- IsGenericDescriptor: function IsGenericDescriptor(Desc) {
- if (typeof Desc === 'undefined') {
- return false;
- }
-
- assertRecord(this, 'Property Descriptor', 'Desc', Desc);
-
- if (!this.IsAccessorDescriptor(Desc) && !this.IsDataDescriptor(Desc)) {
- return true;
- }
-
- return false;
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-8.10.4
- FromPropertyDescriptor: function FromPropertyDescriptor(Desc) {
- if (typeof Desc === 'undefined') {
- return Desc;
- }
-
- assertRecord(this, 'Property Descriptor', 'Desc', Desc);
-
- if (this.IsDataDescriptor(Desc)) {
- return {
- value: Desc['[[Value]]'],
- writable: !!Desc['[[Writable]]'],
- enumerable: !!Desc['[[Enumerable]]'],
- configurable: !!Desc['[[Configurable]]']
- };
- } else if (this.IsAccessorDescriptor(Desc)) {
- return {
- get: Desc['[[Get]]'],
- set: Desc['[[Set]]'],
- enumerable: !!Desc['[[Enumerable]]'],
- configurable: !!Desc['[[Configurable]]']
- };
- } else {
- throw new $TypeError('FromPropertyDescriptor must be called with a fully populated Property Descriptor');
- }
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-8.10.5
- ToPropertyDescriptor: function ToPropertyDescriptor(Obj) {
- if (this.Type(Obj) !== 'Object') {
- throw new $TypeError('ToPropertyDescriptor requires an object');
- }
-
- var desc = {};
- if (has(Obj, 'enumerable')) {
- desc['[[Enumerable]]'] = this.ToBoolean(Obj.enumerable);
- }
- if (has(Obj, 'configurable')) {
- desc['[[Configurable]]'] = this.ToBoolean(Obj.configurable);
- }
- if (has(Obj, 'value')) {
- desc['[[Value]]'] = Obj.value;
- }
- if (has(Obj, 'writable')) {
- desc['[[Writable]]'] = this.ToBoolean(Obj.writable);
- }
- if (has(Obj, 'get')) {
- var getter = Obj.get;
- if (typeof getter !== 'undefined' && !this.IsCallable(getter)) {
- throw new TypeError('getter must be a function');
- }
- desc['[[Get]]'] = getter;
- }
- if (has(Obj, 'set')) {
- var setter = Obj.set;
- if (typeof setter !== 'undefined' && !this.IsCallable(setter)) {
- throw new $TypeError('setter must be a function');
- }
- desc['[[Set]]'] = setter;
- }
-
- if ((has(desc, '[[Get]]') || has(desc, '[[Set]]')) && (has(desc, '[[Value]]') || has(desc, '[[Writable]]'))) {
- throw new $TypeError('Invalid property descriptor. Cannot both specify accessors and a value or writable attribute');
- }
- return desc;
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-11.9.3
- 'Abstract Equality Comparison': function AbstractEqualityComparison(x, y) {
- var xType = this.Type(x);
- var yType = this.Type(y);
- if (xType === yType) {
- return x === y; // ES6+ specified this shortcut anyways.
- }
- if (x == null && y == null) {
- return true;
- }
- if (xType === 'Number' && yType === 'String') {
- return this['Abstract Equality Comparison'](x, this.ToNumber(y));
- }
- if (xType === 'String' && yType === 'Number') {
- return this['Abstract Equality Comparison'](this.ToNumber(x), y);
- }
- if (xType === 'Boolean') {
- return this['Abstract Equality Comparison'](this.ToNumber(x), y);
- }
- if (yType === 'Boolean') {
- return this['Abstract Equality Comparison'](x, this.ToNumber(y));
- }
- if ((xType === 'String' || xType === 'Number') && yType === 'Object') {
- return this['Abstract Equality Comparison'](x, this.ToPrimitive(y));
- }
- if (xType === 'Object' && (yType === 'String' || yType === 'Number')) {
- return this['Abstract Equality Comparison'](this.ToPrimitive(x), y);
- }
- return false;
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-11.9.6
- 'Strict Equality Comparison': function StrictEqualityComparison(x, y) {
- var xType = this.Type(x);
- var yType = this.Type(y);
- if (xType !== yType) {
- return false;
- }
- if (xType === 'Undefined' || xType === 'Null') {
- return true;
- }
- return x === y; // shortcut for steps 4-7
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-11.8.5
- // eslint-disable-next-line max-statements
- 'Abstract Relational Comparison': function AbstractRelationalComparison(x, y, LeftFirst) {
- if (this.Type(LeftFirst) !== 'Boolean') {
- throw new $TypeError('Assertion failed: LeftFirst argument must be a Boolean');
- }
- var px;
- var py;
- if (LeftFirst) {
- px = this.ToPrimitive(x, $Number);
- py = this.ToPrimitive(y, $Number);
- } else {
- py = this.ToPrimitive(y, $Number);
- px = this.ToPrimitive(x, $Number);
- }
- var bothStrings = this.Type(px) === 'String' && this.Type(py) === 'String';
- if (!bothStrings) {
- var nx = this.ToNumber(px);
- var ny = this.ToNumber(py);
- if ($isNaN(nx) || $isNaN(ny)) {
- return undefined;
- }
- if ($isFinite(nx) && $isFinite(ny) && nx === ny) {
- return false;
- }
- if (nx === 0 && ny === 0) {
- return false;
- }
- if (nx === Infinity) {
- return false;
- }
- if (ny === Infinity) {
- return true;
- }
- if (ny === -Infinity) {
- return false;
- }
- if (nx === -Infinity) {
- return true;
- }
- return nx < ny; // by now, these are both nonzero, finite, and not equal
- }
- if (isPrefixOf(py, px)) {
- return false;
- }
- if (isPrefixOf(px, py)) {
- return true;
- }
- return px < py; // both strings, neither a prefix of the other. shortcut for steps c-f
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.10
- msFromTime: function msFromTime(t) {
- return mod(t, msPerSecond);
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.10
- SecFromTime: function SecFromTime(t) {
- return mod($floor(t / msPerSecond), SecondsPerMinute);
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.10
- MinFromTime: function MinFromTime(t) {
- return mod($floor(t / msPerMinute), MinutesPerHour);
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.10
- HourFromTime: function HourFromTime(t) {
- return mod($floor(t / msPerHour), HoursPerDay);
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.2
- Day: function Day(t) {
- return $floor(t / msPerDay);
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.2
- TimeWithinDay: function TimeWithinDay(t) {
- return mod(t, msPerDay);
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.3
- DayFromYear: function DayFromYear(y) {
- return (365 * (y - 1970)) + $floor((y - 1969) / 4) - $floor((y - 1901) / 100) + $floor((y - 1601) / 400);
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.3
- TimeFromYear: function TimeFromYear(y) {
- return msPerDay * this.DayFromYear(y);
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.3
- YearFromTime: function YearFromTime(t) {
- // largest y such that this.TimeFromYear(y) <= t
- return $getUTCFullYear(new $Date(t));
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.6
- WeekDay: function WeekDay(t) {
- return mod(this.Day(t) + 4, 7);
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.3
- DaysInYear: function DaysInYear(y) {
- if (mod(y, 4) !== 0) {
- return 365;
- }
- if (mod(y, 100) !== 0) {
- return 366;
- }
- if (mod(y, 400) !== 0) {
- return 365;
- }
- return 366;
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.3
- InLeapYear: function InLeapYear(t) {
- var days = this.DaysInYear(this.YearFromTime(t));
- if (days === 365) {
- return 0;
- }
- if (days === 366) {
- return 1;
- }
- throw new $EvalError('Assertion failed: there are not 365 or 366 days in a year, got: ' + days);
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.4
- DayWithinYear: function DayWithinYear(t) {
- return this.Day(t) - this.DayFromYear(this.YearFromTime(t));
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.4
- MonthFromTime: function MonthFromTime(t) {
- var day = this.DayWithinYear(t);
- if (0 <= day && day < 31) {
- return 0;
- }
- var leap = this.InLeapYear(t);
- if (31 <= day && day < (59 + leap)) {
- return 1;
- }
- if ((59 + leap) <= day && day < (90 + leap)) {
- return 2;
- }
- if ((90 + leap) <= day && day < (120 + leap)) {
- return 3;
- }
- if ((120 + leap) <= day && day < (151 + leap)) {
- return 4;
- }
- if ((151 + leap) <= day && day < (181 + leap)) {
- return 5;
- }
- if ((181 + leap) <= day && day < (212 + leap)) {
- return 6;
- }
- if ((212 + leap) <= day && day < (243 + leap)) {
- return 7;
- }
- if ((243 + leap) <= day && day < (273 + leap)) {
- return 8;
- }
- if ((273 + leap) <= day && day < (304 + leap)) {
- return 9;
- }
- if ((304 + leap) <= day && day < (334 + leap)) {
- return 10;
- }
- if ((334 + leap) <= day && day < (365 + leap)) {
- return 11;
- }
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.5
- DateFromTime: function DateFromTime(t) {
- var m = this.MonthFromTime(t);
- var d = this.DayWithinYear(t);
- if (m === 0) {
- return d + 1;
- }
- if (m === 1) {
- return d - 30;
- }
- var leap = this.InLeapYear(t);
- if (m === 2) {
- return d - 58 - leap;
- }
- if (m === 3) {
- return d - 89 - leap;
- }
- if (m === 4) {
- return d - 119 - leap;
- }
- if (m === 5) {
- return d - 150 - leap;
- }
- if (m === 6) {
- return d - 180 - leap;
- }
- if (m === 7) {
- return d - 211 - leap;
- }
- if (m === 8) {
- return d - 242 - leap;
- }
- if (m === 9) {
- return d - 272 - leap;
- }
- if (m === 10) {
- return d - 303 - leap;
- }
- if (m === 11) {
- return d - 333 - leap;
- }
- throw new $EvalError('Assertion failed: MonthFromTime returned an impossible value: ' + m);
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.12
- MakeDay: function MakeDay(year, month, date) {
- if (!$isFinite(year) || !$isFinite(month) || !$isFinite(date)) {
- return NaN;
- }
- var y = this.ToInteger(year);
- var m = this.ToInteger(month);
- var dt = this.ToInteger(date);
- var ym = y + $floor(m / 12);
- var mn = mod(m, 12);
- var t = $DateUTC(ym, mn, 1);
- if (this.YearFromTime(t) !== ym || this.MonthFromTime(t) !== mn || this.DateFromTime(t) !== 1) {
- return NaN;
- }
- return this.Day(t) + dt - 1;
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.13
- MakeDate: function MakeDate(day, time) {
- if (!$isFinite(day) || !$isFinite(time)) {
- return NaN;
- }
- return (day * msPerDay) + time;
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.11
- MakeTime: function MakeTime(hour, min, sec, ms) {
- if (!$isFinite(hour) || !$isFinite(min) || !$isFinite(sec) || !$isFinite(ms)) {
- return NaN;
- }
- var h = this.ToInteger(hour);
- var m = this.ToInteger(min);
- var s = this.ToInteger(sec);
- var milli = this.ToInteger(ms);
- var t = (h * msPerHour) + (m * msPerMinute) + (s * msPerSecond) + milli;
- return t;
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.14
- TimeClip: function TimeClip(time) {
- if (!$isFinite(time) || $abs(time) > 8.64e15) {
- return NaN;
- }
- return $Number(new $Date(this.ToNumber(time)));
- },
-
- // https://ecma-international.org/ecma-262/5.1/#sec-5.2
- modulo: function modulo(x, y) {
- return mod(x, y);
- }
- };
-
- module.exports = ES5;
|