Page MenuHomePhabricator

newNotifData.bundledNotifications.map is not a function
Closed, ResolvedPublic

Description

I got a JS error on MediaWiki.org when opening my Notices (Mattflaschen-WMF account):

18:05:50.724 TypeError: newNotifData.bundledNotifications.map is not a function
mw.echo.Controller.prototype.fetchLocalNotifications/<() load.php:6
.Deferred/promise.then/</</<() load.php:47
jQuery.Callbacks/fire() load.php:45
jQuery.Callbacks/self.fireWith() load.php:46
.Deferred/promise.then/</</<() load.php:47
jQuery.Callbacks/fire() load.php:45
jQuery.Callbacks/self.fireWith() load.php:46
.Deferred/</deferred[tuple[0]]() load.php:47
mw.echo.api.PromisePrioritizer.prototype.setSuccess/<() load.php:37
jQuery.Callbacks/fire() load.php:45
jQuery.Callbacks/self.fireWith() load.php:46
.Deferred/</deferred[tuple[0]]() load.php:47
mw.Api.prototype.ajax/xhr<() load.php:112
jQuery.Callbacks/fire() load.php:45
jQuery.Callbacks/self.fireWith() load.php:46
done() load.php:135
.send/callback() load.php:141
1 load.php:6:648

(It failed to finish loading the flyout.)

Weirdly, it worked when I retried in debug mode, and then after that.

Event Timeline

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

Change 311050 had a related patch set uploaded (by Mooeypoo):
Verify bundledNotifications data is an array before running .map()

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

So I can't immediately reproduce this, but I think it might be a good idea to add a defensive check to this operation anyways; bundledNotifications is data we get from the API -- if something goes wrong and it is not an array, it will crash when we run .map() on it. We should verify it's an array first.

We should also try and figure out why that would ever happen in the API side, but the defensive condition is a good idea in any case.

On the PHP side, we are outputting bundledNotifications in DataOutputFormatter->formatOutput on line #145.

Could it have been that array_filter had some edge case that produced a result that was not an array?

I had a suspicion that it was an empty array with something like T12887: API JSON formatter returns [] as an empty return value - inconsistent with {} for non-empty values, which I've seen before (but I guess the reverse).

But I tried faking it to be the empty array on the server, and I can't reproduce (it just gives []).

I think you need array_values( array_filter( $arr ) ). If you have, say, $a = array( 0 => 'foo', 1 => null, 2 => 'bar' ) then array_filter( $a ) will drop $a[1] and return array( 0 => 'foo', 2 => 'bar' ). The JSON encoder will then see that this is an array whose indices are not consecutive integers, and so it'll treat it as an associative array (i.e. an object) and serialize it as {0: 'foo', 2: 'bar'}.

Change 311050 merged by jenkins-bot:
Make sure bundledNotifications is an array

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

Checked in betalabs - general regression testing was done after the fix - no problems/issues have been found.