jetpack
/
jetpack_vendor
/
automattic
/
jetpack-wp-build-polyfills
/
wp-data-keyed-reducer-loader.js
build
3 weeks ago
src
3 weeks ago
CHANGELOG.md
3 weeks ago
wp-data-keyed-reducer-loader.js
3 months ago
wp-data-keyed-reducer-loader.js
62 lines
| 1 | /** |
| 2 | * Webpack loader that rewrites the `keyedReducer` named import of |
| 3 | * `@wordpress/data` to a local copy bundled with the polyfill. |
| 4 | * |
| 5 | * `@wordpress/notices` >= 5.45.0 imports `keyedReducer` from `@wordpress/data` |
| 6 | * (consolidated upstream in `@wordpress/data` 10.45.0; see |
| 7 | * WordPress/gutenberg#77364). The polyfill externalizes `@wordpress/data` to |
| 8 | * the runtime `window.wp.data` global so the notices store registers in the |
| 9 | * shared registry. On sites that still ship an older `@wordpress/data` |
| 10 | * (current WordPress Core), `window.wp.data.keyedReducer` is `undefined` and |
| 11 | * the bundle throws at load time. |
| 12 | * |
| 13 | * This loader leaves every other `@wordpress/data` named import untouched so |
| 14 | * those continue to be resolved against the runtime global. The DEP plugin's |
| 15 | * `externals` callback runs before module resolution, which means a |
| 16 | * `Rule.resolve.alias` mapping for `@wordpress/data` is bypassed for the |
| 17 | * externalized request. Rewriting the import in source — before webpack sees |
| 18 | * the request — is the only path that survives the externals pipeline. |
| 19 | */ |
| 20 | |
| 21 | /* global __dirname */ |
| 22 | |
| 23 | const path = require( 'path' ); |
| 24 | |
| 25 | const LOCAL_PATH = path.resolve( __dirname, 'src/internal/keyed-reducer.js' ); |
| 26 | |
| 27 | /** |
| 28 | * Rewrites `import { keyedReducer } from '@wordpress/data'` (alone or |
| 29 | * combined with other named imports) so `keyedReducer` resolves to the local |
| 30 | * shim while every other name continues to resolve to `@wordpress/data`. |
| 31 | * |
| 32 | * Bails out without changes when the import does not include `keyedReducer` |
| 33 | * or when the import shape isn't a simple named-imports list (we don't try to |
| 34 | * be clever about renames or namespace imports — there are none in the |
| 35 | * affected upstream files, and a loud miss is preferable to a quiet rewrite). |
| 36 | * |
| 37 | * @param {string} source - Source code of the matched module. |
| 38 | * @return {string} Rewritten source. |
| 39 | */ |
| 40 | module.exports = function wpDataKeyedReducerLoader( source ) { |
| 41 | const importRegex = /import\s*\{\s*([^}]+?)\s*\}\s*from\s*(['"])@wordpress\/data\2\s*;?/g; |
| 42 | const localImport = `import { keyedReducer } from ${ JSON.stringify( LOCAL_PATH ) };`; |
| 43 | |
| 44 | return source.replace( importRegex, ( match, namedList, quote ) => { |
| 45 | const names = namedList |
| 46 | .split( ',' ) |
| 47 | .map( n => n.trim() ) |
| 48 | .filter( Boolean ); |
| 49 | if ( ! names.includes( 'keyedReducer' ) ) { |
| 50 | return match; |
| 51 | } |
| 52 | const remaining = names.filter( n => n !== 'keyedReducer' ); |
| 53 | if ( remaining.length === 0 ) { |
| 54 | return localImport; |
| 55 | } |
| 56 | const remainingImport = `import { ${ remaining.join( |
| 57 | ', ' |
| 58 | ) } } from ${ quote }@wordpress/data${ quote };`; |
| 59 | return `${ remainingImport } ${ localImport }`; |
| 60 | } ); |
| 61 | }; |
| 62 |