Permalink
Browse files

Merge pull request #1417 from ichernev/bugfix/cloning-weird-moments

Handle wrongly cloned moments
  • Loading branch information...
2 parents 90de2d3 + 8ac98ec commit b0a23c9b80ac14db73ce669eeab635de54b6b3e0 @icambron icambron committed Jan 14, 2014
Showing with 79 additions and 26 deletions.
  1. +51 −24 moment.js
  2. +17 −0 test/moment/create.js
  3. +11 −2 test/moment/is_moment.js
View
@@ -27,6 +27,19 @@
// internal storage for language config files
languages = {},
+ // moment internal properties
+ momentProperties = {
+ _isAMomentObject: null,
+ _i : null,
+ _f : null,
+ _l : null,
+ _strict : null,
+ _isUTC : null,
+ _offset : null, // optional. Combine with _isUTC
+ _pf : null,
+ _lang : null // optional
+ },
+
// check for nodeJS
hasModule = (typeof module !== 'undefined' && module.exports && typeof require !== 'undefined'),
@@ -265,6 +278,23 @@
lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'];
+ function defaultParsingFlags() {
+ // We need to deep clone this object, and es5 standard is not very
+ // helpful.
+ return {
+ empty : false,
+ unusedTokens : [],
+ unusedInput : [],
+ overflow : -2,
+ charsLeftOver : 0,
+ nullInput : false,
+ invalidMonth : null,
+ invalidFormat : false,
+ userInvalidated : false,
+ iso: false
+ };
+ }
+
function padToken(func, count) {
return function (a) {
return leftZeroFill(func.call(this, a), count);
@@ -356,6 +386,17 @@
return a;
}
+ function cloneMoment(m) {
+ var result = {}, i;
+ for (i in m) {
+ if (m.hasOwnProperty(i) && momentProperties.hasOwnProperty(i)) {
+ result[i] = m[i];
+ }
+ }
+
+ return result;
+ }
+
function absRound(number) {
if (number < 0) {
return Math.ceil(number);
@@ -547,21 +588,6 @@
}
}
- function initializeParsingFlags(config) {
- config._pf = {
- empty : false,
- unusedTokens : [],
- unusedInput : [],
- overflow : -2,
- charsLeftOver : 0,
- nullInput : false,
- invalidMonth : null,
- invalidFormat : false,
- userInvalidated : false,
- iso: false
- };
- }
-
function isValid(m) {
if (m._isValid == null) {
m._isValid = !isNaN(m._d.getTime()) &&
@@ -1316,7 +1342,7 @@
for (i = 0; i < config._f.length; i++) {
currentScore = 0;
tempConfig = extend({}, config);
- initializeParsingFlags(tempConfig);
+ tempConfig._pf = defaultParsingFlags();
tempConfig._f = config._f[i];
makeDateFromStringAndFormat(tempConfig);
@@ -1517,10 +1543,6 @@
var input = config._i,
format = config._f;
- if (typeof config._pf === 'undefined') {
- initializeParsingFlags(config);
- }
-
if (input === null) {
return moment.invalid({nullInput: true});
}
@@ -1530,7 +1552,7 @@
}
if (moment.isMoment(input)) {
- config = extend({}, input);
+ config = cloneMoment(input);
config._d = new Date(+input._d);
} else if (format) {
@@ -1552,11 +1574,13 @@
lang = undefined;
}
return makeMoment({
+ _isAMomentObject: true,
_i : input,
_f : format,
_l : lang,
_strict : strict,
- _isUTC : false
+ _isUTC : false,
+ _pf : defaultParsingFlags()
});
};
@@ -1569,12 +1593,14 @@
lang = undefined;
}
m = makeMoment({
+ _isAMomentObject: true,
_useUTC : true,
_isUTC : true,
_l : lang,
_i : input,
_f : format,
- _strict : strict
+ _strict : strict,
+ _pf : defaultParsingFlags()
}).utc();
return m;
@@ -1687,7 +1713,8 @@
// compare moment object
moment.isMoment = function (obj) {
- return obj instanceof Moment;
+ return obj instanceof Moment ||
+ (obj != null && obj.hasOwnProperty('_isAMomentObject'));
};
// for typechecking Duration objects
View
@@ -105,6 +105,23 @@ exports.create = {
test.done();
},
+ "cloning moment works with weird clones" : function (test) {
+ var extend = function (a, b) {
+ var i;
+ for (i in b) {
+ a[i] = b[i];
+ }
+ return a;
+ },
+ now = moment(),
+ nowu = moment.utc();
+
+ test.expect(2);
+ test.equal(+extend({}, now).clone(), +now, "cloning extend-ed now is now");
+ test.equal(+extend({}, nowu).clone(), +nowu, "cloning extend-ed utc now is utc now");
+ test.done();
+ },
+
"undefined" : function (test) {
test.expect(1);
test.ok(moment().toDate() instanceof Date, "undefined");
View
@@ -2,15 +2,24 @@ var moment = require('../../moment');
exports.is_moment = {
"is moment object": function (test) {
- test.expect(11);
+ test.expect(13);
- var MyObj = function () {};
+ var MyObj = function () {},
+ extend = function (a, b) {
+ var i;
+ for (i in b) {
+ a[i] = b[i];
+ }
+ return a;
+ };
MyObj.prototype.toDate = function () {
return new Date();
};
test.ok(moment.isMoment(moment()), 'simple moment object');
test.ok(moment.isMoment(moment('invalid date')), 'invalid moment object');
+ test.ok(moment.isMoment(extend({}, moment())), 'externally cloned moments are moments');
+ test.ok(moment.isMoment(extend({}, moment.utc())), 'externally cloned utc moments are moments');
test.ok(!moment.isMoment(new MyObj()), 'myObj is not moment object');
test.ok(!moment.isMoment(moment), 'moment function is not moment object');

0 comments on commit b0a23c9

Please sign in to comment.