From: Lucas Sanders Date: Sun, 30 Oct 2016 18:27:54 +0000 (-0400) Subject: Implement Moment, Duration, and Locale prototypes with immutable API X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=40b47fd62b5a7c87fdfb3255df49959ea51e0d1d;p=thirdparty%2Fmoment.git Implement Moment, Duration, and Locale prototypes with immutable API This is done by wrapping all mutation methods with a function that clones a new object before the mutation algorithm. --- diff --git a/src/lib/duration/prototype.js b/src/lib/duration/prototype.js index d923375cb..3fd516a56 100644 --- a/src/lib/duration/prototype.js +++ b/src/lib/duration/prototype.js @@ -1,4 +1,5 @@ import { Duration } from './constructor'; +import wrap from '../utils/wrap'; var proto = Duration.prototype; @@ -14,8 +15,8 @@ import { isValid } from './valid'; proto.isValid = isValid; proto.abs = abs; -proto.add = add; -proto.subtract = subtract; +proto.add = wrap(Duration, add); +proto.subtract = wrap(Duration, subtract); proto.as = as; proto.asMilliseconds = asMilliseconds; proto.asSeconds = asSeconds; @@ -40,11 +41,11 @@ proto.humanize = humanize; proto.toISOString = toISOString; proto.toString = toISOString; proto.toJSON = toISOString; -proto.locale = locale; +proto.locale = wrap(Duration, locale, true); proto.localeData = localeData; // Deprecations import { deprecate } from '../utils/deprecate'; proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString); -proto.lang = lang; +proto.lang = deprecate('duration.lang() is deprecated. Use locale() or localeData() instead.', wrap(Duration, lang)); diff --git a/src/lib/locale/constructor.js b/src/lib/locale/constructor.js index c32b73ee1..dfaaed2a3 100644 --- a/src/lib/locale/constructor.js +++ b/src/lib/locale/constructor.js @@ -1,5 +1,7 @@ +import { set } from './set'; + export function Locale(config) { if (config != null) { - this.set(config); + set.call(this, config); } } diff --git a/src/lib/locale/prototype.js b/src/lib/locale/prototype.js index 24eef89f1..5be98757f 100644 --- a/src/lib/locale/prototype.js +++ b/src/lib/locale/prototype.js @@ -9,6 +9,7 @@ import { ordinal } from './ordinal'; import { preParsePostFormat } from './pre-post-format'; import { relativeTime, pastFuture } from './relative'; import { set } from './set'; +import wrap from '../utils/wrap'; proto.calendar = calendar; proto.longDateFormat = longDateFormat; @@ -18,7 +19,7 @@ proto.preparse = preParsePostFormat; proto.postformat = preParsePostFormat; proto.relativeTime = relativeTime; proto.pastFuture = pastFuture; -proto.set = set; +proto.set = wrap(Locale, set); // Month import { @@ -29,9 +30,9 @@ import { monthsShortRegex } from '../units/month'; -proto.months = localeMonths; -proto.monthsShort = localeMonthsShort; -proto.monthsParse = localeMonthsParse; +proto.months = localeMonths; +proto.monthsShort = localeMonthsShort; +proto.monthsParse = localeMonthsParse; proto.monthsRegex = monthsRegex; proto.monthsShortRegex = monthsShortRegex; @@ -53,14 +54,14 @@ import { weekdaysMinRegex } from '../units/day-of-week'; -proto.weekdays = localeWeekdays; -proto.weekdaysMin = localeWeekdaysMin; -proto.weekdaysShort = localeWeekdaysShort; -proto.weekdaysParse = localeWeekdaysParse; +proto.weekdays = localeWeekdays; +proto.weekdaysMin = localeWeekdaysMin; +proto.weekdaysShort = localeWeekdaysShort; +proto.weekdaysParse = localeWeekdaysParse; -proto.weekdaysRegex = weekdaysRegex; -proto.weekdaysShortRegex = weekdaysShortRegex; -proto.weekdaysMinRegex = weekdaysMinRegex; +proto.weekdaysRegex = weekdaysRegex; +proto.weekdaysShortRegex = weekdaysShortRegex; +proto.weekdaysMinRegex = weekdaysMinRegex; // Hours import { localeIsPM, localeMeridiem } from '../units/hour'; diff --git a/src/lib/moment/locale.js b/src/lib/moment/locale.js index fb46e6569..27d8ab036 100644 --- a/src/lib/moment/locale.js +++ b/src/lib/moment/locale.js @@ -18,16 +18,13 @@ export function locale (key) { } } -export var lang = deprecate( - 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', - function (key) { - if (key === undefined) { - return this.localeData(); - } else { - return this.locale(key); - } +export function lang (key) { + if (key === undefined) { + return this.localeData(); + } else { + return this.locale(key); } -); +} export function localeData () { return this._locale; diff --git a/src/lib/moment/prototype.js b/src/lib/moment/prototype.js index bd8fff79c..dab62143f 100644 --- a/src/lib/moment/prototype.js +++ b/src/lib/moment/prototype.js @@ -1,4 +1,5 @@ import { Moment } from './constructor'; +import wrap from '../utils/wrap'; var proto = Moment.prototype; @@ -18,96 +19,92 @@ import { valueOf, toDate, toArray, toObject, toJSON, unix } from './to-type'; import { isValid, parsingFlags, invalidAt } from './valid'; import { creationData } from './creation-data'; -proto.add = add; -proto.calendar = calendar; -proto.clone = clone; -proto.diff = diff; -proto.endOf = endOf; -proto.format = format; -proto.from = from; -proto.fromNow = fromNow; -proto.to = to; -proto.toNow = toNow; -proto.get = stringGet; -proto.invalidAt = invalidAt; -proto.isAfter = isAfter; -proto.isBefore = isBefore; -proto.isBetween = isBetween; -proto.isSame = isSame; -proto.isSameOrAfter = isSameOrAfter; -proto.isSameOrBefore = isSameOrBefore; -proto.isValid = isValid; -proto.lang = lang; -proto.locale = locale; -proto.localeData = localeData; -proto.max = prototypeMax; -proto.min = prototypeMin; -proto.parsingFlags = parsingFlags; -proto.set = stringSet; -proto.startOf = startOf; -proto.subtract = subtract; -proto.toArray = toArray; -proto.toObject = toObject; -proto.toDate = toDate; -proto.toISOString = toISOString; -proto.inspect = inspect; -proto.toJSON = toJSON; -proto.toString = toString; -proto.unix = unix; -proto.valueOf = valueOf; -proto.creationData = creationData; +proto.add = wrap(Moment, add); +proto.calendar = calendar; +proto.diff = diff; +proto.endOf = wrap(Moment, endOf); +proto.format = format; +proto.from = from; +proto.fromNow = fromNow; +proto.to = to; +proto.toNow = toNow; +proto.get = stringGet; +proto.invalidAt = invalidAt; +proto.isAfter = isAfter; +proto.isBefore = isBefore; +proto.isBetween = isBetween; +proto.isSame = isSame; +proto.isSameOrAfter = isSameOrAfter; +proto.isSameOrBefore = isSameOrBefore; +proto.isValid = isValid; +proto.locale = wrap(Moment, locale); +proto.localeData = localeData; +proto.parsingFlags = parsingFlags; +proto.set = wrap(Moment, stringSet); +proto.startOf = wrap(Moment, startOf); +proto.subtract = wrap(Moment, subtract); +proto.toArray = toArray; +proto.toObject = toObject; +proto.toDate = toDate; +proto.toISOString = toISOString; +proto.inspect = inspect; +proto.toJSON = toJSON; +proto.toString = toString; +proto.unix = unix; +proto.valueOf = valueOf; +proto.creationData = creationData; // Year import { getSetYear, getIsLeapYear } from '../units/year'; -proto.year = getSetYear; +proto.year = wrap(Moment, getSetYear, true); proto.isLeapYear = getIsLeapYear; // Week Year import { getSetWeekYear, getSetISOWeekYear, getWeeksInYear, getISOWeeksInYear } from '../units/week-year'; -proto.weekYear = getSetWeekYear; -proto.isoWeekYear = getSetISOWeekYear; +proto.weekYear = wrap(Moment, getSetWeekYear, true); +proto.isoWeekYear = wrap(Moment, getSetISOWeekYear, true); // Quarter import { getSetQuarter } from '../units/quarter'; -proto.quarter = proto.quarters = getSetQuarter; +proto.quarter = proto.quarters = wrap(Moment, getSetQuarter, true); // Month import { getSetMonth, getDaysInMonth } from '../units/month'; -proto.month = getSetMonth; +proto.month = wrap(Moment, getSetMonth, true); proto.daysInMonth = getDaysInMonth; // Week import { getSetWeek, getSetISOWeek } from '../units/week'; -proto.week = proto.weeks = getSetWeek; -proto.isoWeek = proto.isoWeeks = getSetISOWeek; -proto.weeksInYear = getWeeksInYear; -proto.isoWeeksInYear = getISOWeeksInYear; +proto.week = proto.weeks = wrap(Moment, getSetWeek, true); +proto.isoWeek = proto.isoWeeks = wrap(Moment, getSetISOWeek, true); +proto.weeksInYear = getWeeksInYear; +proto.isoWeeksInYear = getISOWeeksInYear; // Day import { getSetDayOfMonth } from '../units/day-of-month'; import { getSetDayOfWeek, getSetISODayOfWeek, getSetLocaleDayOfWeek } from '../units/day-of-week'; import { getSetDayOfYear } from '../units/day-of-year'; -proto.date = getSetDayOfMonth; -proto.day = proto.days = getSetDayOfWeek; -proto.weekday = getSetLocaleDayOfWeek; -proto.isoWeekday = getSetISODayOfWeek; -proto.dayOfYear = getSetDayOfYear; +proto.date = wrap(Moment, getSetDayOfMonth, true); +proto.day = proto.days = wrap(Moment, getSetDayOfWeek, true); +proto.weekday = wrap(Moment, getSetLocaleDayOfWeek, true); +proto.isoWeekday = wrap(Moment, getSetISODayOfWeek, true); +proto.dayOfYear = wrap(Moment, getSetDayOfYear, true); // Hour import { getSetHour } from '../units/hour'; -proto.hour = proto.hours = getSetHour; +proto.hour = proto.hours = wrap(Moment, getSetHour, true); // Minute import { getSetMinute } from '../units/minute'; -proto.minute = proto.minutes = getSetMinute; +proto.minute = proto.minutes = wrap(Moment, getSetMinute, true); // Second import { getSetSecond } from '../units/second'; -proto.second = proto.seconds = getSetSecond; +proto.second = proto.seconds = wrap(Moment, getSetSecond, true); // Millisecond import { getSetMillisecond } from '../units/millisecond'; -proto.millisecond = proto.milliseconds = getSetMillisecond; +proto.millisecond = proto.milliseconds = wrap(Moment, getSetMillisecond, true); // Offset import { @@ -123,10 +120,10 @@ import { isUtcOffset, isUtc } from '../units/offset'; -proto.utcOffset = getSetOffset; -proto.utc = setOffsetToUTC; -proto.local = setOffsetToLocal; -proto.parseZone = setOffsetToParsedOffset; +proto.utcOffset = wrap(Moment, getSetOffset, true); +proto.utc = wrap(Moment, setOffsetToUTC); +proto.local = wrap(Moment, setOffsetToLocal); +proto.parseZone = wrap(Moment, setOffsetToParsedOffset); proto.hasAlignedHourOffset = hasAlignedHourOffset; proto.isDST = isDaylightSavingTime; proto.isLocal = isLocal; @@ -141,10 +138,32 @@ proto.zoneName = getZoneName; // Deprecations import { deprecate } from '../utils/deprecate'; -proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth); -proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth); -proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear); -proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone); -proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted); +proto.clone = deprecate( + 'clone does nothing in Moment v3.x because the API is now immutable. Use moment(instance) to make a copy.', + function clone() { return this; }); +proto.dates = deprecate( + 'dates accessor is deprecated. Use date instead.', + wrap(Moment, getSetDayOfMonth, true)); +proto.lang = deprecate( + 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', + wrap(Moment, lang)); +proto.max = deprecate( + 'moment().max() is deprecated. Use moment.min() instead (notice lack of parentheses).', + prototypeMax); +proto.min = deprecate( + 'moment().min() is deprecated. Use moment.max() instead (notice lack of parentheses).', + prototypeMin); +proto.months = deprecate( + 'months accessor is deprecated. Use month instead', + wrap(Moment, getSetMonth, true)); +proto.years = deprecate( + 'years accessor is deprecated. Use year instead', + wrap(Moment, getSetYear, true)); +proto.zone = deprecate( + 'moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', + wrap(Moment, getSetZone, true)); +proto.isDSTShifted = deprecate( + 'isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', + isDaylightSavingTimeShifted); export default proto; diff --git a/src/lib/utils/wrap.js b/src/lib/utils/wrap.js new file mode 100644 index 000000000..0bbdb3712 --- /dev/null +++ b/src/lib/utils/wrap.js @@ -0,0 +1,11 @@ +export default function wrap(Type, fn, dontCloneWithNoArgs) { + return function() { + var m; + if (dontCloneWithNoArgs && !arguments.length) { + m = this; + } else { + m = new Type(this); + } + return fn.apply(m, arguments); + }; +} diff --git a/src/moment.js b/src/moment.js index 4d5f3be7e..d810e2a6a 100644 --- a/src/moment.js +++ b/src/moment.js @@ -74,7 +74,7 @@ moment.updateLocale = updateLocale; moment.locales = locales; moment.weekdaysShort = weekdaysShort; moment.normalizeUnits = normalizeUnits; -moment.relativeTimeRounding = relativeTimeRounding; +moment.relativeTimeRounding = relativeTimeRounding; moment.relativeTimeThreshold = relativeTimeThreshold; moment.calendarFormat = getCalendarFormat; moment.prototype = fn;