Page MenuHomePhabricator

"TypeError: moment is undefined" when using Echo
Closed, ResolvedPublic

Description

I'm logged in. I go to https://de.wikipedia.org/wiki/Hilfe:Echo and click one of the two notification icons in the top right corner of the screen. In non-debug mode I get:

Exception in module-execute in module moment:
TypeError: moment is undefined
Stack trace:
@https://de.wikipedia.org/w/load.php?debug=false&lang=de&modules=ext.echo.controller%2Cdm%2Clogger%2Cui%7Cext.echo.styles.notifications%7Cext.echo.ui.desktop%7Cmoment%2Coojs-ui-core%2Coojs-ui-widgets%7Coojs-ui-core.styles%7Coojs-ui.styles.icons%2Cicons-alerts%2Cicons-content%2Cicons-interactions%2Cicons-moderation%2Cicons-user%2Cindicators%2Ctextures%7Cschema.EchoInteraction&skin=vector&version=0eatlxh:146:693
@https://de.wikipedia.org/w/load.php?debug=false&lang=de&modules=ext.echo.controller%2Cdm%2Clogger%2Cui%7Cext.echo.styles.notifications%7Cext.echo.ui.desktop%7Cmoment%2Coojs-ui-core%2Coojs-ui-widgets%7Coojs-ui-core.styles%7Coojs-ui.styles.icons%2Cicons-alerts%2Cicons-content%2Cicons-interactions%2Cicons-moderation%2Cicons-user%2Cindicators%2Ctextures%7Cschema.EchoInteraction&skin=vector&version=0eatlxh:146:206
@https://de.wikipedia.org/w/load.php?debug=false&lang=de&modules=ext.echo.controller%2Cdm%2Clogger%2Cui%7Cext.echo.styles.notifications%7Cext.echo.ui.desktop%7Cmoment%2Coojs-ui-core%2Coojs-ui-widgets%7Coojs-ui-core.styles%7Coojs-ui.styles.icons%2Cicons-alerts%2Cicons-content%2Cicons-interactions%2Cicons-moderation%2Cicons-user%2Cindicators%2Ctextures%7Cschema.EchoInteraction&skin=vector&version=0eatlxh:146:31
execute/runScript/<@https://de.wikipedia.org/w/load.php?debug=false&lang=de&modules=jquery%2Cmediawiki&only=scripts&skin=vector&version=07zvr6j:161:274
jQuery.Callbacks/fire@https://de.wikipedia.org/w/load.php?debug=false&lang=de&modules=jquery%2Cmediawiki&only=scripts&skin=vector&version=07zvr6j:45:104
jQuery.Callbacks/self.add@https://de.wikipedia.org/w/load.php?debug=false&lang=de&modules=jquery%2Cmediawiki&only=scripts&skin=vector&version=07zvr6j:45:656
.Deferred/promise.always@https://de.wikipedia.org/w/load.php?debug=false&lang=de&modules=jquery%2Cmediawiki&only=scripts&skin=vector&version=07zvr6j:46:865
execute/runScript@https://de.wikipedia.org/w/load.php?debug=false&lang=de&modules=jquery%2Cmediawiki&only=scripts&skin=vector&version=07zvr6j:161:144
execute/</checkCssHandles@https://de.wikipedia.org/w/load.php?debug=false&lang=de&modules=jquery%2Cmediawiki&only=scripts&skin=vector&version=07zvr6j:161:974
execute@https://de.wikipedia.org/w/load.php?debug=false&lang=de&modules=jquery%2Cmediawiki&only=scripts&skin=vector&version=07zvr6j:162:681
mw.loader.implement@https://de.wikipedia.org/w/load.php?debug=false&lang=de&modules=jquery%2Cmediawiki&only=scripts&skin=vector&version=07zvr6j:168:713
@https://de.wikipedia.org/w/load.php?debug=false&lang=de&modules=ext.echo.controller%2Cdm%2Clogger%2Cui%7Cext.echo.styles.notifications%7Cext.echo.ui.desktop%7Cmoment%2Coojs-ui-core%2Coojs-ui-widgets%7Coojs-ui-core.styles%7Coojs-ui.styles.icons%2Cicons-alerts%2Cicons-content%2Cicons-interactions%2Cicons-moderation%2Cicons-user%2Cindicators%2Ctextures%7Cschema.EchoInteraction&skin=vector&version=0eatlxh:96:239

Same with debug=1:

TypeError: moment is undefined de.js:29:5
<anonymous> de.js:29
<anonymous> de.js:12
<anonymous> de.js:6

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald Transcript

In which browser does this happen? Does it happen in debug mode too? If it does, can you give us a stack trace of that instead?

Never mind, I see the debug mode backtrace now. I was confused by the filename, turns out de.js is the locale file for German.

Catrope triaged this task as Unbreak Now! priority.Sep 12 2016, 4:14 PM

Well, this is an entertaining bug. moment's nodejs-vs-browser detection is broken.

moment/locale/de.js looks like this:

(function (factory) {
    if (typeof define === 'function' && define.amd) {
        define(['moment'], factory); // AMD
    } else if (typeof exports === 'object') {
        module.exports = factory(require('../moment')); // Node
    } else {
        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
    }
}(function (moment) {
    ...
    return moment.defineLocale('de', {
        ...
    });
}));

In a browser, there is no global define function and no global exports object, so we fall through to the third case. So far so good. We now look for the global object and expect it to either be called global, or for it to be this. In a browser, there is no global object called global, and this is the global window object, so we'll choose this and then use this.moment which will be defined, right?

Not so fast. There usually isn't a global variable called global, but on this particular page (Hilfe:Echo) there is a <span id="#global"> tag, so the global variable called global is a reference to this DOM element. This means we try to pass the .moment of an HTMLSpanElement object to the function, and that's undefined and blows things up.

I think the best way to solve this would be to check if what we think is the global object actually has a .moment property before using it, but we'd have to make that change to every single locale file, so I'll first check if upstream has fixed this already.

Change 310060 had a related patch set uploaded (by Catrope):
momentjs: Hack around bug in node/browser compat wrapper in locale files

https://gerrit.wikimedia.org/r/310060

Change 310060 merged by jenkins-bot:
momentjs: Hack around bug in node/browser compat wrapper in locale files

https://gerrit.wikimedia.org/r/310060

Change 310448 had a related patch set uploaded (by Mattflaschen):
momentjs: Hack around bug in node/browser compat wrapper in locale files

https://gerrit.wikimedia.org/r/310448

Change 310449 had a related patch set uploaded (by Mattflaschen):
momentjs: Hack around bug in node/browser compat wrapper in locale files

https://gerrit.wikimedia.org/r/310449

Change 310448 merged by jenkins-bot:
momentjs: Hack around bug in node/browser compat wrapper in locale files

https://gerrit.wikimedia.org/r/310448

Change 310449 merged by jenkins-bot:
momentjs: Hack around bug in node/browser compat wrapper in locale files

https://gerrit.wikimedia.org/r/310449

Mentioned in SAL (#wikimedia-operations) [2016-09-13T23:19:49Z] <catrope@tin> Synchronized php-1.28.0-wmf.19/resources/lib/moment/locale: T145382 (duration: 00m 49s)

Mentioned in SAL (#wikimedia-operations) [2016-09-13T23:32:09Z] <catrope@tin> Synchronized php-1.28.0-wmf.18/resources/lib/moment/locale: T145382 (duration: 00m 47s)

The page Hilfe:Echo allows to click on the notification badges without errors.

resolved? (just checking open UBN!s)

Change 394112 had a related patch set uploaded (by Reedy; owner: Catrope):
[mediawiki/core@REL1_27] momentjs: Hack around bug in node/browser compat wrapper in locale files

https://gerrit.wikimedia.org/r/394112

Change 394112 merged by jenkins-bot:
[mediawiki/core@REL1_27] momentjs: Hack around bug in node/browser compat wrapper in locale files

https://gerrit.wikimedia.org/r/394112

Change 407690 had a related patch set uploaded (by Ejegg; owner: Catrope):
[mediawiki/core@fundraising/REL1_27] momentjs: Hack around bug in node/browser compat wrapper in locale files

https://gerrit.wikimedia.org/r/407690

Change 407690 merged by jenkins-bot:
[mediawiki/core@fundraising/REL1_27] momentjs: Hack around bug in node/browser compat wrapper in locale files

https://gerrit.wikimedia.org/r/407690