diff --git a/package.json b/package.json index 73d88cc968f00..b78867dd659c6 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "npm": ">=6.9.0 <7" }, "config": { - "IS_GUTENBERG_PLUGIN": true + "IS_GUTENBERG_PLUGIN": true, + "ALLOW_EXPERIMENT_REREGISTRATION": true }, "dependencies": { "@wordpress/a11y": "file:packages/a11y", diff --git a/packages/experiments/src/implementation.js b/packages/experiments/src/implementation.js index 14ec8a42552e2..6ef1af0f35880 100644 --- a/packages/experiments/src/implementation.js +++ b/packages/experiments/src/implementation.js @@ -47,6 +47,15 @@ const registeredExperiments = []; const requiredConsent = 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.'; +let allowReRegistration; +// Use try/catch to force "false" if the environment variable is not explicitly +// set to true (e.g. when building WordPress core). +try { + allowReRegistration = process.env.ALLOW_EXPERIMENT_REREGISTRATION; +} catch ( error ) { + allowReRegistration = false; +} + /** * Called by a @wordpress package wishing to opt-in to accessing or exposing * private experimental APIs. @@ -68,19 +77,20 @@ export const __dangerousOptInToUnstableAPIsOnlyForCoreModules = ( 'your product will inevitably break on one of the next WordPress releases.' ); } - if ( ! process.env.IS_GUTENBERG_PLUGIN ) { + if ( + ! allowReRegistration && + registeredExperiments.includes( moduleName ) + ) { // This check doesn't play well with Story Books / Hot Module Reloading // and isn't included in the Gutenberg plugin. It only matters in the // WordPress core release. - if ( registeredExperiments.includes( moduleName ) ) { - throw new Error( - `You tried to opt-in to unstable APIs as module "${ moduleName }" which is already registered. ` + - 'This feature is only for JavaScript modules shipped with WordPress core. ' + - 'Please do not use it in plugins and themes as the unstable APIs will be removed ' + - 'without a warning. If you ignore this error and depend on unstable features, ' + - 'your product will inevitably break on one of the next WordPress releases.' - ); - } + throw new Error( + `You tried to opt-in to unstable APIs as module "${ moduleName }" which is already registered. ` + + 'This feature is only for JavaScript modules shipped with WordPress core. ' + + 'Please do not use it in plugins and themes as the unstable APIs will be removed ' + + 'without a warning. If you ignore this error and depend on unstable features, ' + + 'your product will inevitably break on one of the next WordPress releases.' + ); } if ( consent !== requiredConsent ) { throw new Error( diff --git a/test/unit/config/is-gutenberg-plugin.js b/test/unit/config/is-gutenberg-plugin.js index 7af5e4ad9a864..72527ecb725a3 100644 --- a/test/unit/config/is-gutenberg-plugin.js +++ b/test/unit/config/is-gutenberg-plugin.js @@ -22,4 +22,11 @@ global.process.env = { // eslint-disable-next-line @wordpress/is-gutenberg-plugin IS_GUTENBERG_PLUGIN: String( process.env.npm_package_config_IS_GUTENBERG_PLUGIN ) === 'true', + /** + * Whether to allow the same experiment to be registered multiple times. + * This is useful for development purposes, but should be set to false + * during the unit tests to ensure the Gutenberg plugin can be cleanly + * merged into WordPress core where this is false. + */ + ALLOW_EXPERIMENT_REREGISTRATION: false, }; diff --git a/tools/webpack/shared.js b/tools/webpack/shared.js index a807943952865..414ac4adf940b 100644 --- a/tools/webpack/shared.js +++ b/tools/webpack/shared.js @@ -66,6 +66,9 @@ const plugins = [ // Inject the `IS_GUTENBERG_PLUGIN` global, used for feature flagging. 'process.env.IS_GUTENBERG_PLUGIN': process.env.npm_package_config_IS_GUTENBERG_PLUGIN, + // Inject the `ALLOW_EXPERIMENT_REREGISTRATION` global, used by @wordpress/experiments. + 'process.env.ALLOW_EXPERIMENT_REREGISTRATION': + process.env.npm_package_config_ALLOW_EXPERIMENT_REREGISTRATION, } ), mode === 'production' && new ReadableJsAssetsWebpackPlugin(), ];