RCFilters: Export i18n messages as a config var instead of inline script
authorRoan Kattouw <roan.kattouw@gmail.com>
Thu, 9 Aug 2018 01:31:04 +0000 (18:31 -0700)
committerRoan Kattouw <roan.kattouw@gmail.com>
Thu, 9 Aug 2018 01:31:04 +0000 (18:31 -0700)
We used to generate an inline script tag with an mw.messages.set(...)
call to export these i18n messages, but there are no guarantees that
this script tag will run before mw.rcfilters.init does and tries to
access these messages. This race condition doesn't seem to be happening
in practice right now, but dec800968eb makes it more probable.

Instead, export the messages object as a config var in mw.config, and
import it into mw.messages at the start of mw.rcfilters.init. This just
moves the blob from one inline script tag to another, but mw.config is
guaranteed to be populated before any modules execute.

Longer term, we should move these messages, as well as the filter
definitions, to a ResourceLoader module rather than embedding them in
every page view. I filed T201574 for that.

Bug: T192623
Change-Id: I2d58f55701b28876a6491432cee0fc56f97ff00b

includes/specialpage/ChangesListSpecialPage.php
resources/src/mediawiki.rcfilters/mw.rcfilters.init.js

index 58944b4..caa039b 100644 (file)
@@ -780,26 +780,20 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                $out = $this->getOutput();
                if ( $this->isStructuredFilterUiEnabled() && !$this->including() ) {
                        $jsData = $this->getStructuredFilterJsData();
-
                        $messages = [];
                        foreach ( $jsData['messageKeys'] as $key ) {
                                $messages[$key] = $this->msg( $key )->plain();
                        }
-                       $out->addBodyClasses( 'mw-rcfilters-enabled' );
 
+                       $out->addBodyClasses( 'mw-rcfilters-enabled' );
                        $collapsed = $this->getUser()->getBoolOption( static::$collapsedPreferenceName );
                        if ( $collapsed ) {
                                $out->addBodyClasses( 'mw-rcfilters-collapsed' );
                        }
 
-                       $out->addHTML(
-                               ResourceLoader::makeInlineScript(
-                                       ResourceLoader::makeMessageSetScript( $messages ),
-                                       $out->getCSPNonce()
-                               )
-                       );
-
+                       // These config and message exports should be moved into a ResourceLoader data module (T201574)
                        $out->addJsConfigVars( 'wgStructuredChangeFilters', $jsData['groups'] );
+                       $out->addJsConfigVars( 'wgStructuredChangeFiltersMessages', $messages );
                        $out->addJsConfigVars( 'wgStructuredChangeFiltersCollapsedState', $collapsed );
 
                        $out->addJsConfigVars(
index c918df8..9724927 100644 (file)
                }
        };
 
+       // Import i18n messages from config
+       mw.messages.set( mw.config.get( 'wgStructuredChangeFiltersMessages' ) );
+
        // Early execute of init
        if ( document.readyState === 'interactive' || document.readyState === 'complete' ) {
                rcfilters.init();