/**
* @param ResourceLoaderContext $context
* @param array $options [optional] Array of options
- * - 'target': Custom parameter passed to StartupModule.
+ * - 'target': Parameter for modules=startup request, see ResourceLoaderStartUpModule.
+ * - 'safemode': Parameter for modules=startup request, see ResourceLoaderStartUpModule.
+ * - 'nonce': From OutputPage::getCSPNonce().
*/
public function __construct( ResourceLoaderContext $context, array $options = [] ) {
$this->context = $context;
$this->resourceLoader = $context->getResourceLoader();
- $this->options = $options;
+ $this->options = $options + [
+ 'target' => null,
+ 'safemode' => null,
+ 'nonce' => null,
+ ];
}
/**
'styles' => [],
'general' => [],
],
-
+ // Deprecations for style-only modules
+ 'styledeprecations' => [],
];
foreach ( $this->modules as $name ) {
$data['styles'][] = $name;
}
}
+ $deprecation = $module->getDeprecationInformation();
+ if ( $deprecation ) {
+ $data['styledeprecations'][] = $deprecation;
+ }
}
foreach ( $this->moduleScripts as $name ) {
* @return string|WrappedStringList HTML
*/
public function getHeadHtml() {
+ $nonce = $this->options['nonce'];
$data = $this->getData();
$chunks = [];
// See also #getDocumentAttributes() and /resources/src/startup.js.
$chunks[] = Html::inlineScript(
'document.documentElement.className = document.documentElement.className'
- . '.replace( /(^|\s)client-nojs(\s|$)/, "$1client-js$2" );'
+ . '.replace( /(^|\s)client-nojs(\s|$)/, "$1client-js$2" );',
+ $nonce
);
// Inline RLQ: Set page variables
if ( $this->config ) {
$chunks[] = ResourceLoader::makeInlineScript(
- ResourceLoader::makeConfigSetScript( $this->config )
+ ResourceLoader::makeConfigSetScript( $this->config ),
+ $nonce
);
}
$states = array_merge( $this->exemptStates, $data['states'] );
if ( $states ) {
$chunks[] = ResourceLoader::makeInlineScript(
- ResourceLoader::makeLoaderStateScript( $states )
+ ResourceLoader::makeLoaderStateScript( $states ),
+ $nonce
);
}
if ( $data['embed']['general'] ) {
$chunks[] = $this->getLoad(
$data['embed']['general'],
- ResourceLoaderModule::TYPE_COMBINED
+ ResourceLoaderModule::TYPE_COMBINED,
+ $nonce
);
}
// Inline RLQ: Load general modules
if ( $data['general'] ) {
$chunks[] = ResourceLoader::makeInlineScript(
- Xml::encodeJsCall( 'mw.loader.load', [ $data['general'] ] )
+ Xml::encodeJsCall( 'mw.loader.load', [ $data['general'] ] ),
+ $nonce
);
}
if ( $data['scripts'] ) {
$chunks[] = $this->getLoad(
$data['scripts'],
- ResourceLoaderModule::TYPE_SCRIPTS
+ ResourceLoaderModule::TYPE_SCRIPTS,
+ $nonce
);
}
- // External stylesheets
+ // Deprecations for only=styles modules
+ if ( $data['styledeprecations'] ) {
+ $chunks[] = ResourceLoader::makeInlineScript(
+ implode( '', $data['styledeprecations'] ),
+ $nonce
+ );
+ }
+
+ // External stylesheets (only=styles)
if ( $data['styles'] ) {
$chunks[] = $this->getLoad(
$data['styles'],
- ResourceLoaderModule::TYPE_STYLES
+ ResourceLoaderModule::TYPE_STYLES,
+ $nonce
);
}
if ( $data['embed']['styles'] ) {
$chunks[] = $this->getLoad(
$data['embed']['styles'],
- ResourceLoaderModule::TYPE_STYLES
+ ResourceLoaderModule::TYPE_STYLES,
+ $nonce
);
}
// Async scripts. Once the startup is loaded, inline RLQ scripts will run.
// Pass-through a custom 'target' from OutputPage (T143066).
- $startupQuery = isset( $this->options['target'] )
- ? [ 'target' => (string)$this->options['target'] ]
- : [];
+ $startupQuery = [];
+ foreach ( [ 'target', 'safemode' ] as $param ) {
+ if ( $this->options[$param] !== null ) {
+ $startupQuery[$param] = (string)$this->options[$param];
+ }
+ }
$chunks[] = $this->getLoad(
'startup',
ResourceLoaderModule::TYPE_SCRIPTS,
+ $nonce,
$startupQuery
);
return self::makeContext( $this->context, $group, $type );
}
- private function getLoad( $modules, $only, array $extraQuery = [] ) {
- return self::makeLoad( $this->context, (array)$modules, $only, $extraQuery );
+ private function getLoad( $modules, $only, $nonce, array $extraQuery = [] ) {
+ return self::makeLoad( $this->context, (array)$modules, $only, $extraQuery, $nonce );
}
private static function makeContext( ResourceLoaderContext $mainContext, $group, $type,
}
$context = new ResourceLoaderContext( $mainContext->getResourceLoader(), $req );
// Allow caller to setVersion() and setModules()
- return new DerivativeResourceLoaderContext( $context );
+ $ret = new DerivativeResourceLoaderContext( $context );
+ $ret->setContentOverrideCallback( $mainContext->getContentOverrideCallback() );
+ return $ret;
}
/**
* @param array $modules One or more module names
* @param string $only ResourceLoaderModule TYPE_ class constant
* @param array $extraQuery [optional] Array with extra query parameters for the request
+ * @param string $nonce [optional] Content-Security-Policy nonce (from OutputPage::getCSPNonce)
* @return string|WrappedStringList HTML
*/
public static function makeLoad( ResourceLoaderContext $mainContext, array $modules, $only,
- array $extraQuery = []
+ array $extraQuery = [], $nonce = null
) {
$rl = $mainContext->getResourceLoader();
$chunks = [];
$chunks = [];
// Recursively call us for every item
foreach ( $modules as $name ) {
- $chunks[] = self::makeLoad( $mainContext, [ $name ], $only, $extraQuery );
+ $chunks[] = self::makeLoad( $mainContext, [ $name ], $only, $extraQuery, $nonce );
}
return new WrappedStringList( "\n", $chunks );
}
);
} else {
$chunks[] = ResourceLoader::makeInlineScript(
- $rl->makeModuleResponse( $context, $moduleSet )
+ $rl->makeModuleResponse( $context, $moduleSet ),
+ $nonce
);
}
} else {
] );
} else {
$chunk = ResourceLoader::makeInlineScript(
- Xml::encodeJsCall( 'mw.loader.load', [ $url ] )
+ Xml::encodeJsCall( 'mw.loader.load', [ $url ] ),
+ $nonce
);
}
}