Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature] Fix issue #4985 and add createError method #5599

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/lib/create/from-anything.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)));
Expand Down Expand Up @@ -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) {
Expand Down
7 changes: 7 additions & 0 deletions src/lib/create/from-array.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand Down
7 changes: 7 additions & 0 deletions src/lib/create/from-string-and-array.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -17,6 +18,12 @@ export function configFromStringAndArray(config) {
if (config._f.length === 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;
}

Expand Down
13 changes: 13 additions & 0 deletions src/lib/create/from-string-and-format.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 () {};
Expand All @@ -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 = [];
Expand Down
28 changes: 25 additions & 3 deletions src/lib/create/from-string.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -219,28 +220,49 @@ 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) {
config._isValid = false;
} 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
);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/lib/moment/constructor.js
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -60,6 +61,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.
Expand Down
54 changes: 54 additions & 0 deletions src/lib/utils/create-error.js
Original file line number Diff line number Diff line change
@@ -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;
31 changes: 31 additions & 0 deletions src/test/moment/create.js
Original file line number Diff line number Diff line change
Expand Up @@ -2814,3 +2814,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;
});