]> git.ipfire.org Git - thirdparty/moment.git/commitdiff
Removing `new Function` for #377
authorTim Wood <washwithcare@gmail.com>
Mon, 20 Aug 2012 18:43:05 +0000 (11:43 -0700)
committerTim Wood <washwithcare@gmail.com>
Mon, 20 Aug 2012 18:43:05 +0000 (11:43 -0700)
moment.js

index 95520c0dd3dabd9533938fc281eb62db1e37e718..a01f043df2b27c6ed5da9bc9405c0035d0819bbf 100644 (file)
--- a/moment.js
+++ b/moment.js
@@ -30,9 +30,8 @@
         aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
 
         // format tokens
-        formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?)/g,
+        formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?|.)/g,
         localFormattingTokens = /(LT|LL?L?L?)/g,
-        formattingRemoveEscapes = /(^\[)|(\\)|\]$/g,
 
         // parsing tokens
         parseMultipleFormatChunker = /([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,
         // format function strings
         formatFunctions = {},
 
+        // tokens to ordinalize and pad
+        ordinalizeTokens = 'DDD w M D d'.split(' '),
+        paddedTokens = 'M D H h m s w'.split(' '),
+
         /*
          * moment.fn.format uses new Function() to create an inlined formatting function.
          * Results are a 3x speed boost
@@ -84,7 +87,7 @@
          *
          * These strings are appended into a function using replaceFormatTokens and makeFormatFunction
          */
-        formatFunctionStrings = {
+        formatTokenFunctions = {
             // a = placeholder
             // b = placeholder
             // t = the current moment being formatted
             // o = language.ordinal function
             // p = leftZeroFill function
             // m = language.meridiem value or function
-            M    : '(a=t.month()+1)',
-            MMM  : 'v("monthsShort",t.month())',
-            MMMM : 'v("months",t.month())',
-            D    : '(a=t.date())',
-            DDD  : '(a=new Date(t.year(),t.month(),t.date()),b=new Date(t.year(),0,1),a=~~(((a-b)/864e5)+1.5))',
-            d    : '(a=t.day())',
-            dd   : 'v("weekdaysMin",t.day())',
-            ddd  : 'v("weekdaysShort",t.day())',
-            dddd : 'v("weekdays",t.day())',
-            w    : '(a=new Date(t.year(),t.month(),t.date()-t.day()+5),b=new Date(a.getFullYear(),0,4),a=~~((a-b)/864e5/7+1.5))',
-            YY   : 'p(t.year()%100,2)',
-            YYYY : 'p(t.year(),4)',
-            a    : 'm(t.hours(),t.minutes(),!0)',
-            A    : 'm(t.hours(),t.minutes(),!1)',
-            H    : 't.hours()',
-            h    : 't.hours()%12||12',
-            m    : 't.minutes()',
-            s    : 't.seconds()',
-            S    : '~~(t.milliseconds()/100)',
-            SS   : 'p(~~(t.milliseconds()/10),2)',
-            SSS  : 'p(t.milliseconds(),3)',
-            Z    : '((a=-t.zone())<0?((a=-a),"-"):"+")+p(~~(a/60),2)+":"+p(~~a%60,2)',
-            ZZ   : '((a=-t.zone())<0?((a=-a),"-"):"+")+p(~~(10*a/6),4)'
-        },
+            M    : function () {
+                return this.month() + 1;
+            },
+            MMM  : function (format) {
+                return getValueFromArray("monthsShort", this.month(), this, format);
+            },
+            MMMM : function (format) {
+                return getValueFromArray("months", this.month(), this, format);
+            },
+            D    : function () {
+                return this.date();
+            },
+            DDD  : function () {
+                var a = new Date(this.year(), this.month(), this.date()),
+                    b = new Date(this.year(), 0, 1);
+                return ~~(((a - b) / 864e5) + 1.5);
+            },
+            d    : function () {
+                return this.day();
+            },
+            dd   : function (format) {
+                return getValueFromArray("weekdaysMin", this.day(), this, format);
+            },
+            ddd  : function (format) {
+                return getValueFromArray("weekdaysShort", this.day(), this, format);
+            },
+            dddd : function (format) {
+                return getValueFromArray("weekdays", this.day(), this, format);
+            },
+            w    : function () {
+                var a = new Date(this.year(), this.month(), this.date() - this.day() + 5),
+                    b = new Date(a.getFullYear(), 0, 4);
+                return ~~((a - b) / 864e5 / 7 + 1.5);
+            },
+            YY   : function () {
+                return leftZeroFill(this.year() % 100, 2);
+            },
+            YYYY : function () {
+                return leftZeroFill(this.year(), 4);
+            },
+            a    : function () {
+                return this.lang().meridiem(this.hours(), this.minutes(), true);
+            },
+            A    : function () {
+                return this.lang().meridiem(this.hours(), this.minutes(), false);
+            },
+            H    : function () {
+                return this.hours();
+            },
+            h    : function () {
+                return this.hours() % 12 || 12;
+            },
+            m    : function () {
+                return this.minutes();
+            },
+            s    : function () {
+                return this.seconds();
+            },
+            S    : function () {
+                return ~~(this.milliseconds() / 100);
+            },
+            SS   : function () {
+                return leftZeroFill(~~(this.milliseconds() / 10), 2);
+            },
+            SSS  : function () {
+                return leftZeroFill(this.milliseconds(), 3);
+            },
+            Z    : function () {
+                var a = -this.zone(),
+                    b = "+";
+                if (a < 0) {
+                    a = -a;
+                    b = "-";
+                }
+                return b + leftZeroFill(~~(a / 60), 2) + ":" + leftZeroFill(~~a % 60, 2);
+            },
+            ZZ   : function () {
+                var a = -this.zone(),
+                    b = "+";
+                if (a < 0) {
+                    a = -a;
+                    b = "-";
+                }
+                return b + leftZeroFill(~~(10 * a / 6), 4);
+            }
+        };
 
-        ordinalizeTokens = 'DDD w M D d'.split(' '),
-        paddedTokens = 'M D H h m s w'.split(' ');
+    function getValueFromArray(key, index, m, format) {
+        var lang = m.lang();
+        return lang[key].call ? lang[key](m, format) : lang[key][index];
+    }
+
+    function padToken(func, count) {
+        return function (a) {
+            return leftZeroFill(func.call(this, a), count);
+        };
+    }
+    function ordinalizeToken(func) {
+        return function (a) {
+            var b = func.call(this, a);
+            return b + this.lang().ordinal(b);
+        };
+    }
 
     while (ordinalizeTokens.length) {
         i = ordinalizeTokens.pop();
-        formatFunctionStrings[i + 'o'] = formatFunctionStrings[i] + '+o(a)';
+        formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i]);
     }
     while (paddedTokens.length) {
         i = paddedTokens.pop();
-        formatFunctionStrings[i + i] = 'p(' + formatFunctionStrings[i] + ',2)';
+        formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
     }
-    formatFunctionStrings.DDDD = 'p(' + formatFunctionStrings.DDD + ',3)';
+    formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
 
 
     /************************************
     ************************************/
 
 
-    // helper for building inline formatting functions
-    function replaceFormatTokens(token) {
-        return formatFunctionStrings[token] ? 
-            ("'+(" + formatFunctionStrings[token] + ")+'") :
-            token.replace(formattingRemoveEscapes, "").replace(/\\?'/g, "\\'");
-    }
-
     // helper for recursing long date formatting tokens
     function replaceLongDateFormatTokens(input) {
         return getLangDefinition().longDateFormat[input] || input;
     }
 
-    function makeFormatFunction(format) {
-        var output = "var a,b;return '" +
-            format.replace(formattingTokens, replaceFormatTokens) + "';",
-            Fn = Function; // get around jshint
-        // t = the current moment being formatted
-        // v = getValueAtKey function
-        // o = language.ordinal function
-        // p = leftZeroFill function
-        // m = language.meridiem value or function
-        return new Fn('t', 'v', 'o', 'p', 'm', output);
+    function removeFormattingTokens(input) {
+        if (input.match(/\[.*\]/)) {
+            return input.replace(/^\[|\]$/g, "");
+        }
+        return input.replace(/\\/g, "");
     }
 
-    function makeOrGetFormatFunction(format) {
-        if (!formatFunctions[format]) {
-            formatFunctions[format] = makeFormatFunction(format);
+    function makeFormatFunction(format) {
+        var array = format.match(formattingTokens), i, length;
+
+        for (i = 0, length = array.length; i < length; i++) {
+            if (formatTokenFunctions[array[i]]) {
+                array[i] = formatTokenFunctions[array[i]];
+            } else {
+                array[i] = removeFormattingTokens(array[i]);
+            }
         }
-        return formatFunctions[format];
+
+        return function (mom) {
+            var output = "";
+            for (i = 0; i < length; i++) {
+                output += typeof array[i].call === 'function' ? array[i].call(mom, format) : array[i];
+            }
+            return output;
+        };
     }
 
     // format date using native date object
     function formatMoment(m, format) {
-        var lang = getLangDefinition(m);
-
-        function getValueFromArray(key, index) {
-            return lang[key].call ? lang[key](m, format) : lang[key][index];
-        }
-
         while (localFormattingTokens.test(format)) {
             format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
         }
             formatFunctions[format] = makeFormatFunction(format);
         }
 
-        return formatFunctions[format](m, getValueFromArray, lang.ordinal, leftZeroFill, lang.meridiem);
+        return formatFunctions[format](m);
     }