From: Alanscut Date: Tue, 16 Jun 2020 07:14:24 +0000 (+0800) Subject: [feature]fix issue #4985 and add method X-Git-Tag: 2.30.0~14^2~1 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=c475ab3706d7aa40fa4a020f09c53cb41598e917;p=thirdparty%2Fmoment.git [feature]fix issue #4985 and add method --- diff --git a/src/lib/create/from-anything.js b/src/lib/create/from-anything.js index 0c5d77236..479349210 100644 --- a/src/lib/create/from-anything.js +++ b/src/lib/create/from-anything.js @@ -17,6 +17,7 @@ import { configFromStringAndFormat } from './from-string-and-format'; import { configFromString } from './from-string'; import { configFromArray } from './from-array'; import { configFromObject } from './from-object'; +import createError from '../utils/create-error'; function createFromConfig(config) { var res = new Moment(checkOverflow(prepareConfig(config))); @@ -83,6 +84,12 @@ function configFromInput(config) { } else { hooks.createFromInputFallback(config); } + createError( + config._i + ' failed to build a Date using `new Date()`', + config._d, + config._i, + config._f + ); } export function createLocalOrUTC(input, format, locale, strict, isUTC) { diff --git a/src/lib/create/from-array.js b/src/lib/create/from-array.js index 610d802da..365e7cd85 100644 --- a/src/lib/create/from-array.js +++ b/src/lib/create/from-array.js @@ -18,6 +18,7 @@ import { import { createLocal } from './local'; import defaults from '../utils/defaults'; import getParsingFlags from './parsing-flags'; +import createError from '../utils/create-error'; function currentDateArray(config) { // hooks is actually the exported moment object @@ -101,6 +102,12 @@ export function configFromArray(config) { null, input ); + createError( + config._i + ' failed to build a Date using `new Date()`', + config._d, + config._i, + config._f + ); expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay(); diff --git a/src/lib/create/from-string-and-array.js b/src/lib/create/from-string-and-array.js index 4e6416742..180201069 100644 --- a/src/lib/create/from-string-and-array.js +++ b/src/lib/create/from-string-and-array.js @@ -3,6 +3,7 @@ import { configFromStringAndFormat } from './from-string-and-format'; import getParsingFlags from './parsing-flags'; import { isValid } from './valid'; import extend from '../utils/extend'; +import createError from '../utils/create-error'; // date from string and array of format strings export function configFromStringAndArray(config) { @@ -18,6 +19,12 @@ export function configFromStringAndArray(config) { if (configfLen === 0) { getParsingFlags(config).invalidFormat = true; config._d = new Date(NaN); + createError( + "Invalid `format`, its length shouldn't be 0", + config._d, + config._i, + config._f + ); return; } diff --git a/src/lib/create/from-string-and-format.js b/src/lib/create/from-string-and-format.js index 82d60d520..063b09459 100644 --- a/src/lib/create/from-string-and-format.js +++ b/src/lib/create/from-string-and-format.js @@ -11,6 +11,7 @@ import checkOverflow from './check-overflow'; import { YEAR, HOUR } from '../units/constants'; import { hooks } from '../utils/hooks'; import getParsingFlags from './parsing-flags'; +import createError from '../utils/create-error'; // constant that refers to the ISO standard hooks.ISO_8601 = function () {}; @@ -23,10 +24,22 @@ export function configFromStringAndFormat(config) { // TODO: Move this to another part of the creation flow to prevent circular deps if (config._f === hooks.ISO_8601) { configFromISO(config); + createError( + config._i + ' does not match the `ISO 8601` standard', + config._d, + config._i, + config._f + ); return; } if (config._f === hooks.RFC_2822) { configFromRFC2822(config); + createError( + config._i + ' does not match the `RFC 2822` standard', + config._d, + config._i, + config._f + ); return; } config._a = []; diff --git a/src/lib/create/from-string.js b/src/lib/create/from-string.js index 58739b9d7..b50e77e61 100644 --- a/src/lib/create/from-string.js +++ b/src/lib/create/from-string.js @@ -5,6 +5,7 @@ import { deprecate } from '../utils/deprecate'; import getParsingFlags from './parsing-flags'; import { defaultLocaleMonthsShort } from '../units/month'; import { defaultLocaleWeekdaysShort } from '../units/day-of-week'; +import createError from '../utils/create-error'; // iso 8601 regex // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00) @@ -223,21 +224,36 @@ export function configFromString(config) { var matched = aspNetJsonRegex.exec(config._i); if (matched !== null) { config._d = new Date(+matched[1]); - return; + return createError( + matched[1] + ' failed to build a Date using `new Date()`', + config._d, + config._i, + config._f + ); } configFromISO(config); if (config._isValid === false) { delete config._isValid; } else { - return; + return createError( + config._i + ' does not match the `ISO 8601` standard', + config._d, + config._i, + config._f + ); } configFromRFC2822(config); if (config._isValid === false) { delete config._isValid; } else { - return; + return createError( + config._i + ' does not match the `RFC 2822` standard', + config._d, + config._i, + config._f + ); } if (config._strict) { @@ -245,6 +261,12 @@ export function configFromString(config) { } else { // Final attempt, use Input Fallback hooks.createFromInputFallback(config); + createError( + config._i + ' failed to build a Date using `new Date()`', + config._d, + config._i, + config._f + ); } } diff --git a/src/lib/moment/constructor.js b/src/lib/moment/constructor.js index b86de8b92..5be63a268 100644 --- a/src/lib/moment/constructor.js +++ b/src/lib/moment/constructor.js @@ -1,6 +1,7 @@ import { hooks } from '../utils/hooks'; import isUndefined from '../utils/is-undefined'; import getParsingFlags from '../create/parsing-flags'; +import createError from '../utils/create-error'; // Plugins that add properties should also add the key here (null value), // so we can properly clone ourselves. @@ -63,6 +64,7 @@ export function Moment(config) { this._d = new Date(config._d != null ? config._d.getTime() : NaN); if (!this.isValid()) { this._d = new Date(NaN); + createError('invalid moment instance', config._d, config._i, config._f); } // Prevent infinite loop in case updateOffset creates new moment // objects. diff --git a/src/lib/utils/create-error.js b/src/lib/utils/create-error.js new file mode 100644 index 000000000..49148c8ae --- /dev/null +++ b/src/lib/utils/create-error.js @@ -0,0 +1,54 @@ +import { hooks } from './hooks'; +import isDate from './is-date'; + +/** + * Update an Error with the specified date, input and format. + * + * @param {*} error The error to update + * @param {*} date The date + * @param {*} input The input + * @param {*} format The format + */ +function enhanceError(error, date, input, format) { + error.date = date; + error.input = input; + error.format = format; + error.toJSON = function toJSON() { + return { + // Standard + message: this.message, + name: this.name, + // Microsoft + description: this.description, + number: this.number, + // Mozilla + fileName: this.fileName, + lineNumber: this.lineNumber, + columnNumber: this.columnNumber, + stack: this.stack, + }; + }; + throw error; +} + +/** + * Create an Error with the specified message, date, input and format. + * + * @param {*} message The error message + * @param {*} date The date + * @param {*} input The input + * @param {*} format The format + */ +export default function createError(message, date, input, format) { + if (hooks.suppressCreateError !== false) { + return; + } + if (isDate(date) && date.toString() !== 'Invalid Date') { + return; + } + var error = new Error(message); + enhanceError(error, date, input, format); +} + +// Specify whether to disable throwing errors, ths default value is `true` +hooks.suppressCreateError = true; diff --git a/src/test/moment/create.js b/src/test/moment/create.js index 288610b2c..b4d46970f 100644 --- a/src/test/moment/create.js +++ b/src/test/moment/create.js @@ -2917,3 +2917,34 @@ test('k, kk', function (assert) { } } }); + +test('Invalid date will throw an error', function (assert) { + var i, + data, + dataList = [ + ['10:32:17 027', null], + ['20202-02-01', moment.ISO_8601], + ['20202-02-01', moment.RFC_2822], + ['20202-02-01', []], + [new Date(NaN), null], + ]; + moment.suppressCreateError = false; + for (i = 0; i < dataList.length; i++) { + data = dataList[i]; + try { + moment(data[0], data[1]); + } catch (error) { + assert.ok( + error instanceof Error, + 'Invalid date returns an instance of Error' + ); + if (error.toJSON) { + assert.ok( + error.toJSON instanceof Function, + 'Error instance contains toJSON method' + ); + } + } + } + moment.suppressCreateError = true; +});