From bfc5255731a308034cd527fe44afdf54d503be49 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 8 May 2024 13:33:23 +0200 Subject: [PATCH 01/40] No more skipLibCheck --- packages/components/tsconfig.json | 5 +---- packages/dataviews/tsconfig.json | 1 - packages/plugins/tsconfig.json | 3 +-- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/components/tsconfig.json b/packages/components/tsconfig.json index 81045d05c21fc..2033a6f43fede 100644 --- a/packages/components/tsconfig.json +++ b/packages/components/tsconfig.json @@ -9,10 +9,7 @@ "gutenberg-test-env", "jest", "@testing-library/jest-dom" - ], - // TODO: Remove `skipLibCheck` after resolving duplicate declaration of the `process` variable - // between `@types/webpack-env` (from @storybook packages) and `gutenberg-env`. - "skipLibCheck": true + ] }, "references": [ { "path": "../a11y" }, diff --git a/packages/dataviews/tsconfig.json b/packages/dataviews/tsconfig.json index 60122ee152c80..83c47d8320d83 100644 --- a/packages/dataviews/tsconfig.json +++ b/packages/dataviews/tsconfig.json @@ -4,7 +4,6 @@ "compilerOptions": { "rootDir": "src", "declarationDir": "build-types", - "skipLibCheck": true, "checkJs": false }, "references": [ diff --git a/packages/plugins/tsconfig.json b/packages/plugins/tsconfig.json index d20dcecf0d613..9a0da807348b2 100644 --- a/packages/plugins/tsconfig.json +++ b/packages/plugins/tsconfig.json @@ -4,8 +4,7 @@ "compilerOptions": { "rootDir": "src", "declarationDir": "build-types", - "types": [ "gutenberg-env" ], - "skipLibCheck": true + "types": [ "gutenberg-env" ] }, "references": [ { "path": "../components" }, From 8b03884a708e32dc65cac91d4c15e8aac7dc5628 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 8 May 2024 16:46:39 +0200 Subject: [PATCH 02/40] Fix the process problem --- typings/gutenberg-env/index.d.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/typings/gutenberg-env/index.d.ts b/typings/gutenberg-env/index.d.ts index ecf60a7ca094f..5a23ae5a5b9b9 100644 --- a/typings/gutenberg-env/index.d.ts +++ b/typings/gutenberg-env/index.d.ts @@ -3,9 +3,15 @@ interface Environment { IS_GUTENBERG_PLUGIN?: boolean; IS_WORDPRESS_CORE?: boolean; } -interface Process { - env: Environment; + +declare namespace NodeJS { + export interface ProcessEnv extends Environment {} + + export interface Process { + env: ProcessEnv; + } } -declare var process: Process; + +declare var process: NodeJS.Process; declare var SCRIPT_DEBUG: boolean; From 3ca79aa985cac10b1200f14f7e27841286a5de8a Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 8 May 2024 18:32:11 +0200 Subject: [PATCH 03/40] Go bonkers on the global vars --- .eslintrc.js | 1 + tools/webpack/shared.js | 6 +++--- typings/gutenberg-env/index.d.ts | 19 ++++++++----------- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 0b0c71c39a266..fce9a595e0a37 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -92,6 +92,7 @@ module.exports = { ], globals: { wp: 'off', + globalThis: 'readonly', }, settings: { jsdoc: { diff --git a/tools/webpack/shared.js b/tools/webpack/shared.js index debd3fc93f6f6..3e6225aaebb12 100644 --- a/tools/webpack/shared.js +++ b/tools/webpack/shared.js @@ -64,13 +64,13 @@ const plugins = [ process.env.WP_BUNDLE_ANALYZER && new BundleAnalyzerPlugin(), new DefinePlugin( { // Inject the `IS_GUTENBERG_PLUGIN` global, used for feature flagging. - 'process.env.IS_GUTENBERG_PLUGIN': + 'globalThis.IS_GUTENBERG_PLUGIN': process.env.npm_package_config_IS_GUTENBERG_PLUGIN, // Inject the `IS_WORDPRESS_CORE` global, used for feature flagging. - 'process.env.IS_WORDPRESS_CORE': + 'globalThis.IS_WORDPRESS_CORE': process.env.npm_package_config_IS_WORDPRESS_CORE, // Inject the `SCRIPT_DEBUG` global, used for dev versions of JavaScript. - SCRIPT_DEBUG: mode === 'development', + 'globalThis.SCRIPT_DEBUG': mode === 'development', } ), mode === 'production' && new ReadableJsAssetsWebpackPlugin(), ]; diff --git a/typings/gutenberg-env/index.d.ts b/typings/gutenberg-env/index.d.ts index 5a23ae5a5b9b9..0239ee2ecded8 100644 --- a/typings/gutenberg-env/index.d.ts +++ b/typings/gutenberg-env/index.d.ts @@ -1,17 +1,14 @@ -interface Environment { - NODE_ENV: unknown; - IS_GUTENBERG_PLUGIN?: boolean; - IS_WORDPRESS_CORE?: boolean; -} - declare namespace NodeJS { - export interface ProcessEnv extends Environment {} - - export interface Process { - env: ProcessEnv; + interface ProcessEnv { + readonly NODE_ENV?: 'production' | 'development' | 'test'; + } + interface Process { + env: NodeJS.ProcessEnv; } } declare var process: NodeJS.Process; -declare var SCRIPT_DEBUG: boolean; +declare var SCRIPT_DEBUG: undefined | boolean; +declare var IS_GUTENBERG_PLUGIN: undefined | boolean; +declare var IS_WORDPRESS_CORE: undefined | boolean; From c5215aa562c5c25bb8a5611e5b0663dba2f28901 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Thu, 9 May 2024 15:48:47 +0200 Subject: [PATCH 04/40] Update warning package --- packages/warning/babel-plugin.js | 19 +++++-------------- packages/warning/src/index.js | 2 +- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/packages/warning/babel-plugin.js b/packages/warning/babel-plugin.js index 02c466b5de24e..3cf32d311bd6c 100644 --- a/packages/warning/babel-plugin.js +++ b/packages/warning/babel-plugin.js @@ -14,24 +14,15 @@ const pkg = require( './package.json' ); function babelPlugin( { types: t } ) { const seen = Symbol(); - const typeofProcessExpression = t.binaryExpression( - '!==', - t.unaryExpression( 'typeof', t.identifier( 'SCRIPT_DEBUG' ), false ), - t.stringLiteral( 'undefined' ) - ); - const scriptDebugCheckExpression = t.binaryExpression( '===', - t.identifier( 'SCRIPT_DEBUG' ), + t.memberExpression( + t.identifier( 'globalThis' ), + t.identifier( 'SCRIPT_DEBUG' ) + ), t.booleanLiteral( true ) ); - const logicalExpression = t.logicalExpression( - '&&', - typeofProcessExpression, - scriptDebugCheckExpression - ); - return { visitor: { ImportDeclaration( path, state ) { @@ -70,7 +61,7 @@ function babelPlugin( { types: t } ) { node[ seen ] = true; path.replaceWith( t.ifStatement( - logicalExpression, + scriptDebugCheckExpression, t.blockStatement( [ t.expressionStatement( node ), ] ) diff --git a/packages/warning/src/index.js b/packages/warning/src/index.js index 89ce71db112a2..934fe401eb464 100644 --- a/packages/warning/src/index.js +++ b/packages/warning/src/index.js @@ -4,7 +4,7 @@ import { logged } from './utils'; function isDev() { - return typeof SCRIPT_DEBUG !== 'undefined' && SCRIPT_DEBUG === true; + return globalThis.SCRIPT_DEBUG === true; } /** From f5651493af72027b414ebc930e7db7cd99076362 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Thu, 9 May 2024 15:50:30 +0200 Subject: [PATCH 05/40] Add globalThis.SCRIPT_DEBUG replacement to scripts --- packages/scripts/config/webpack.config.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/scripts/config/webpack.config.js b/packages/scripts/config/webpack.config.js index b7f61eb215eaf..f306fbd54a8a6 100644 --- a/packages/scripts/config/webpack.config.js +++ b/packages/scripts/config/webpack.config.js @@ -307,7 +307,8 @@ const scriptConfig = { plugins: [ new webpack.DefinePlugin( { // Inject the `SCRIPT_DEBUG` global, used for development features flagging. - SCRIPT_DEBUG: ! isProduction, + 'globalThis.SCRIPT_DEBUG': JSON.stringify( ! isProduction ), + SCRIPT_DEBUG: JSON.stringify( ! isProduction ), } ), // If we run a modules build, the 2 compilations can "clean" each other's output @@ -456,7 +457,8 @@ if ( hasExperimentalModulesFlag ) { plugins: [ new webpack.DefinePlugin( { // Inject the `SCRIPT_DEBUG` global, used for development features flagging. - SCRIPT_DEBUG: ! isProduction, + 'globalThis.SCRIPT_DEBUG': JSON.stringify( ! isProduction ), + SCRIPT_DEBUG: JSON.stringify( ! isProduction ), } ), // The WP_BUNDLE_ANALYZER global variable enables a utility that represents // bundle content as a convenient interactive zoomable treemap. From 1b66bac6c28d5557f1957a41ebabac792edf22e8 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Thu, 9 May 2024 15:51:19 +0200 Subject: [PATCH 06/40] Better replacement Webpack replacements are source string replacements --- tools/webpack/shared.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/webpack/shared.js b/tools/webpack/shared.js index 3e6225aaebb12..f30d3a830f3eb 100644 --- a/tools/webpack/shared.js +++ b/tools/webpack/shared.js @@ -64,13 +64,15 @@ const plugins = [ process.env.WP_BUNDLE_ANALYZER && new BundleAnalyzerPlugin(), new DefinePlugin( { // Inject the `IS_GUTENBERG_PLUGIN` global, used for feature flagging. - 'globalThis.IS_GUTENBERG_PLUGIN': - process.env.npm_package_config_IS_GUTENBERG_PLUGIN, + 'globalThis.IS_GUTENBERG_PLUGIN': JSON.stringify( + Boolean( process.env.npm_package_config_IS_GUTENBERG_PLUGIN ) + ), // Inject the `IS_WORDPRESS_CORE` global, used for feature flagging. - 'globalThis.IS_WORDPRESS_CORE': - process.env.npm_package_config_IS_WORDPRESS_CORE, + 'globalThis.IS_WORDPRESS_CORE': JSON.stringify( + Boolean( process.env.npm_package_config_IS_WORDPRESS_CORE ) + ), // Inject the `SCRIPT_DEBUG` global, used for dev versions of JavaScript. - 'globalThis.SCRIPT_DEBUG': mode === 'development', + 'globalThis.SCRIPT_DEBUG': JSON.stringify( mode === 'development' ), } ), mode === 'production' && new ReadableJsAssetsWebpackPlugin(), ]; From b1da9417e8d73d547451ec25829e544a00e8b73b Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Thu, 9 May 2024 16:49:32 +0200 Subject: [PATCH 07/40] Update tests --- packages/warning/test/babel-plugin.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/warning/test/babel-plugin.js b/packages/warning/test/babel-plugin.js index a3c4bd55745ef..c845d79d700ca 100644 --- a/packages/warning/test/babel-plugin.js +++ b/packages/warning/test/babel-plugin.js @@ -28,7 +28,7 @@ describe( 'babel-plugin', () => { ); const expected = join( 'import warning from "@wordpress/warning";', - 'typeof SCRIPT_DEBUG !== "undefined" && SCRIPT_DEBUG === true ? warning("a") : void 0;' + 'globalThis.SCRIPT_DEBUG === true ? warning("a") : void 0;' ); expect( transformCode( input ) ).toEqual( expected ); @@ -45,7 +45,7 @@ describe( 'babel-plugin', () => { const input = 'warning("a");'; const options = { callee: 'warning' }; const expected = - 'typeof SCRIPT_DEBUG !== "undefined" && SCRIPT_DEBUG === true ? warning("a") : void 0;'; + 'globalThis.SCRIPT_DEBUG === true ? warning("a") : void 0;'; expect( transformCode( input, options ) ).toEqual( expected ); } ); @@ -59,9 +59,9 @@ describe( 'babel-plugin', () => { ); const expected = join( 'import warning from "@wordpress/warning";', - 'typeof SCRIPT_DEBUG !== "undefined" && SCRIPT_DEBUG === true ? warning("a") : void 0;', - 'typeof SCRIPT_DEBUG !== "undefined" && SCRIPT_DEBUG === true ? warning("b") : void 0;', - 'typeof SCRIPT_DEBUG !== "undefined" && SCRIPT_DEBUG === true ? warning("c") : void 0;' + 'globalThis.SCRIPT_DEBUG === true ? warning("a") : void 0;', + 'globalThis.SCRIPT_DEBUG === true ? warning("b") : void 0;', + 'globalThis.SCRIPT_DEBUG === true ? warning("c") : void 0;' ); expect( transformCode( input ) ).toEqual( expected ); @@ -76,9 +76,9 @@ describe( 'babel-plugin', () => { ); const expected = join( 'import warn from "@wordpress/warning";', - 'typeof SCRIPT_DEBUG !== "undefined" && SCRIPT_DEBUG === true ? warn("a") : void 0;', - 'typeof SCRIPT_DEBUG !== "undefined" && SCRIPT_DEBUG === true ? warn("b") : void 0;', - 'typeof SCRIPT_DEBUG !== "undefined" && SCRIPT_DEBUG === true ? warn("c") : void 0;' + 'globalThis.SCRIPT_DEBUG === true ? warn("a") : void 0;', + 'globalThis.SCRIPT_DEBUG === true ? warn("b") : void 0;', + 'globalThis.SCRIPT_DEBUG === true ? warn("c") : void 0;' ); expect( transformCode( input ) ).toEqual( expected ); @@ -93,9 +93,9 @@ describe( 'babel-plugin', () => { ); const expected = join( 'import warn from "@wordpress/warning";', - 'typeof SCRIPT_DEBUG !== "undefined" && SCRIPT_DEBUG === true ? warn("a") : void 0;', - 'typeof SCRIPT_DEBUG !== "undefined" && SCRIPT_DEBUG === true ? warn("b") : void 0;', - 'typeof SCRIPT_DEBUG !== "undefined" && SCRIPT_DEBUG === true ? warn("c") : void 0;' + 'globalThis.SCRIPT_DEBUG === true ? warn("a") : void 0;', + 'globalThis.SCRIPT_DEBUG === true ? warn("b") : void 0;', + 'globalThis.SCRIPT_DEBUG === true ? warn("c") : void 0;' ); expect( transformCode( input ) ).toEqual( expected ); From b687afbba919cf5dd2ba72f5409d17fc888873ca Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Fri, 10 May 2024 19:54:41 +0200 Subject: [PATCH 08/40] Some env improvements --- test/unit/config/gutenberg-env.js | 44 +++++++++---------------------- typings/gutenberg-env/index.d.ts | 11 ++++++++ 2 files changed, 23 insertions(+), 32 deletions(-) diff --git a/test/unit/config/gutenberg-env.js b/test/unit/config/gutenberg-env.js index a6a1b81f74097..25fb473a49676 100644 --- a/test/unit/config/gutenberg-env.js +++ b/test/unit/config/gutenberg-env.js @@ -1,32 +1,12 @@ -global.process.env = { - ...global.process.env, - /* - Inject the `IS_GUTENBERG_PLUGIN` global, used for feature flagging. - - The conversion to boolean is required here. Why? Package.json defines - IS_GUTENBERG_PLUGIN as follows: - - "config": { - "IS_GUTENBERG_PLUGIN": true - } - - Webpack then replaces references to IS_GUTENBERG_PLUGIN with a literal value `true`. - The file you are reading right now, however, receives a string value "true": - - "true" === process.env.npm_package_config_IS_GUTENBERG_PLUGIN - - The code can only work consistently in both environments when the value of - IS_GUTENBERG_PLUGIN is consistent. For this reason, the line below turns the - string representation of IS_GUTENBERG_PLUGIN into a boolean value. - */ - // eslint-disable-next-line @wordpress/is-gutenberg-plugin - IS_GUTENBERG_PLUGIN: - String( process.env.npm_package_config_IS_GUTENBERG_PLUGIN ) === 'true', - /** - * Feature flag guarding features specific to WordPress core. - * It's important to set it to "true" in the test environment - * to ensure the Gutenberg plugin can be cleanly merged into - * WordPress core. - */ - IS_WORDPRESS_CORE: true, -}; +/* + * Feature flag guarding features specific to WordPress core. + * It's important to set it to "true" in the test environment + * to ensure the Gutenberg plugin can be cleanly merged into + * WordPress core. + */ +globalThis.IS_WORDPRESS_CORE = true; + +// Inject the `IS_GUTENBERG_PLUGIN` global, used for feature flagging. +// eslint-disable-next-line @wordpress/is-gutenberg-plugin +globalThis.IS_GUTENBERG_PLUGIN = + String( process.env.npm_package_config_IS_GUTENBERG_PLUGIN ) === 'true'; diff --git a/typings/gutenberg-env/index.d.ts b/typings/gutenberg-env/index.d.ts index 0239ee2ecded8..c2bc71ae435ee 100644 --- a/typings/gutenberg-env/index.d.ts +++ b/typings/gutenberg-env/index.d.ts @@ -9,6 +9,17 @@ declare namespace NodeJS { declare var process: NodeJS.Process; +/** + * Whether the code is running in WordPress with SCRIPT_DEBUG flag. + */ declare var SCRIPT_DEBUG: undefined | boolean; + +/** + * Whether code is running within the Gutenberg plugin. + * + * When the codebase is built for the plugin, this variable will be set to `true`. + * When building for WordPress Core, it will be set to `false` or `undefined`. + */ declare var IS_GUTENBERG_PLUGIN: undefined | boolean; + declare var IS_WORDPRESS_CORE: undefined | boolean; From 27db646de54e1fb87e037d53931179dafcab8b2a Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 14:19:37 +0200 Subject: [PATCH 09/40] Add no-wp-process-env rule --- packages/eslint-plugin/configs/custom.js | 1 + .../rules/__tests__/no-wp-process-env.js | 58 ++++++++++++++ .../eslint-plugin/rules/no-wp-process-env.js | 76 +++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 packages/eslint-plugin/rules/__tests__/no-wp-process-env.js create mode 100644 packages/eslint-plugin/rules/no-wp-process-env.js diff --git a/packages/eslint-plugin/configs/custom.js b/packages/eslint-plugin/configs/custom.js index dcee5de349bad..e6c67c0c6e435 100644 --- a/packages/eslint-plugin/configs/custom.js +++ b/packages/eslint-plugin/configs/custom.js @@ -7,6 +7,7 @@ module.exports = { '@wordpress/no-global-active-element': 'error', '@wordpress/no-global-get-selection': 'error', '@wordpress/no-unsafe-wp-apis': 'error', + '@wordpress/no-wp-process-env': 'error', }, overrides: [ { diff --git a/packages/eslint-plugin/rules/__tests__/no-wp-process-env.js b/packages/eslint-plugin/rules/__tests__/no-wp-process-env.js new file mode 100644 index 0000000000000..24426d206cba1 --- /dev/null +++ b/packages/eslint-plugin/rules/__tests__/no-wp-process-env.js @@ -0,0 +1,58 @@ +/** + * External dependencies + */ +import { RuleTester } from 'eslint'; + +/** + * Internal dependencies + */ +import rule from '../no-wp-process-env'; + +const ruleTester = new RuleTester( { + parserOptions: { + ecmaVersion: 6, + }, +} ); + +ruleTester.run( 'no-wp-process-env', rule, { + valid: [ + { code: 'process.env.NODE_ENV' }, + { code: 'process.env.WHATEVER' }, + { code: 'process.env[foo]' }, + { code: 'process.env["foo"]' }, + { code: `process['env']["foo"]` }, + { code: "process['env'][`foo`]" }, + { code: "process.env[`${ '' }IS_GUTENBERG_PLUGIN`]" }, + { code: `a.b.c` }, + { code: `x['y']['z']` }, + { code: `d[e][f]` }, + { code: `process[ (()=>'env')() ][ {_:'SCRIPT_DEBUG'}['_'] ]` }, + ], + invalid: [ + { + code: 'process.env.IS_GUTENBERG_PLUGIN', + errors: [ { messageId: 'message' } ], + output: 'globalThis.IS_GUTENBERG_PLUGIN', + }, + { + code: 'process.env.SCRIPT_DEBUG', + errors: [ { messageId: 'message' } ], + output: 'globalThis.SCRIPT_DEBUG', + }, + { + code: 'process.env.IS_WORDPRESS', + errors: [ { messageId: 'message' } ], + output: 'globalThis.IS_WORDPRESS', + }, + { + code: `process['env']["IS_GUTENBERG_PLUGIN"]`, + errors: [ { messageId: 'message' } ], + output: 'globalThis.IS_GUTENBERG_PLUGIN', + }, + { + code: 'process[`env`][`IS_GUTENBERG_PLUGIN`]', + errors: [ { messageId: 'message' } ], + output: 'globalThis.IS_GUTENBERG_PLUGIN', + }, + ], +} ); diff --git a/packages/eslint-plugin/rules/no-wp-process-env.js b/packages/eslint-plugin/rules/no-wp-process-env.js new file mode 100644 index 0000000000000..a64a8c6e46095 --- /dev/null +++ b/packages/eslint-plugin/rules/no-wp-process-env.js @@ -0,0 +1,76 @@ +const VARIABLES = new Set( + /** @type {const} */ ( [ + 'GUTENBERG_PHASE', + 'IS_GUTENBERG_PLUGIN', + 'IS_WORDPRESS', + 'SCRIPT_DEBUG', + ] ) +); + +/** @type {import('eslint').Rule.RuleModule} */ +module.exports = { + meta: { + type: 'problem', + schema: [], + messages: { + message: + '`{{ name }}` should not be accessed from process.env. Use `globalThis.{{name}}`.', + }, + }, + create( context ) { + return { + MemberExpression( node ) { + const propertyNameOrValue = memberProperty( node ); + if ( ! propertyNameOrValue ) { + return; + } + if ( ! VARIABLES.has( propertyNameOrValue ) ) { + return; + } + + if ( node.object.type !== 'MemberExpression' ) { + return; + } + + const obj = node.object; + const envCandidateProperty = memberProperty( obj ); + if ( envCandidateProperty !== 'env' ) { + return; + } + + if ( + obj.object.type !== 'Identifier' || + obj.object.name !== 'process' + ) { + return; + } + + context.report( { + node, + messageId: 'message', + data: { name: propertyNameOrValue }, + } ); + }, + }; + }, +}; + +/** + * @param {import('estree').MemberExpression} node + */ +function memberProperty( node ) { + switch ( node.property.type ) { + case 'Identifier': + return node.property.name; + case 'Literal': + return node.property.value; + case 'TemplateLiteral': + if ( + ! node.property.expressions.length && + node.property.quasis.length === 1 + ) { + return node.property.quasis[ 0 ].value.raw; + } + } + return null; +} From 90da9abe9126929c108b10f4109dee172964d617 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 14:33:15 +0200 Subject: [PATCH 10/40] Implement fixer --- packages/eslint-plugin/rules/no-wp-process-env.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/rules/no-wp-process-env.js b/packages/eslint-plugin/rules/no-wp-process-env.js index a64a8c6e46095..f38ba318fefec 100644 --- a/packages/eslint-plugin/rules/no-wp-process-env.js +++ b/packages/eslint-plugin/rules/no-wp-process-env.js @@ -1,4 +1,4 @@ -const VARIABLES = new Set( +const NAMES = new Set( /** @type {const} */ ( [ 'GUTENBERG_PHASE', 'IS_GUTENBERG_PLUGIN', @@ -12,6 +12,7 @@ module.exports = { meta: { type: 'problem', schema: [], + fixable: true, messages: { message: '`{{ name }}` should not be accessed from process.env. Use `globalThis.{{name}}`.', @@ -24,7 +25,7 @@ module.exports = { if ( ! propertyNameOrValue ) { return; } - if ( ! VARIABLES.has( propertyNameOrValue ) ) { + if ( ! NAMES.has( propertyNameOrValue ) ) { return; } @@ -49,6 +50,12 @@ module.exports = { node, messageId: 'message', data: { name: propertyNameOrValue }, + fix( fixer ) { + return fixer.replaceTextRange( + [ obj.range[ 0 ], node.range[ 1 ] ], + `globalThis.${ propertyNameOrValue }` + ); + }, } ); }, }; From a4be59e1ed848dfaa7b5755a93af396b8ae1f894 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 14:45:24 +0200 Subject: [PATCH 11/40] Update lint and add noGutenbergPhase rule --- .../rules/__tests__/no-wp-process-env.js | 14 +++++++++----- .../eslint-plugin/rules/no-wp-process-env.js | 16 +++++++++++++--- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/packages/eslint-plugin/rules/__tests__/no-wp-process-env.js b/packages/eslint-plugin/rules/__tests__/no-wp-process-env.js index 24426d206cba1..5b97e04c43436 100644 --- a/packages/eslint-plugin/rules/__tests__/no-wp-process-env.js +++ b/packages/eslint-plugin/rules/__tests__/no-wp-process-env.js @@ -31,28 +31,32 @@ ruleTester.run( 'no-wp-process-env', rule, { invalid: [ { code: 'process.env.IS_GUTENBERG_PLUGIN', - errors: [ { messageId: 'message' } ], + errors: [ { messageId: 'useGlobalThis' } ], output: 'globalThis.IS_GUTENBERG_PLUGIN', }, { code: 'process.env.SCRIPT_DEBUG', - errors: [ { messageId: 'message' } ], + errors: [ { messageId: 'useGlobalThis' } ], output: 'globalThis.SCRIPT_DEBUG', }, { code: 'process.env.IS_WORDPRESS', - errors: [ { messageId: 'message' } ], + errors: [ { messageId: 'useGlobalThis' } ], output: 'globalThis.IS_WORDPRESS', }, { code: `process['env']["IS_GUTENBERG_PLUGIN"]`, - errors: [ { messageId: 'message' } ], + errors: [ { messageId: 'useGlobalThis' } ], output: 'globalThis.IS_GUTENBERG_PLUGIN', }, { code: 'process[`env`][`IS_GUTENBERG_PLUGIN`]', - errors: [ { messageId: 'message' } ], + errors: [ { messageId: 'useGlobalThis' } ], output: 'globalThis.IS_GUTENBERG_PLUGIN', }, + { + code: 'process.env.GUTENBERG_PHASE', + errors: [ { messageId: 'noGutenbergPhase' } ], + }, ], } ); diff --git a/packages/eslint-plugin/rules/no-wp-process-env.js b/packages/eslint-plugin/rules/no-wp-process-env.js index f38ba318fefec..6cb25fa4b1f95 100644 --- a/packages/eslint-plugin/rules/no-wp-process-env.js +++ b/packages/eslint-plugin/rules/no-wp-process-env.js @@ -14,8 +14,10 @@ module.exports = { schema: [], fixable: true, messages: { - message: + useGlobalThis: '`{{ name }}` should not be accessed from process.env. Use `globalThis.{{name}}`.', + noGutenbergPhase: + 'The GUTENBERG_PHASE environement variable is no longer available. Use IS_GUTENBERG_PLUGIN (boolean).', }, }, create( context ) { @@ -46,13 +48,21 @@ module.exports = { return; } + if ( propertyNameOrValue === 'GUTENBERG_PHASE' ) { + context.report( { + node, + messageId: 'noGutenbergPhase', + } ); + return; + } + context.report( { node, - messageId: 'message', + messageId: 'useGlobalThis', data: { name: propertyNameOrValue }, fix( fixer ) { return fixer.replaceTextRange( - [ obj.range[ 0 ], node.range[ 1 ] ], + node.range, `globalThis.${ propertyNameOrValue }` ); }, From 346fe0f72243dcb0b78118c8c3fef735e39beacd Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 16:32:18 +0200 Subject: [PATCH 12/40] Remove gutenberg-phase eslint --- .../eslint-plugin/rules/gutenberg-phase.js | 174 ------------------ 1 file changed, 174 deletions(-) delete mode 100644 packages/eslint-plugin/rules/gutenberg-phase.js diff --git a/packages/eslint-plugin/rules/gutenberg-phase.js b/packages/eslint-plugin/rules/gutenberg-phase.js deleted file mode 100644 index e3ec9ccf8180e..0000000000000 --- a/packages/eslint-plugin/rules/gutenberg-phase.js +++ /dev/null @@ -1,174 +0,0 @@ -/** - * Traverse up through the chain of parent AST nodes returning the first parent - * the predicate returns a truthy value for. - * - * @param {Object} sourceNode The AST node to search from. - * @param {Function} predicate A predicate invoked for each parent. - * - * @return {Object | undefined} The first encountered parent node where the predicate - * returns a truthy value. - */ -function findParent( sourceNode, predicate ) { - if ( ! sourceNode.parent ) { - return; - } - - if ( predicate( sourceNode.parent ) ) { - return sourceNode.parent; - } - - return findParent( sourceNode.parent, predicate ); -} - -/** - * Tests whether the GUTENBERG_PHASE variable is accessed via - * `process.env.GUTENBERG_PHASE`. - * - * @example - * ```js - * // good - * if ( process.env.GUTENBERG_PHASE === 2 ) { - * - * // bad - * if ( GUTENBERG_PHASE === 2 ) { - * ``` - * - * @param {Object} node The GUTENBERG_PHASE identifier node. - * @param {Object} context The eslint context object. - */ -function testIsAccessedViaProcessEnv( node, context ) { - const parent = node.parent; - - if ( - parent && - parent.type === 'MemberExpression' && - context.getSource( parent ) === 'process.env.GUTENBERG_PHASE' - ) { - return; - } - - context.report( - node, - 'The `GUTENBERG_PHASE` constant should be accessed using `process.env.GUTENBERG_PHASE`.' - ); -} - -/** - * Tests whether the GUTENBERG_PHASE variable is used in a strict binary - * equality expression in a comparison with a number, triggering a - * violation if not. - * - * @example - * ```js - * // good - * if ( process.env.GUTENBERG_PHASE === 2 ) { - * - * // bad - * if ( process.env.GUTENBERG_PHASE >= '2' ) { - * ``` - * - * @param {Object} node The GUTENBERG_PHASE identifier node. - * @param {Object} context The eslint context object. - */ -function testIsUsedInStrictBinaryExpression( node, context ) { - const parent = findParent( - node, - ( candidate ) => candidate.type === 'BinaryExpression' - ); - - if ( parent ) { - const comparisonNode = - node.parent.type === 'MemberExpression' ? node.parent : node; - - // Test for process.env.GUTENBERG_PHASE === or === process.env.GUTENBERG_PHASE. - const hasCorrectOperator = [ '===', '!==' ].includes( parent.operator ); - const hasCorrectOperands = - ( parent.left === comparisonNode && - typeof parent.right.value === 'number' ) || - ( parent.right === comparisonNode && - typeof parent.left.value === 'number' ); - - if ( hasCorrectOperator && hasCorrectOperands ) { - return; - } - } - - context.report( - node, - 'The `GUTENBERG_PHASE` constant should only be used in a strict equality comparison with a primitive number.' - ); -} - -/** - * Tests whether the GUTENBERG_PHASE variable is used as the condition for an - * if statement, triggering a violation if not. - * - * @example - * ```js - * // good - * if ( process.env.GUTENBERG_PHASE === 2 ) { - * - * // bad - * const isFeatureActive = process.env.GUTENBERG_PHASE === 2; - * ``` - * - * @param {Object} node The GUTENBERG_PHASE identifier node. - * @param {Object} context The eslint context object. - */ -function testIsUsedInIfOrTernary( node, context ) { - const conditionalParent = findParent( node, ( candidate ) => - [ 'IfStatement', 'ConditionalExpression' ].includes( candidate.type ) - ); - const binaryParent = findParent( - node, - ( candidate ) => candidate.type === 'BinaryExpression' - ); - - if ( - conditionalParent && - binaryParent && - conditionalParent.test && - conditionalParent.test.range[ 0 ] === binaryParent.range[ 0 ] && - conditionalParent.test.range[ 1 ] === binaryParent.range[ 1 ] - ) { - return; - } - - context.report( - node, - 'The `GUTENBERG_PHASE` constant should only be used as part of the condition in an if statement or ternary expression.' - ); -} - -module.exports = { - meta: { - type: 'problem', - schema: [], - deprecated: true, - replacedBy: '@wordpress/is-gutenberg-plugin', - }, - create( context ) { - return { - Identifier( node ) { - // Bypass any identifiers with a node name different to `GUTENBERG_PHASE`. - if ( node.name !== 'GUTENBERG_PHASE' ) { - return; - } - - testIsAccessedViaProcessEnv( node, context ); - testIsUsedInStrictBinaryExpression( node, context ); - testIsUsedInIfOrTernary( node, context ); - }, - Literal( node ) { - // Bypass any identifiers with a node value different to `GUTENBERG_PHASE`. - if ( node.value !== 'GUTENBERG_PHASE' ) { - return; - } - - if ( node.parent && node.parent.type === 'MemberExpression' ) { - testIsAccessedViaProcessEnv( node, context ); - } - }, - }; - }, -}; From b45d5985e3131458a675e796dadcfdf29985ac88 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 16:35:39 +0200 Subject: [PATCH 13/40] Update tests --- .../rules/__tests__/is-gutenberg-plugin.js | 76 ++++++++++++++----- 1 file changed, 57 insertions(+), 19 deletions(-) diff --git a/packages/eslint-plugin/rules/__tests__/is-gutenberg-plugin.js b/packages/eslint-plugin/rules/__tests__/is-gutenberg-plugin.js index c2ffa8415269d..0a6cf38248f87 100644 --- a/packages/eslint-plugin/rules/__tests__/is-gutenberg-plugin.js +++ b/packages/eslint-plugin/rules/__tests__/is-gutenberg-plugin.js @@ -14,52 +14,90 @@ const ruleTester = new RuleTester( { }, } ); -const ERROR_MESSAGE = - 'The `process.env.IS_GUTENBERG_PLUGIN` constant should only be used as the condition in an if statement or ternary expression.'; - ruleTester.run( 'is-gutenberg-plugin', rule, { valid: [ - { code: `if ( process.env.IS_GUTENBERG_PLUGIN ) {}` }, - { code: `if ( ! process.env.IS_GUTENBERG_PLUGIN ) {}` }, + { code: `if ( globalThis.IS_GUTENBERG_PLUGIN ) {}` }, + { code: `if ( globalThis.IS_WORDPRESS ) {}` }, + { code: `if ( globalThis.SCRIPT_DEBUG ) {}` }, + { code: `if ( ! globalThis.IS_GUTENBERG_PLUGIN ) {}` }, { // Ensure whitespace is ok. code: `if ( - process.env. + globalThis. IS_GUTENBERG_PLUGIN ) {}`, }, - { code: `const test = process.env.IS_GUTENBERG_PLUGIN ? foo : bar` }, - { code: `const test = ! process.env.IS_GUTENBERG_PLUGIN ? bar : foo` }, + { code: `const test = globalThis.IS_GUTENBERG_PLUGIN ? foo : bar` }, + { code: `const test = ! globalThis.IS_GUTENBERG_PLUGIN ? bar : foo` }, { // Ensure whitespace is ok. - code: `const test = ! process.env. + code: `const test = ! globalThis. IS_GUTENBERG_PLUGIN ? bar : foo`, }, ], invalid: [ { code: `if ( IS_GUTENBERG_PLUGIN ) {}`, - errors: [ { message: ERROR_MESSAGE } ], + errors: [ + { + messageId: 'usedWithoutGlobalThis', + data: { name: 'IS_GUTENBERG_PLUGIN' }, + }, + ], + }, + { + code: `if ( SCRIPT_DEBUG ) {}`, + errors: [ + { + messageId: 'usedWithoutGlobalThis', + data: { name: 'SCRIPT_DEBUG' }, + }, + ], }, { code: `if ( window[ 'IS_GUTENBERG_PLUGIN' ] ) {}`, - errors: [ { message: ERROR_MESSAGE } ], + errors: [ + { + messageId: 'usedWithoutGlobalThis', + data: { name: 'IS_GUTENBERG_PLUGIN' }, + }, + ], }, { - code: `if ( true ) { process.env.IS_GUTENBERG_PLUGIN === 2 }`, - errors: [ { message: ERROR_MESSAGE } ], + code: `if ( true ) { globalThis.IS_GUTENBERG_PLUGIN === 2 }`, + errors: [ + { + messageId: 'usedOutsideConditional', + data: { name: 'IS_GUTENBERG_PLUGIN' }, + }, + ], }, { - code: `if ( process.env.IS_GUTENBERG_PLUGIN === 2 ) {}`, - errors: [ { message: ERROR_MESSAGE } ], + code: `if ( globalThis.IS_GUTENBERG_PLUGIN === 2 ) {}`, + errors: [ + { + messageId: 'usedOutsideConditional', + data: { name: 'IS_GUTENBERG_PLUGIN' }, + }, + ], }, { - code: `if ( true || process.env.IS_GUTENBERG_PLUGIN === 2 ) {}`, - errors: [ { message: ERROR_MESSAGE } ], + code: `if ( true || globalThis.IS_GUTENBERG_PLUGIN === 2 ) {}`, + errors: [ + { + messageId: 'usedOutsideConditional', + data: { name: 'IS_GUTENBERG_PLUGIN' }, + }, + ], }, { - code: `const isFeatureActive = process.env.IS_GUTENBERG_PLUGIN;`, - errors: [ { message: ERROR_MESSAGE } ], + code: `const isFeatureActive = globalThis.IS_GUTENBERG_PLUGIN;`, + errors: [ + { + messageId: 'usedOutsideConditional', + data: { name: 'IS_GUTENBERG_PLUGIN' }, + }, + ], }, ], } ); From 515f77d518818518fd265843e55d8be42808e3d0 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 16:54:22 +0200 Subject: [PATCH 14/40] rework is-gb-plugin --- .eslintrc.js | 2 +- ...gutenberg-plugin.js => wp-global-usage.js} | 5 +- .../rules/is-gutenberg-plugin.js | 94 ------------- .../eslint-plugin/rules/wp-global-usage.js | 125 ++++++++++++++++++ 4 files changed, 129 insertions(+), 97 deletions(-) rename packages/eslint-plugin/rules/__tests__/{is-gutenberg-plugin.js => wp-global-usage.js} (94%) delete mode 100644 packages/eslint-plugin/rules/is-gutenberg-plugin.js create mode 100644 packages/eslint-plugin/rules/wp-global-usage.js diff --git a/.eslintrc.js b/.eslintrc.js index fce9a595e0a37..490c542f9d456 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -105,7 +105,7 @@ module.exports = { 'jest/expect-expect': 'off', 'react/jsx-boolean-value': 'error', '@wordpress/dependency-group': 'error', - '@wordpress/is-gutenberg-plugin': 'error', + '@wordpress/wp-global-usage': 'error', '@wordpress/react-no-unsafe-timeout': 'error', '@wordpress/i18n-text-domain': [ 'error', diff --git a/packages/eslint-plugin/rules/__tests__/is-gutenberg-plugin.js b/packages/eslint-plugin/rules/__tests__/wp-global-usage.js similarity index 94% rename from packages/eslint-plugin/rules/__tests__/is-gutenberg-plugin.js rename to packages/eslint-plugin/rules/__tests__/wp-global-usage.js index 0a6cf38248f87..2ac6c3668ce18 100644 --- a/packages/eslint-plugin/rules/__tests__/is-gutenberg-plugin.js +++ b/packages/eslint-plugin/rules/__tests__/wp-global-usage.js @@ -6,7 +6,7 @@ import { RuleTester } from 'eslint'; /** * Internal dependencies */ -import rule from '../is-gutenberg-plugin'; +import rule from '../wp-global-usage'; const ruleTester = new RuleTester( { parserOptions: { @@ -14,8 +14,9 @@ const ruleTester = new RuleTester( { }, } ); -ruleTester.run( 'is-gutenberg-plugin', rule, { +ruleTester.run( 'wp-global-usage', rule, { valid: [ + { code: "const text = 'SCRIPT_DEBUG'" }, { code: `if ( globalThis.IS_GUTENBERG_PLUGIN ) {}` }, { code: `if ( globalThis.IS_WORDPRESS ) {}` }, { code: `if ( globalThis.SCRIPT_DEBUG ) {}` }, diff --git a/packages/eslint-plugin/rules/is-gutenberg-plugin.js b/packages/eslint-plugin/rules/is-gutenberg-plugin.js deleted file mode 100644 index 00475545e6158..0000000000000 --- a/packages/eslint-plugin/rules/is-gutenberg-plugin.js +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Traverse up through the chain of parent AST nodes returning the first parent - * the predicate returns a truthy value for. - * - * @param {Object} sourceNode The AST node to search from. - * @param {Function} predicate A predicate invoked for each parent. - * - * @return {Object | undefined} The first encountered parent node where the predicate - * returns a truthy value. - */ -function findParent( sourceNode, predicate ) { - if ( ! sourceNode.parent ) { - return; - } - - if ( predicate( sourceNode.parent ) ) { - return sourceNode.parent; - } - - return findParent( sourceNode.parent, predicate ); -} - -/** - * Tests whether the IS_GUTENBERG_PLUGIN variable is used as the condition for an - * if statement or ternary, triggering a violation if not. - * - * @example - * ```js - * // good - * if ( process.env.IS_GUTENBERG_PLUGIN ) { - * - * // bad - * const isFeatureActive = process.env.IS_GUTENBERG_PLUGIN; - * ``` - * - * @param {Object} node The IS_GUTENBERG_PLUGIN identifier node. - * @param {Object} context The eslint context object. - */ -function isUsedInConditional( node, context ) { - const conditionalParent = findParent( node, ( candidate ) => - [ 'IfStatement', 'ConditionalExpression' ].includes( candidate.type ) - ); - - if ( ! conditionalParent ) { - return false; - } - - // Allow for whitespace as prettier sometimes breaks this on separate lines. - const textRegex = /^\s*!?\s*process\s*\.\s*env\s*\.\s*IS_GUTENBERG_PLUGIN$/; - const testSource = context.getSource( conditionalParent.test ); - - if ( ! textRegex.test( testSource ) ) { - return false; - } - - return true; -} - -const ERROR_MESSAGE = - 'The `process.env.IS_GUTENBERG_PLUGIN` constant should only be used as the condition in an if statement or ternary expression.'; - -module.exports = { - meta: { - type: 'problem', - schema: [], - }, - create( context ) { - return { - Identifier( node ) { - // Bypass any identifiers with a node name different to `IS_GUTENBERG_PLUGIN`. - if ( node.name !== 'IS_GUTENBERG_PLUGIN' ) { - return; - } - - if ( ! isUsedInConditional( node, context ) ) { - context.report( node, ERROR_MESSAGE ); - } - }, - // Check for literals, e.g. when 'IS_GUTENBERG_PLUGIN' is used as a string via something like 'window[ 'IS_GUTENBERG_PLUGIN' ]'. - Literal( node ) { - // Bypass any identifiers with a node value different to `IS_GUTENBERG_PLUGIN`. - if ( node.value !== 'IS_GUTENBERG_PLUGIN' ) { - return; - } - - if ( node.parent && node.parent.type === 'MemberExpression' ) { - if ( ! isUsedInConditional( node, context ) ) { - context.report( node, ERROR_MESSAGE ); - } - } - }, - }; - }, -}; diff --git a/packages/eslint-plugin/rules/wp-global-usage.js b/packages/eslint-plugin/rules/wp-global-usage.js new file mode 100644 index 0000000000000..7adc6f25ca022 --- /dev/null +++ b/packages/eslint-plugin/rules/wp-global-usage.js @@ -0,0 +1,125 @@ +const NAMES = new Set( + /** @type {const} */ ( [ + 'IS_GUTENBERG_PLUGIN', + 'IS_WORDPRESS', + 'SCRIPT_DEBUG', + ] ) +); + +/** + * Tests whether the IS_GUTENBERG_PLUGIN variable is used as the condition for an + * if statement or ternary, triggering a violation if not. + * + * @example + * ```js + * // good + * if ( process.env.IS_GUTENBERG_PLUGIN ) { + * + * // bad + * const isFeatureActive = process.env.IS_GUTENBERG_PLUGIN; + * ``` + * + * @param {import('estree').Node} node The IS_GUTENBERG_PLUGIN identifier node. + */ +function isUsedInConditional( node ) { + /** @type {import('estree').Node|undefined} */ + let current = node.parent; + + // Simple negation is the only expresion allowed in the conditional: + // if ( ! globalThis.SCRIPT_DEBUG ) {} + // const D = ! globalThis.SCRIPT_DEBUG ? 'yes' : 'no'; + if ( + current.parent.type === 'UnaryExpression' && + current.parent.operator === '!' + ) { + current = current.parent; + } + + // Check if the current node is the test of a conditional + + /** @type {import('estree').Node|undefined} */ + const parent = current.parent; + + if ( parent.type === 'IfStatement' && parent.test === current ) { + return true; + } + if ( parent.type === 'ConditionalExpression' && parent.test === current ) { + return true; + } + return false; +} + +/** @type {import('eslint').Rule.RuleModule} */ +module.exports = { + meta: { + type: 'problem', + schema: [], + messages: { + usedOutsideConditional: + '`globalThis.{{ name }}` should only be used as the condition in an if statement or ternary expression.', + usedWithoutGlobalThis: + '`{{ name }}` should not be used directly. Use `globalThis.{{ name }}`.', + }, + }, + create( context ) { + return { + Identifier( node ) { + // Bypass any identifiers with a node name different to `IS_GUTENBERG_PLUGIN`. + if ( ! NAMES.has( node.name ) ) { + return; + } + + if ( + node.parent?.type !== 'MemberExpression' || + node.parent.object.type !== 'Identifier' || + node.parent.object.name !== 'globalThis' + ) { + context.report( { + node, + messageId: 'usedWithoutGlobalThis', + data: { name: node.name }, + } ); + } else if ( ! isUsedInConditional( node ) ) { + context.report( { + node, + messageId: 'usedOutsideConditional', + data: { + name: node.name, + }, + } ); + } + }, + + // Check for literals, e.g. when 'IS_GUTENBERG_PLUGIN' is used as a string via something like 'window[ 'IS_GUTENBERG_PLUGIN' ]'. + Literal( node ) { + // Bypass any identifiers with a node value different to `IS_GUTENBERG_PLUGIN`. + if ( ! NAMES.has( node.value ) ) { + return; + } + + if ( node.parent.type !== 'MemberExpression' ) { + return; + } + + if ( + node.parent.object.type !== 'Identifier' || + node.parent.object.name !== 'globalThis' + ) { + context.report( { + node, + messageId: 'usedWithoutGlobalThis', + data: { name: node.value }, + } ); + } else if ( ! isUsedInConditional( node ) ) { + context.report( { + node, + messageId: 'usedOutsideConditional', + data: { + name: node.value, + }, + } ); + } + }, + }; + }, +}; From c25ea4e15228caf298bba4fd5dbaf3c0506efb12 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 17:01:06 +0200 Subject: [PATCH 15/40] Replace process.env.IS_GUTENBERG_PLUGIN usage --- packages/e2e-tests/config/is-gutenberg-plugin.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/e2e-tests/config/is-gutenberg-plugin.js b/packages/e2e-tests/config/is-gutenberg-plugin.js index d03b70b3ec11a..5cfe3ada705df 100644 --- a/packages/e2e-tests/config/is-gutenberg-plugin.js +++ b/packages/e2e-tests/config/is-gutenberg-plugin.js @@ -1,6 +1,3 @@ -global.process.env = { - ...global.process.env, - // Inject the `IS_GUTENBERG_PLUGIN` global, used for feature flagging. - // eslint-disable-next-line @wordpress/is-gutenberg-plugin - IS_GUTENBERG_PLUGIN: process.env.npm_package_config_IS_GUTENBERG_PLUGIN, -}; +// eslint-disable-next-line @wordpress/wp-global-usage +globalThis.IS_GUTENBERG_PLUGIN = + process.env.npm_package_config_IS_GUTENBERG_PLUGIN === 'true'; From 25dd78b072aef392e16f8fd22e5004f8692d53de Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 17:07:02 +0200 Subject: [PATCH 16/40] docs --- .../docs/rules/is-gutenberg-plugin.md | 61 ------------------- .../docs/rules/wp-globals-usage.md | 60 ++++++++++++++++++ 2 files changed, 60 insertions(+), 61 deletions(-) delete mode 100644 packages/eslint-plugin/docs/rules/is-gutenberg-plugin.md create mode 100644 packages/eslint-plugin/docs/rules/wp-globals-usage.md diff --git a/packages/eslint-plugin/docs/rules/is-gutenberg-plugin.md b/packages/eslint-plugin/docs/rules/is-gutenberg-plugin.md deleted file mode 100644 index 99b51cf5cbb93..0000000000000 --- a/packages/eslint-plugin/docs/rules/is-gutenberg-plugin.md +++ /dev/null @@ -1,61 +0,0 @@ -# The `IS_GUTENBERG_PLUGIN` global (is-gutenberg-plugin) - -To enable the use of feature flags in Gutenberg, the IS_GUTENBERG_PLUGIN global constant was introduced. This constant is replaced with a boolean value at build time using webpack's define plugin. - -There are a few rules around using this constant: - -- Only access `IS_GUTENBERG_PLUGIN` via `process.env`, e.g. `process.env.IS_GUTENBERG_PLUGIN`. This is required since webpack's define plugin only replaces exact matches of `process.env.IS_GUTENBERG_PLUGIN` in the codebase. -- The `IS_GUTENBERG_PLUGIN` variable should only be used as a simple boolean expression. -- `IS_GUTENBERG_PLUGIN` should only be used within the condition of an if statement, e.g. `if ( process.env.IS_GUTENBERG_PLUGIN ) { // implement feature here }` or ternary `process.env.IS_GUTENBERG_PLUGIN ? something : somethingElse`. This rule ensures code that is disabled through a feature flag is removed by dead code elimination. - -## Rule details - -Examples of **incorrect** code for this rule: - -```js -if ( IS_GUTENBERG_PLUGIN ) { - // implement feature here. -} -``` - -```js -if ( window[ 'IS_GUTENBERG_PLUGIN' ] ) { - // implement feature here. -} -``` - -```js -if ( process.env.IS_GUTENBERG_PLUGIN == 1 ) { - // implement feature here. -} -``` - -```js -if ( process.env.IS_GUTENBERG_PLUGIN === true ) { - // implement feature here. -} -``` - -```js -if ( true || process.env.IS_GUTENBERG_PLUGIN ) { - // implement feature here. -} -``` - -```js -const isMyFeatureActive = process.env.IS_GUTENBERG_PLUGIN; -``` - -Examples of **correct** code for this rule: - -```js -if ( process.env.IS_GUTENBERG_PLUGIN ) { - // implement feature here. -} -``` - -```js -if ( ! process.env.IS_GUTENBERG_PLUGIN ) { - return; -} -``` diff --git a/packages/eslint-plugin/docs/rules/wp-globals-usage.md b/packages/eslint-plugin/docs/rules/wp-globals-usage.md new file mode 100644 index 0000000000000..1cf9c5bff72c5 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/wp-globals-usage.md @@ -0,0 +1,60 @@ +# WordPress globals usage (wp-globals-usage) + +To enable the use of feature flags in Gutenberg some globals are used, such as `IS_GUTENBERG_PLUGIN` and `SCRIPT_DEBUG`. + +There are a few rules around using this constant: + +- Only access the globals via `globalThis`, e.g. `globalThis.IS_GUTENBERG_PLUGIN`. This allows the variables to be replaced compile time. +- The globals should only be used as a conditional test (negation is allowed). + +## Rule details + +Examples of **incorrect** code for this rule: + +```js +if ( IS_GUTENBERG_PLUGIN ) { + // implement feature here. +} +``` + +```js +if ( window[ 'IS_GUTENBERG_PLUGIN' ] ) { + // implement feature here. +} +``` + +```js +if ( globalThis.IS_GUTENBERG_PLUGIN == 1 ) { + // implement feature here. +} +``` + +```js +if ( globalThis.IS_GUTENBERG_PLUGIN === true ) { + // implement feature here. +} +``` + +```js +if ( true || globalThis.IS_GUTENBERG_PLUGIN ) { + // implement feature here. +} +``` + +```js +const isMyFeatureActive = globalThis.IS_GUTENBERG_PLUGIN; +``` + +Examples of **correct** code for this rule: + +```js +if ( globalThis.IS_GUTENBERG_PLUGIN ) { + // implement feature here. +} +``` + +```js +if ( ! globalThis.IS_GUTENBERG_PLUGIN ) { + return; +} +``` From ba5375db21b7e9430df1516b0c27c4edfff4b2f9 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 17:15:35 +0200 Subject: [PATCH 17/40] Add eslint-plugin changelog --- packages/eslint-plugin/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 84251a677bd1e..9b0df19c17932 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +### Breaking Changes + +- `@wordpress/is-gutenberg-plugin` rule has been replaced by `@wordpress/wp-global-usage` ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). +- `@wordpress/wp-process-env` rule has been added and included in the recommended configurations ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). + ## 18.1.0 (2024-05-16) ### Internal From 8da663c0764e53a95dea6e9dfd0c4f1c6d54d870 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 17:20:11 +0200 Subject: [PATCH 18/40] Update eslint plugin README --- packages/eslint-plugin/README.md | 39 ++++++++++--------- .../docs/rules/no-wp-process-env.md | 23 +++++++++++ 2 files changed, 43 insertions(+), 19 deletions(-) create mode 100644 packages/eslint-plugin/docs/rules/no-wp-process-env.md diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index 1619778add661..42a1daff558c0 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -69,25 +69,26 @@ The granular rulesets will not define any environment globals. As such, if they ### Rules -| Rule | Description | Recommended | -| -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ----------- | -| [data-no-store-string-literals](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/data-no-store-string-literals.md) | Discourage passing string literals to reference data stores | | -| [dependency-group](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/dependency-group.md) | Enforce dependencies docblocks formatting | ✓ | -| [is-gutenberg-plugin](docs/rules/is-gutenberg-plugin.md) | Governs the use of the `process.env.IS_GUTENBERG_PLUGIN` constant | ✓ | -| [no-base-control-with-label-without-id](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-base-control-with-label-without-id.md) | Disallow the usage of BaseControl component with a label prop set but omitting the id property | ✓ | -| [no-unguarded-get-range-at](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-unguarded-get-range-at.md) | Disallow the usage of unguarded `getRangeAt` calls | ✓ | -| [no-unsafe-wp-apis](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-unsafe-wp-apis.md) | Disallow the usage of unsafe APIs from `@wordpress/*` packages | ✓ | -| [no-unused-vars-before-return](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-unused-vars-before-return.md) | Disallow assigning variable values if unused before a return | ✓ | -| [react-no-unsafe-timeout](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/react-no-unsafe-timeout.md) | Disallow unsafe `setTimeout` in component | | -| [valid-sprintf](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/valid-sprintf.md) | Enforce valid sprintf usage | ✓ | -| [i18n-ellipsis](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/i18n-ellipsis.md) | Disallow using three dots in translatable strings | ✓ | -| [i18n-no-collapsible-whitespace](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/i18n-no-collapsible-whitespace.md) | Disallow collapsible whitespace in translatable strings | ✓ | -| [i18n-no-placeholders-only](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/i18n-no-placeholders-only.md) | Prevent using only placeholders in translatable strings | ✓ | -| [i18n-no-variables](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/i18n-no-variables.md) | Enforce string literals as translation function arguments | ✓ | -| [i18n-text-domain](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/i18n-text-domain.md) | Enforce passing valid text domains | ✓ | -| [i18n-translator-comments](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/i18n-translator-comments.md) | Enforce adding translator comments | ✓ | -| [i18n-no-flanking-whitespace](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/i18n-no-flanking-whitespace.md) | Disallow leading or trailing whitespace in translatable strings | | -| [i18n-hyphenated-range](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/i18n-hyphenated-range.md) | Disallow hyphenated numerical ranges in translatable strings | | +| Rule | Description | Recommended | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ----------- | +| [data-no-store-string-literals](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/data-no-store-string-literals.md) | Discourage passing string literals to reference data stores. | | +| [dependency-group](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/dependency-group.md) | Enforce dependencies docblocks formatting. | ✓ | +| [i18n-ellipsis](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/i18n-ellipsis.md) | Disallow using three dots in translatable strings. | ✓ | +| [i18n-hyphenated-range](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/i18n-hyphenated-range.md) | Disallow hyphenated numerical ranges in translatable strings. | | +| [i18n-no-collapsible-whitespace](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/i18n-no-collapsible-whitespace.md) | Disallow collapsible whitespace in translatable strings. | ✓ | +| [i18n-no-flanking-whitespace](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/i18n-no-flanking-whitespace.md) | Disallow leading or trailing whitespace in translatable strings. | | +| [i18n-no-placeholders-only](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/i18n-no-placeholders-only.md) | Prevent using only placeholders in translatable strings. | ✓ | +| [i18n-no-variables](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/i18n-no-variables.md) | Enforce string literals as translation function arguments. | ✓ | +| [i18n-text-domain](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/i18n-text-domain.md) | Enforce passing valid text domains. | ✓ | +| [i18n-translator-comments](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/i18n-translator-comments.md) | Enforce adding translator comments. | ✓ | +| [no-base-control-with-label-without-id](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-base-control-with-label-without-id.md) | Disallow the usage of BaseControl component with a label prop set but omitting the id property. | ✓ | +| [no-unguarded-get-range-at](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-unguarded-get-range-at.md) | Disallow the usage of unguarded `getRangeAt` calls. | ✓ | +| [no-unsafe-wp-apis](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-unsafe-wp-apis.md) | Disallow the usage of unsafe APIs from `@wordpress/*` packagesl | ✓ | +| [no-unused-vars-before-return](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-unused-vars-before-return.md) | Disallow assigning variable values if unused before a return. | ✓ | +| [no-wp-process-env](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-wp-process-env.md) | Disallow legacy usage of WordPress variables via `process.env` like `process.env.SCRIPT_DEBUG`. | ✓ | +| [react-no-unsafe-timeout](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/react-no-unsafe-timeout.md) | Disallow unsafe `setTimeout` in component. | | +| [valid-sprintf](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/valid-sprintf.md) | Enforce valid sprintf usage. | ✓ | +| [wp-globals-usage](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/wp-globals-usage.md) | Enforce correct usage of WordPress globals like `globalThis.SCRIPT_DEBUG`. | | ### Legacy diff --git a/packages/eslint-plugin/docs/rules/no-wp-process-env.md b/packages/eslint-plugin/docs/rules/no-wp-process-env.md new file mode 100644 index 0000000000000..46fa6ed431c20 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/no-wp-process-env.md @@ -0,0 +1,23 @@ +# No WordPress process.env (no-wp-process-env) + +WordPress globals were accessed via `process.env` in the past. This practice created difficulty for +package consumers and was removed. + +The correct way to access these globals is now via `globalThis`, e.g. `globalThis.SCRIPT_DEBUG`. +This is safer for package consumers. + +This rule is fixable. + +## Rule details + +Examples of **incorrect** code for this rule: + +```js +process.env.SCRIPT_DEBUG; +``` + +Examples of **correct** code for this rule: + +```js +globalThis.SCRIPT_DEBUG; +``` From 898ad7ff41b5c1be840b6004f7482b84caaf62ad Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 20:11:10 +0200 Subject: [PATCH 19/40] Update eslint-ignore --- test/unit/config/gutenberg-env.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/config/gutenberg-env.js b/test/unit/config/gutenberg-env.js index 25fb473a49676..986edf55f34f9 100644 --- a/test/unit/config/gutenberg-env.js +++ b/test/unit/config/gutenberg-env.js @@ -7,6 +7,6 @@ globalThis.IS_WORDPRESS_CORE = true; // Inject the `IS_GUTENBERG_PLUGIN` global, used for feature flagging. -// eslint-disable-next-line @wordpress/is-gutenberg-plugin +// eslint-disable-next-line @wordpress/wp-global-usage globalThis.IS_GUTENBERG_PLUGIN = String( process.env.npm_package_config_IS_GUTENBERG_PLUGIN ) === 'true'; From 3a272605644e93c58a9658f29358c980470448df Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 20:26:03 +0200 Subject: [PATCH 20/40] Fix property name --- packages/eslint-plugin/rules/__tests__/wp-global-usage.js | 1 + packages/eslint-plugin/rules/wp-global-usage.js | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/packages/eslint-plugin/rules/__tests__/wp-global-usage.js b/packages/eslint-plugin/rules/__tests__/wp-global-usage.js index 2ac6c3668ce18..b53f6045fc3d6 100644 --- a/packages/eslint-plugin/rules/__tests__/wp-global-usage.js +++ b/packages/eslint-plugin/rules/__tests__/wp-global-usage.js @@ -17,6 +17,7 @@ const ruleTester = new RuleTester( { ruleTester.run( 'wp-global-usage', rule, { valid: [ { code: "const text = 'SCRIPT_DEBUG'" }, + { code: 'const config = { SCRIPT_DEBUG: true }' }, { code: `if ( globalThis.IS_GUTENBERG_PLUGIN ) {}` }, { code: `if ( globalThis.IS_WORDPRESS ) {}` }, { code: `if ( globalThis.SCRIPT_DEBUG ) {}` }, diff --git a/packages/eslint-plugin/rules/wp-global-usage.js b/packages/eslint-plugin/rules/wp-global-usage.js index 7adc6f25ca022..b145d091d904b 100644 --- a/packages/eslint-plugin/rules/wp-global-usage.js +++ b/packages/eslint-plugin/rules/wp-global-usage.js @@ -69,6 +69,10 @@ module.exports = { return; } + if ( node.parent.type === 'Property' ) { + return; + } + if ( node.parent?.type !== 'MemberExpression' || node.parent.object.type !== 'Identifier' || From 82cf4a00d40c19200d94844b53ea530b1e6df477 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 20:34:15 +0200 Subject: [PATCH 21/40] Fix docs --- packages/eslint-plugin/README.md | 2 +- .../docs/rules/{wp-globals-usage.md => wp-global-usage.md} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename packages/eslint-plugin/docs/rules/{wp-globals-usage.md => wp-global-usage.md} (96%) diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index 42a1daff558c0..bd629a593f277 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -88,7 +88,7 @@ The granular rulesets will not define any environment globals. As such, if they | [no-wp-process-env](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-wp-process-env.md) | Disallow legacy usage of WordPress variables via `process.env` like `process.env.SCRIPT_DEBUG`. | ✓ | | [react-no-unsafe-timeout](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/react-no-unsafe-timeout.md) | Disallow unsafe `setTimeout` in component. | | | [valid-sprintf](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/valid-sprintf.md) | Enforce valid sprintf usage. | ✓ | -| [wp-globals-usage](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/wp-globals-usage.md) | Enforce correct usage of WordPress globals like `globalThis.SCRIPT_DEBUG`. | | +| [wp-global-usage](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/wp-global-usage.md) | Enforce correct usage of WordPress globals like `globalThis.SCRIPT_DEBUG`. | | ### Legacy diff --git a/packages/eslint-plugin/docs/rules/wp-globals-usage.md b/packages/eslint-plugin/docs/rules/wp-global-usage.md similarity index 96% rename from packages/eslint-plugin/docs/rules/wp-globals-usage.md rename to packages/eslint-plugin/docs/rules/wp-global-usage.md index 1cf9c5bff72c5..d7b90b89258a9 100644 --- a/packages/eslint-plugin/docs/rules/wp-globals-usage.md +++ b/packages/eslint-plugin/docs/rules/wp-global-usage.md @@ -1,4 +1,4 @@ -# WordPress globals usage (wp-globals-usage) +# WordPress global usage (wp-global-usage) To enable the use of feature flags in Gutenberg some globals are used, such as `IS_GUTENBERG_PLUGIN` and `SCRIPT_DEBUG`. From 01378ae465bae4f0d98de093f9ae2ef24e96cb32 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 20:34:26 +0200 Subject: [PATCH 22/40] Add basic fixing --- packages/eslint-plugin/rules/__tests__/wp-global-usage.js | 6 ++++-- packages/eslint-plugin/rules/wp-global-usage.js | 7 +++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/rules/__tests__/wp-global-usage.js b/packages/eslint-plugin/rules/__tests__/wp-global-usage.js index b53f6045fc3d6..e8baf22486e28 100644 --- a/packages/eslint-plugin/rules/__tests__/wp-global-usage.js +++ b/packages/eslint-plugin/rules/__tests__/wp-global-usage.js @@ -39,22 +39,24 @@ ruleTester.run( 'wp-global-usage', rule, { ], invalid: [ { - code: `if ( IS_GUTENBERG_PLUGIN ) {}`, + code: 'if ( IS_GUTENBERG_PLUGIN ) {}', errors: [ { messageId: 'usedWithoutGlobalThis', data: { name: 'IS_GUTENBERG_PLUGIN' }, }, ], + output: 'if ( globalThis.IS_GUTENBERG_PLUGIN ) {}', }, { - code: `if ( SCRIPT_DEBUG ) {}`, + code: 'if ( SCRIPT_DEBUG ) {}', errors: [ { messageId: 'usedWithoutGlobalThis', data: { name: 'SCRIPT_DEBUG' }, }, ], + output: 'if ( globalThis.SCRIPT_DEBUG ) {}', }, { code: `if ( window[ 'IS_GUTENBERG_PLUGIN' ] ) {}`, diff --git a/packages/eslint-plugin/rules/wp-global-usage.js b/packages/eslint-plugin/rules/wp-global-usage.js index b145d091d904b..fa4ce23a43ac0 100644 --- a/packages/eslint-plugin/rules/wp-global-usage.js +++ b/packages/eslint-plugin/rules/wp-global-usage.js @@ -54,6 +54,7 @@ module.exports = { meta: { type: 'problem', schema: [], + fixable: true, messages: { usedOutsideConditional: '`globalThis.{{ name }}` should only be used as the condition in an if statement or ternary expression.', @@ -82,6 +83,12 @@ module.exports = { node, messageId: 'usedWithoutGlobalThis', data: { name: node.name }, + fix( fixer ) { + return fixer.replaceText( + node, + `globalThis.${ node.name }` + ); + }, } ); } else if ( ! isUsedInConditional( node ) ) { context.report( { From d688c0215f7e3523a1657d60788c4ef84294bfa5 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 20:35:11 +0200 Subject: [PATCH 23/40] Use better fix --- packages/eslint-plugin/rules/no-wp-process-env.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/rules/no-wp-process-env.js b/packages/eslint-plugin/rules/no-wp-process-env.js index 6cb25fa4b1f95..987e1813a6e6a 100644 --- a/packages/eslint-plugin/rules/no-wp-process-env.js +++ b/packages/eslint-plugin/rules/no-wp-process-env.js @@ -61,8 +61,8 @@ module.exports = { messageId: 'useGlobalThis', data: { name: propertyNameOrValue }, fix( fixer ) { - return fixer.replaceTextRange( - node.range, + return fixer.replaceText( + node, `globalThis.${ propertyNameOrValue }` ); }, From ee87395b9c1981265b4e82ef01baecc5276b8fbb Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 21:32:53 +0200 Subject: [PATCH 24/40] fixin the rules --- .../rules/__tests__/wp-global-usage.js | 13 ++++- .../eslint-plugin/rules/wp-global-usage.js | 52 +++++++++++++++---- 2 files changed, 55 insertions(+), 10 deletions(-) diff --git a/packages/eslint-plugin/rules/__tests__/wp-global-usage.js b/packages/eslint-plugin/rules/__tests__/wp-global-usage.js index e8baf22486e28..fed530f0bb12a 100644 --- a/packages/eslint-plugin/rules/__tests__/wp-global-usage.js +++ b/packages/eslint-plugin/rules/__tests__/wp-global-usage.js @@ -48,6 +48,16 @@ ruleTester.run( 'wp-global-usage', rule, { ], output: 'if ( globalThis.IS_GUTENBERG_PLUGIN ) {}', }, + { + code: 'if ( window.IS_GUTENBERG_PLUGIN ) {}', + errors: [ + { + messageId: 'usedWithoutGlobalThis', + data: { name: 'IS_GUTENBERG_PLUGIN' }, + }, + ], + output: 'if ( globalThis.IS_GUTENBERG_PLUGIN ) {}', + }, { code: 'if ( SCRIPT_DEBUG ) {}', errors: [ @@ -59,13 +69,14 @@ ruleTester.run( 'wp-global-usage', rule, { output: 'if ( globalThis.SCRIPT_DEBUG ) {}', }, { - code: `if ( window[ 'IS_GUTENBERG_PLUGIN' ] ) {}`, + code: "if ( window[ 'IS_GUTENBERG_PLUGIN' ] ) {}", errors: [ { messageId: 'usedWithoutGlobalThis', data: { name: 'IS_GUTENBERG_PLUGIN' }, }, ], + output: 'if ( globalThis.IS_GUTENBERG_PLUGIN ) {}', }, { code: `if ( true ) { globalThis.IS_GUTENBERG_PLUGIN === 2 }`, diff --git a/packages/eslint-plugin/rules/wp-global-usage.js b/packages/eslint-plugin/rules/wp-global-usage.js index fa4ce23a43ac0..e278f48fceef3 100644 --- a/packages/eslint-plugin/rules/wp-global-usage.js +++ b/packages/eslint-plugin/rules/wp-global-usage.js @@ -23,7 +23,7 @@ const NAMES = new Set( */ function isUsedInConditional( node ) { /** @type {import('estree').Node|undefined} */ - let current = node.parent; + let current = node; // Simple negation is the only expresion allowed in the conditional: // if ( ! globalThis.SCRIPT_DEBUG ) {} @@ -74,11 +74,7 @@ module.exports = { return; } - if ( - node.parent?.type !== 'MemberExpression' || - node.parent.object.type !== 'Identifier' || - node.parent.object.name !== 'globalThis' - ) { + if ( node.parent.type !== 'MemberExpression' ) { context.report( { node, messageId: 'usedWithoutGlobalThis', @@ -90,7 +86,37 @@ module.exports = { ); }, } ); - } else if ( ! isUsedInConditional( node ) ) { + + if ( ! isUsedInConditional( node ) ) { + context.report( { + node, + messageId: 'usedOutsideConditional', + data: { + name: node.name, + }, + } ); + } + return; + } + + if ( + node.parent.object.type === 'Identifier' && + node.parent.object.name !== 'globalThis' + ) { + context.report( { + node, + messageId: 'usedWithoutGlobalThis', + data: { name: node.name }, + fix( fixer ) { + if ( node.parent.object.name === 'window' ) { + return fixer.replaceText( + node.parent, + `globalThis.${ node.name }` + ); + } + }, + } ); + } else if ( ! isUsedInConditional( node.parent ) ) { context.report( { node, messageId: 'usedOutsideConditional', @@ -113,15 +139,23 @@ module.exports = { } if ( - node.parent.object.type !== 'Identifier' || + node.parent.object.type === 'Identifier' && node.parent.object.name !== 'globalThis' ) { context.report( { node, messageId: 'usedWithoutGlobalThis', data: { name: node.value }, + fix( fixer ) { + if ( node.parent.object.name === 'window' ) { + return fixer.replaceText( + node.parent, + `globalThis.${ node.value }` + ); + } + }, } ); - } else if ( ! isUsedInConditional( node ) ) { + } else if ( ! isUsedInConditional( node.parent ) ) { context.report( { node, messageId: 'usedOutsideConditional', From 8543511e73cdcbf022e1dcf54bea69c12df0b77e Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 21:56:09 +0200 Subject: [PATCH 25/40] Fix warning package lints --- packages/warning/src/index.js | 1 + packages/warning/src/test/index.js | 13 ++++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/warning/src/index.js b/packages/warning/src/index.js index 934fe401eb464..5744e99d94fd2 100644 --- a/packages/warning/src/index.js +++ b/packages/warning/src/index.js @@ -4,6 +4,7 @@ import { logged } from './utils'; function isDev() { + // eslint-disable-next-line @wordpress/wp-global-usage return globalThis.SCRIPT_DEBUG === true; } diff --git a/packages/warning/src/test/index.js b/packages/warning/src/test/index.js index a32e5f1e0fae4..5fdf67b05360c 100644 --- a/packages/warning/src/test/index.js +++ b/packages/warning/src/test/index.js @@ -4,28 +4,31 @@ import warning from '..'; import { logged } from '../utils'; +// eslint-disable-next-line eslint-comments/disable-enable-pair +/* eslint-disable @wordpress/wp-global-usage */ + describe( 'warning', () => { - const initialScriptDebug = global.SCRIPT_DEBUG; + const initialScriptDebug = globalThis.SCRIPT_DEBUG; afterEach( () => { - global.SCRIPT_DEBUG = initialScriptDebug; + globalThis.SCRIPT_DEBUG = initialScriptDebug; logged.clear(); } ); it( 'logs to console.warn when SCRIPT_DEBUG is set to `true`', () => { - global.SCRIPT_DEBUG = true; + globalThis.SCRIPT_DEBUG = true; warning( 'warning' ); expect( console ).toHaveWarnedWith( 'warning' ); } ); it( 'does not log to console.warn if SCRIPT_DEBUG not set to `true`', () => { - global.SCRIPT_DEBUG = false; + globalThis.SCRIPT_DEBUG = false; warning( 'warning' ); expect( console ).not.toHaveWarned(); } ); it( 'should show a message once', () => { - global.SCRIPT_DEBUG = true; + globalThis.SCRIPT_DEBUG = true; warning( 'warning' ); warning( 'warning' ); From 099a809eb0e04d549d36a2888eab4b2f4d07807d Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 21:57:49 +0200 Subject: [PATCH 26/40] Fix test file --- packages/jest-preset-default/scripts/setup-globals.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/jest-preset-default/scripts/setup-globals.js b/packages/jest-preset-default/scripts/setup-globals.js index abd99f620dc89..37922a3302e70 100644 --- a/packages/jest-preset-default/scripts/setup-globals.js +++ b/packages/jest-preset-default/scripts/setup-globals.js @@ -1,5 +1,6 @@ // Run all tests with development tools enabled. -global.SCRIPT_DEBUG = true; +// eslint-disable-next-line @wordpress/wp-global-usage +globalThis.SCRIPT_DEBUG = true; // These are necessary to load TinyMCE successfully. global.URL = window.URL; From ab3527d803db3354ac35de13f983dbdb4733d169 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 22:01:16 +0200 Subject: [PATCH 27/40] Update docs --- docs/contributors/code/coding-guidelines.md | 8 +++--- docs/how-to-guides/feature-flags.md | 29 ++++++++++++--------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/docs/contributors/code/coding-guidelines.md b/docs/contributors/code/coding-guidelines.md index 06f86715a65a0..d89df5876e380 100644 --- a/docs/contributors/code/coding-guidelines.md +++ b/docs/contributors/code/coding-guidelines.md @@ -141,9 +141,9 @@ An **plugin-only API** is one which is planned for eventual public availability, Plugin-only APIs are excluded from WordPress Core and only available in the Gutenberg Plugin: ```js -// Using process.env.IS_GUTENBERG_PLUGIN allows Webpack to exclude this +// Using globalThis.IS_GUTENBERG_PLUGIN allows Webpack to exclude this // export from WordPress core: -if ( process.env.IS_GUTENBERG_PLUGIN ) { +if ( globalThis.IS_GUTENBERG_PLUGIN ) { export { doSomethingExciting } from './api'; } ``` @@ -448,8 +448,8 @@ lock( privateApis, { privateEverywhere, privateInCorePublicInPlugin } ); // The privateInCorePublicInPlugin function is explicitly exported, // but this export will not be merged into WordPress core thanks to -// the process.env.IS_GUTENBERG_PLUGIN check. -if ( process.env.IS_GUTENBERG_PLUGIN ) { +// the globalThis.IS_GUTENBERG_PLUGIN check. +if ( globalThis.IS_GUTENBERG_PLUGIN ) { export const privateInCorePublicInPlugin = unlock( privateApis ).privateInCorePublicInPlugin; } diff --git a/docs/how-to-guides/feature-flags.md b/docs/how-to-guides/feature-flags.md index 5855f93f8ed9f..c253ffb54e7b9 100644 --- a/docs/how-to-guides/feature-flags.md +++ b/docs/how-to-guides/feature-flags.md @@ -2,9 +2,9 @@ 'Feature flags' are variables that allow you to prevent specific code in the Gutenberg project from being shipped to WordPress core, and to run certain experimental features only in the plugin. -## Introducing `process.env.IS_GUTENBERG_PLUGIN` +## Introducing `globalThis.IS_GUTENBERG_PLUGIN` -The `process.env.IS_GUTENBERG_PLUGIN` is an environment variable whose value 'flags' whether code is running within the Gutenberg plugin. +The `globalThis.IS_GUTENBERG_PLUGIN` is an environment variable whose value 'flags' whether code is running within the Gutenberg plugin. When the codebase is built for the plugin, this variable will be set to `true`. When building for WordPress core, it will be set to `false` or `undefined`. @@ -19,8 +19,9 @@ function myPluginOnlyFeature() { // implementation } -export const pluginOnlyFeature = - process.env.IS_GUTENBERG_PLUGIN ? myPluginOnlyFeature : undefined; +export const pluginOnlyFeature = globalThis.IS_GUTENBERG_PLUGIN + ? myPluginOnlyFeature + : undefined; ``` In the above example, the `pluginOnlyFeature` export will be `undefined` in non-plugin environments such as WordPress core. @@ -32,37 +33,39 @@ If you're attempting to import and call a plugin-only feature, be sure to wrap t ```js import { pluginOnlyFeature } from '@wordpress/foo'; -if ( process.env.IS_GUTENBERG_PLUGIN ) { +if ( globalThis.IS_GUTENBERG_PLUGIN ) { pluginOnlyFeature(); } ``` ## How it works -During the webpack build, instances of `process.env.IS_GUTENBERG_PLUGIN` will be replaced using webpack's [define plugin](https://webpack.js.org/plugins/define-plugin/). +During the webpack build, instances of `globalThis.IS_GUTENBERG_PLUGIN` will be replaced using webpack's [define plugin](https://webpack.js.org/plugins/define-plugin/). For example, in the following code – ```js -if ( process.env.IS_GUTENBERG_PLUGIN ) { +if ( globalThis.IS_GUTENBERG_PLUGIN ) { pluginOnlyFeature(); } ``` -– the variable `process.env.IS_GUTENBERG_PLUGIN` will be replaced with the boolean `true` during the plugin-only build: +– the variable `globalThis.IS_GUTENBERG_PLUGIN` will be replaced with the boolean `true` during the plugin-only build: ```js -if ( true ) { // Wepack has replaced `process.env.IS_GUTENBERG_PLUGIN` with `true` +if ( true ) { + // Wepack has replaced `globalThis.IS_GUTENBERG_PLUGIN` with `true` pluginOnlyFeature(); } ``` This ensures that code within the body of the `if` statement will always be executed. -In WordPress core, the `process.env.IS_GUTENBERG_PLUGIN` variable is replaced with `undefined`. The built code looks like this: +In WordPress core, the `globalThis.IS_GUTENBERG_PLUGIN` variable is replaced with `undefined`. The built code looks like this: ```js -if ( undefined ) { // Wepack has replaced `process.env.IS_GUTENBERG_PLUGIN` with `undefined` +if ( undefined ) { + // Wepack has replaced `globalThis.IS_GUTENBERG_PLUGIN` with `undefined` pluginOnlyFeature(); } ``` @@ -71,7 +74,7 @@ if ( undefined ) { // Wepack has replaced `process.env.IS_GUTENBERG_PLUGIN` with ### Dead code elimination -For production builds, webpack ['minifies'](https://en.wikipedia.org/wiki/Minification_(programming)) the code, removing as much unnecessary JavaScript as it can. +For production builds, webpack ['minifies']() the code, removing as much unnecessary JavaScript as it can. One of the steps involves something known as 'dead code elimination'. For example, when the following code is encountered, webpack determines that the surrounding `if` statement is unnecessary: @@ -99,6 +102,6 @@ In this case, the minification process will remove the entire `if` statement inc ## Frequently asked questions -### Why shouldn't I assign the result of an expression involving `IS_GUTENBERG_PLUGIN` to a variable, e.g. `const isMyFeatureActive = process.env.IS_GUTENBERG_PLUGIN === 2`? +### Why shouldn't I assign the result of an expression involving `IS_GUTENBERG_PLUGIN` to a variable, e.g. `const isMyFeatureActive = globalThis.IS_GUTENBERG_PLUGIN === 2`? Introducing complexity may prevent webpack's minifier from identifying and therefore eliminating dead code. Therefore it is recommended to use the examples in this document to ensure your feature flag functions as intended. For further details, see the [Dead Code Elimination](#dead-code-elimination) section. From 1b65e95b74adb4977630bd9a9ceca8e4adecb678 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 22:05:26 +0200 Subject: [PATCH 28/40] fix IS_WORDPRESS_CORE --- .../rules/__tests__/no-wp-process-env.js | 4 ++-- .../eslint-plugin/rules/__tests__/wp-global-usage.js | 12 +++++++++++- packages/eslint-plugin/rules/no-wp-process-env.js | 2 +- packages/eslint-plugin/rules/wp-global-usage.js | 2 +- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/eslint-plugin/rules/__tests__/no-wp-process-env.js b/packages/eslint-plugin/rules/__tests__/no-wp-process-env.js index 5b97e04c43436..330ed560aea99 100644 --- a/packages/eslint-plugin/rules/__tests__/no-wp-process-env.js +++ b/packages/eslint-plugin/rules/__tests__/no-wp-process-env.js @@ -40,9 +40,9 @@ ruleTester.run( 'no-wp-process-env', rule, { output: 'globalThis.SCRIPT_DEBUG', }, { - code: 'process.env.IS_WORDPRESS', + code: 'process.env.IS_WORDPRESS_CORE', errors: [ { messageId: 'useGlobalThis' } ], - output: 'globalThis.IS_WORDPRESS', + output: 'globalThis.IS_WORDPRESS_CORE', }, { code: `process['env']["IS_GUTENBERG_PLUGIN"]`, diff --git a/packages/eslint-plugin/rules/__tests__/wp-global-usage.js b/packages/eslint-plugin/rules/__tests__/wp-global-usage.js index fed530f0bb12a..d553b358f27b9 100644 --- a/packages/eslint-plugin/rules/__tests__/wp-global-usage.js +++ b/packages/eslint-plugin/rules/__tests__/wp-global-usage.js @@ -19,7 +19,7 @@ ruleTester.run( 'wp-global-usage', rule, { { code: "const text = 'SCRIPT_DEBUG'" }, { code: 'const config = { SCRIPT_DEBUG: true }' }, { code: `if ( globalThis.IS_GUTENBERG_PLUGIN ) {}` }, - { code: `if ( globalThis.IS_WORDPRESS ) {}` }, + { code: `if ( globalThis.IS_WORDPRESS_CORE ) {}` }, { code: `if ( globalThis.SCRIPT_DEBUG ) {}` }, { code: `if ( ! globalThis.IS_GUTENBERG_PLUGIN ) {}` }, { @@ -68,6 +68,16 @@ ruleTester.run( 'wp-global-usage', rule, { ], output: 'if ( globalThis.SCRIPT_DEBUG ) {}', }, + { + code: 'if ( IS_WORDPRESS_CORE ) {}', + errors: [ + { + messageId: 'usedWithoutGlobalThis', + data: { name: 'IS_WORDPRESS_CORE' }, + }, + ], + output: 'if ( globalThis.IS_WORDPRESS_CORE ) {}', + }, { code: "if ( window[ 'IS_GUTENBERG_PLUGIN' ] ) {}", errors: [ diff --git a/packages/eslint-plugin/rules/no-wp-process-env.js b/packages/eslint-plugin/rules/no-wp-process-env.js index 987e1813a6e6a..55aca44b92ba7 100644 --- a/packages/eslint-plugin/rules/no-wp-process-env.js +++ b/packages/eslint-plugin/rules/no-wp-process-env.js @@ -2,7 +2,7 @@ const NAMES = new Set( /** @type {const} */ ( [ 'GUTENBERG_PHASE', 'IS_GUTENBERG_PLUGIN', - 'IS_WORDPRESS', + 'IS_WORDPRESS_CORE', 'SCRIPT_DEBUG', ] ) ); diff --git a/packages/eslint-plugin/rules/wp-global-usage.js b/packages/eslint-plugin/rules/wp-global-usage.js index e278f48fceef3..c6c75d9933123 100644 --- a/packages/eslint-plugin/rules/wp-global-usage.js +++ b/packages/eslint-plugin/rules/wp-global-usage.js @@ -1,7 +1,7 @@ const NAMES = new Set( /** @type {const} */ ( [ 'IS_GUTENBERG_PLUGIN', - 'IS_WORDPRESS', + 'IS_WORDPRESS_CORE', 'SCRIPT_DEBUG', ] ) ); From d654e8691b902a029e6cd2ed81aaec921746f3d0 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 22:14:03 +0200 Subject: [PATCH 29/40] eslint plugin --- .../rules/__tests__/wp-global-usage.js | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/eslint-plugin/rules/__tests__/wp-global-usage.js b/packages/eslint-plugin/rules/__tests__/wp-global-usage.js index d553b358f27b9..9d3dc9b2a29d7 100644 --- a/packages/eslint-plugin/rules/__tests__/wp-global-usage.js +++ b/packages/eslint-plugin/rules/__tests__/wp-global-usage.js @@ -18,10 +18,11 @@ ruleTester.run( 'wp-global-usage', rule, { valid: [ { code: "const text = 'SCRIPT_DEBUG'" }, { code: 'const config = { SCRIPT_DEBUG: true }' }, - { code: `if ( globalThis.IS_GUTENBERG_PLUGIN ) {}` }, - { code: `if ( globalThis.IS_WORDPRESS_CORE ) {}` }, - { code: `if ( globalThis.SCRIPT_DEBUG ) {}` }, - { code: `if ( ! globalThis.IS_GUTENBERG_PLUGIN ) {}` }, + { code: 'if ( globalThis.IS_GUTENBERG_PLUGIN ) {}' }, + { code: 'if ( globalThis.IS_WORDPRESS_CORE ) {}' }, + { code: 'if ( globalThis.SCRIPT_DEBUG ) {}' }, + { code: 'if ( process.env.SCRIPT_DEBUG ) {}' }, + { code: 'if ( ! globalThis.IS_GUTENBERG_PLUGIN ) {}' }, { // Ensure whitespace is ok. code: `if ( @@ -29,8 +30,8 @@ ruleTester.run( 'wp-global-usage', rule, { IS_GUTENBERG_PLUGIN ) {}`, }, - { code: `const test = globalThis.IS_GUTENBERG_PLUGIN ? foo : bar` }, - { code: `const test = ! globalThis.IS_GUTENBERG_PLUGIN ? bar : foo` }, + { code: 'const test = globalThis.IS_GUTENBERG_PLUGIN ? foo : bar' }, + { code: 'const test = ! globalThis.IS_GUTENBERG_PLUGIN ? bar : foo' }, { // Ensure whitespace is ok. code: `const test = ! globalThis. @@ -89,7 +90,7 @@ ruleTester.run( 'wp-global-usage', rule, { output: 'if ( globalThis.IS_GUTENBERG_PLUGIN ) {}', }, { - code: `if ( true ) { globalThis.IS_GUTENBERG_PLUGIN === 2 }`, + code: 'if ( true ) { globalThis.IS_GUTENBERG_PLUGIN === 2 }', errors: [ { messageId: 'usedOutsideConditional', @@ -98,7 +99,7 @@ ruleTester.run( 'wp-global-usage', rule, { ], }, { - code: `if ( globalThis.IS_GUTENBERG_PLUGIN === 2 ) {}`, + code: 'if ( globalThis.IS_GUTENBERG_PLUGIN === 2 ) {}', errors: [ { messageId: 'usedOutsideConditional', @@ -107,7 +108,7 @@ ruleTester.run( 'wp-global-usage', rule, { ], }, { - code: `if ( true || globalThis.IS_GUTENBERG_PLUGIN === 2 ) {}`, + code: 'if ( true || globalThis.IS_GUTENBERG_PLUGIN === 2 ) {}', errors: [ { messageId: 'usedOutsideConditional', @@ -116,7 +117,7 @@ ruleTester.run( 'wp-global-usage', rule, { ], }, { - code: `const isFeatureActive = globalThis.IS_GUTENBERG_PLUGIN;`, + code: 'const isFeatureActive = globalThis.IS_GUTENBERG_PLUGIN;', errors: [ { messageId: 'usedOutsideConditional', From 6f3e97b6573236055c74790063ed2da6abbc61b7 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 13 May 2024 22:14:31 +0200 Subject: [PATCH 30/40] lint disable --- test/unit/config/gutenberg-env.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit/config/gutenberg-env.js b/test/unit/config/gutenberg-env.js index 986edf55f34f9..f6ea2d16c1c79 100644 --- a/test/unit/config/gutenberg-env.js +++ b/test/unit/config/gutenberg-env.js @@ -4,6 +4,7 @@ * to ensure the Gutenberg plugin can be cleanly merged into * WordPress core. */ +// eslint-disable-next-line @wordpress/wp-global-usage globalThis.IS_WORDPRESS_CORE = true; // Inject the `IS_GUTENBERG_PLUGIN` global, used for feature flagging. From 18a489ce352c29ea68d3b402eda3022fd58f95b9 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Tue, 14 May 2024 12:39:27 +0200 Subject: [PATCH 31/40] Add gutenberg-phase changelog --- packages/eslint-plugin/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 9b0df19c17932..682fac4e8f1f0 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -6,6 +6,7 @@ - `@wordpress/is-gutenberg-plugin` rule has been replaced by `@wordpress/wp-global-usage` ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). - `@wordpress/wp-process-env` rule has been added and included in the recommended configurations ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). +- `@wordpress/gutenberg-phase` rule has been removed (deprecated in v10.0.0) ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). ## 18.1.0 (2024-05-16) From b212ea0d063a6a14fa63d6cfd981f28c7527d1b0 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 15 May 2024 13:13:37 +0200 Subject: [PATCH 32/40] Fix typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Greg Ziółkowski --- docs/how-to-guides/feature-flags.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/feature-flags.md b/docs/how-to-guides/feature-flags.md index c253ffb54e7b9..0248e19f4d221 100644 --- a/docs/how-to-guides/feature-flags.md +++ b/docs/how-to-guides/feature-flags.md @@ -65,7 +65,7 @@ In WordPress core, the `globalThis.IS_GUTENBERG_PLUGIN` variable is replaced wit ```js if ( undefined ) { - // Wepack has replaced `globalThis.IS_GUTENBERG_PLUGIN` with `undefined` + // Webpack has replaced `globalThis.IS_GUTENBERG_PLUGIN` with `undefined` pluginOnlyFeature(); } ``` From 4e81a6f5349efefb2da994ed3a06c25bf34fc233 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 15 May 2024 13:36:52 +0200 Subject: [PATCH 33/40] Fix url encoding of parens --- docs/how-to-guides/feature-flags.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/feature-flags.md b/docs/how-to-guides/feature-flags.md index 0248e19f4d221..dc9dbfe1e038b 100644 --- a/docs/how-to-guides/feature-flags.md +++ b/docs/how-to-guides/feature-flags.md @@ -74,7 +74,7 @@ if ( undefined ) { ### Dead code elimination -For production builds, webpack ['minifies']() the code, removing as much unnecessary JavaScript as it can. +For production builds, webpack ['minifies'](https://en.wikipedia.org/wiki/Minification_%28programming%29) the code, removing as much unnecessary JavaScript as it can. One of the steps involves something known as 'dead code elimination'. For example, when the following code is encountered, webpack determines that the surrounding `if` statement is unnecessary: From b52b7d885b9bbb673e97a974d64fab6d20f69fcf Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 15 May 2024 13:42:14 +0200 Subject: [PATCH 34/40] Revert unrelated markdown changes --- docs/how-to-guides/feature-flags.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/feature-flags.md b/docs/how-to-guides/feature-flags.md index dc9dbfe1e038b..371062111d475 100644 --- a/docs/how-to-guides/feature-flags.md +++ b/docs/how-to-guides/feature-flags.md @@ -74,7 +74,7 @@ if ( undefined ) { ### Dead code elimination -For production builds, webpack ['minifies'](https://en.wikipedia.org/wiki/Minification_%28programming%29) the code, removing as much unnecessary JavaScript as it can. +For production builds, webpack ['minifies'](https://en.wikipedia.org/wiki/Minification_(programming)) the code, removing as much unnecessary JavaScript as it can. One of the steps involves something known as 'dead code elimination'. For example, when the following code is encountered, webpack determines that the surrounding `if` statement is unnecessary: From 6cc5653b3d6a7c701ab80f4da55a7f9d7fc16cc9 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 15 May 2024 17:42:24 +0200 Subject: [PATCH 35/40] Update stale code example --- docs/how-to-guides/feature-flags.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/feature-flags.md b/docs/how-to-guides/feature-flags.md index 371062111d475..11c5ae881337d 100644 --- a/docs/how-to-guides/feature-flags.md +++ b/docs/how-to-guides/feature-flags.md @@ -102,6 +102,6 @@ In this case, the minification process will remove the entire `if` statement inc ## Frequently asked questions -### Why shouldn't I assign the result of an expression involving `IS_GUTENBERG_PLUGIN` to a variable, e.g. `const isMyFeatureActive = globalThis.IS_GUTENBERG_PLUGIN === 2`? +### Why shouldn't I assign the result of an expression involving `IS_GUTENBERG_PLUGIN` to a variable, e.g. `const isMyFeatureActive = ! Object.is( undefined, globalThis.IS_GUTENBERG_PLUGIN )`? Introducing complexity may prevent webpack's minifier from identifying and therefore eliminating dead code. Therefore it is recommended to use the examples in this document to ensure your feature flag functions as intended. For further details, see the [Dead Code Elimination](#dead-code-elimination) section. From db956ccc79a049952dd68c1d382b3362f9743e2e Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Tue, 21 May 2024 16:35:36 +0200 Subject: [PATCH 36/40] Apply autofix --- packages/block-library/src/index.js | 32 +++++++++---------- .../src/api/parser/convert-legacy-block.js | 2 +- packages/core-data/src/actions.js | 2 +- packages/core-data/src/entities.js | 4 +-- packages/core-data/src/resolvers.js | 2 +- packages/customize-widgets/src/index.js | 2 +- .../src/components/visual-editor/index.js | 2 +- packages/edit-post/src/index.js | 2 +- packages/edit-site/src/index.js | 2 +- packages/edit-widgets/src/index.js | 2 +- packages/editor/src/bindings/index.js | 2 +- .../src/components/post-actions/actions.js | 2 +- packages/interactivity-router/src/index.ts | 8 ++--- packages/interactivity/src/utils.ts | 5 ++- packages/private-apis/src/implementation.js | 2 +- .../full-content/full-content.test.js | 2 +- 16 files changed, 38 insertions(+), 35 deletions(-) diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js index 9cb2f44d05eb9..56365c87a268f 100644 --- a/packages/block-library/src/index.js +++ b/packages/block-library/src/index.js @@ -314,21 +314,21 @@ export const registerCoreBlocks = ( * __experimentalRegisterExperimentalCoreBlocks( settings ); * ``` */ -export const __experimentalRegisterExperimentalCoreBlocks = process.env - .IS_GUTENBERG_PLUGIN - ? ( { enableFSEBlocks } = {} ) => { - const enabledExperiments = [ enableFSEBlocks ? 'fse' : null ]; - getAllBlocks() - .filter( ( { metadata } ) => - isBlockMetadataExperimental( metadata ) - ) - .filter( - ( { metadata: { __experimental } } ) => - __experimental === true || - enabledExperiments.includes( __experimental ) - ) - .forEach( ( { init } ) => init() ); - } - : undefined; +export const __experimentalRegisterExperimentalCoreBlocks = + globalThis.IS_GUTENBERG_PLUGIN + ? ( { enableFSEBlocks } = {} ) => { + const enabledExperiments = [ enableFSEBlocks ? 'fse' : null ]; + getAllBlocks() + .filter( ( { metadata } ) => + isBlockMetadataExperimental( metadata ) + ) + .filter( + ( { metadata: { __experimental } } ) => + __experimental === true || + enabledExperiments.includes( __experimental ) + ) + .forEach( ( { init } ) => init() ); + } + : undefined; export { privateApis } from './private-apis'; diff --git a/packages/blocks/src/api/parser/convert-legacy-block.js b/packages/blocks/src/api/parser/convert-legacy-block.js index c828a3f5db6c4..8396b98109792 100644 --- a/packages/blocks/src/api/parser/convert-legacy-block.js +++ b/packages/blocks/src/api/parser/convert-legacy-block.js @@ -79,7 +79,7 @@ export function convertLegacyBlockNameAndAttributes( name, attributes ) { // The following code is only relevant for the Gutenberg plugin. // It's a stand-alone if statement for dead-code elimination. - if ( process.env.IS_GUTENBERG_PLUGIN ) { + if ( globalThis.IS_GUTENBERG_PLUGIN ) { // Convert pattern overrides added during experimental phase. // Only four blocks were supported initially. // These checks can be removed in WordPress 6.6. diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index 454250e8ad13c..be4d12f0cb9ef 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -396,7 +396,7 @@ export const editEntityRecord = }, {} ), }; if ( window.__experimentalEnableSync && entityConfig.syncConfig ) { - if ( process.env.IS_GUTENBERG_PLUGIN ) { + if ( globalThis.IS_GUTENBERG_PLUGIN ) { const objectId = entityConfig.getSyncObjectId( recordId ); getSyncProvider().update( entityConfig.syncObjectType + '--edit', diff --git a/packages/core-data/src/entities.js b/packages/core-data/src/entities.js index e91744110faf3..8d09402087cf9 100644 --- a/packages/core-data/src/entities.js +++ b/packages/core-data/src/entities.js @@ -485,7 +485,7 @@ export const getOrLoadEntitiesConfig = if ( configs?.length > 0 && hasConfig ) { if ( window.__experimentalEnableSync ) { - if ( process.env.IS_GUTENBERG_PLUGIN ) { + if ( globalThis.IS_GUTENBERG_PLUGIN ) { registerSyncConfigs( configs ); } } @@ -506,7 +506,7 @@ export const getOrLoadEntitiesConfig = configs = await loader.loadEntities(); if ( window.__experimentalEnableSync ) { - if ( process.env.IS_GUTENBERG_PLUGIN ) { + if ( globalThis.IS_GUTENBERG_PLUGIN ) { registerSyncConfigs( configs ); } } diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index f040e548e6160..3e5373eda6d6a 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -81,7 +81,7 @@ export const getEntityRecord = entityConfig.syncConfig && ! query ) { - if ( process.env.IS_GUTENBERG_PLUGIN ) { + if ( globalThis.IS_GUTENBERG_PLUGIN ) { const objectId = entityConfig.getSyncObjectId( key ); // Loads the persisted document. diff --git a/packages/customize-widgets/src/index.js b/packages/customize-widgets/src/index.js index 5b438cac86f49..9afda775a1701 100644 --- a/packages/customize-widgets/src/index.js +++ b/packages/customize-widgets/src/index.js @@ -61,7 +61,7 @@ export function initialize( editorName, blockEditorSettings ) { } ); registerCoreBlocks( coreBlocks ); registerLegacyWidgetBlock(); - if ( process.env.IS_GUTENBERG_PLUGIN ) { + if ( globalThis.IS_GUTENBERG_PLUGIN ) { __experimentalRegisterExperimentalCoreBlocks( { enableFSEBlocks: ENABLE_EXPERIMENTAL_FSE_BLOCKS, } ); diff --git a/packages/edit-post/src/components/visual-editor/index.js b/packages/edit-post/src/components/visual-editor/index.js index 3bb50999c2a92..c1e13d79f2941 100644 --- a/packages/edit-post/src/components/visual-editor/index.js +++ b/packages/edit-post/src/components/visual-editor/index.js @@ -24,7 +24,7 @@ import { usePaddingAppender } from './use-padding-appender'; const { EditorCanvas } = unlock( editorPrivateApis ); -const isGutenbergPlugin = process.env.IS_GUTENBERG_PLUGIN ? true : false; +const isGutenbergPlugin = globalThis.IS_GUTENBERG_PLUGIN ? true : false; export default function VisualEditor( { styles } ) { const { diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index 0a2d17a344e47..1e0b3fe7d4d6f 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -80,7 +80,7 @@ export function initializeEditor( registerCoreBlocks(); registerLegacyWidgetBlock( { inserter: false } ); registerWidgetGroupBlock( { inserter: false } ); - if ( process.env.IS_GUTENBERG_PLUGIN ) { + if ( globalThis.IS_GUTENBERG_PLUGIN ) { __experimentalRegisterExperimentalCoreBlocks( { enableFSEBlocks: settings.__unstableEnableFullSiteEditingBlocks, } ); diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js index f42842f504e54..41fc0a1985fde 100644 --- a/packages/edit-site/src/index.js +++ b/packages/edit-site/src/index.js @@ -42,7 +42,7 @@ export function initializeEditor( id, settings ) { dispatch( blocksStore ).setFreeformFallbackBlockName( 'core/html' ); registerLegacyWidgetBlock( { inserter: false } ); registerWidgetGroupBlock( { inserter: false } ); - if ( process.env.IS_GUTENBERG_PLUGIN ) { + if ( globalThis.IS_GUTENBERG_PLUGIN ) { __experimentalRegisterExperimentalCoreBlocks( { enableFSEBlocks: true, } ); diff --git a/packages/edit-widgets/src/index.js b/packages/edit-widgets/src/index.js index eb87d22fefef9..2374ec19dabd7 100644 --- a/packages/edit-widgets/src/index.js +++ b/packages/edit-widgets/src/index.js @@ -73,7 +73,7 @@ export function initializeEditor( id, settings ) { dispatch( blocksStore ).reapplyBlockTypeFilters(); registerCoreBlocks( coreBlocks ); registerLegacyWidgetBlock(); - if ( process.env.IS_GUTENBERG_PLUGIN ) { + if ( globalThis.IS_GUTENBERG_PLUGIN ) { __experimentalRegisterExperimentalCoreBlocks( { enableFSEBlocks: ENABLE_EXPERIMENTAL_FSE_BLOCKS, } ); diff --git a/packages/editor/src/bindings/index.js b/packages/editor/src/bindings/index.js index ce77b87ebc7a5..5824cdde022cc 100644 --- a/packages/editor/src/bindings/index.js +++ b/packages/editor/src/bindings/index.js @@ -13,6 +13,6 @@ import postMeta from './post-meta'; const { registerBlockBindingsSource } = unlock( dispatch( blocksStore ) ); registerBlockBindingsSource( postMeta ); -if ( process.env.IS_GUTENBERG_PLUGIN ) { +if ( globalThis.IS_GUTENBERG_PLUGIN ) { registerBlockBindingsSource( patternOverrides ); } diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 926d9b92fe5d1..f6a28c3421356 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -1116,7 +1116,7 @@ export function usePostActions( postType, onActionPerformed ) { const actions = [ postTypeObject?.viewable && viewPostAction, postRevisionsAction, - process.env.IS_GUTENBERG_PLUGIN + globalThis.IS_GUTENBERG_PLUGIN ? ! isTemplateOrTemplatePart && ! isPattern && duplicatePostAction diff --git a/packages/interactivity-router/src/index.ts b/packages/interactivity-router/src/index.ts index 09f484131b62e..49c793267d379 100644 --- a/packages/interactivity-router/src/index.ts +++ b/packages/interactivity-router/src/index.ts @@ -86,7 +86,7 @@ const regionsToVdom: RegionsToVdom = async ( dom, { vdom } = {} ) => { const regions = { body: undefined }; let head: HTMLElement[]; // @ts-ignore - if ( process.env.IS_GUTENBERG_PLUGIN ) { + if ( globalThis.IS_GUTENBERG_PLUGIN ) { if ( navigationMode === 'fullPage' ) { head = await fetchHeadAssets( dom, headElements ); regions.body = vdom @@ -112,7 +112,7 @@ const regionsToVdom: RegionsToVdom = async ( dom, { vdom } = {} ) => { const renderRegions = ( page: Page ) => { batch( () => { // @ts-ignore - if ( process.env.IS_GUTENBERG_PLUGIN ) { + if ( globalThis.IS_GUTENBERG_PLUGIN ) { if ( navigationMode === 'fullPage' ) { // Once this code is tested and more mature, the head should be updated for region based navigation as well. updateHead( page.head ); @@ -170,7 +170,7 @@ window.addEventListener( 'popstate', async () => { // Once this code is tested and more mature, the head should be updated for // region based navigation as well. // @ts-ignore -if ( process.env.IS_GUTENBERG_PLUGIN ) { +if ( globalThis.IS_GUTENBERG_PLUGIN ) { if ( navigationMode === 'fullPage' ) { // Cache the scripts. Has to be called before fetching the assets. [].map.call( document.querySelectorAll( 'script[src]' ), ( script ) => { @@ -368,7 +368,7 @@ export const { state, actions } = store( 'core/router', { // Add click and prefetch to all links. // @ts-ignore -if ( process.env.IS_GUTENBERG_PLUGIN ) { +if ( globalThis.IS_GUTENBERG_PLUGIN ) { if ( navigationMode === 'fullPage' ) { // Navigate on click. document.addEventListener( diff --git a/packages/interactivity/src/utils.ts b/packages/interactivity/src/utils.ts index ecf22899309e9..b1cacf4ab8e35 100644 --- a/packages/interactivity/src/utils.ts +++ b/packages/interactivity/src/utils.ts @@ -317,7 +317,10 @@ const logged: Set< string > = new Set(); */ export const warn = ( message: string ): void => { // @ts-expect-error - if ( typeof SCRIPT_DEBUG !== 'undefined' && SCRIPT_DEBUG === true ) { + if ( + typeof globalThis.SCRIPT_DEBUG !== 'undefined' && + globalThis.SCRIPT_DEBUG === true + ) { if ( logged.has( message ) ) { return; } diff --git a/packages/private-apis/src/implementation.js b/packages/private-apis/src/implementation.js index a31fd91ce094d..bea820226fe33 100644 --- a/packages/private-apis/src/implementation.js +++ b/packages/private-apis/src/implementation.js @@ -66,7 +66,7 @@ let allowReRegistration; // Let's default to true, then. Try/catch will fall back to "true" even if the // environment variable is not explicitly defined. try { - allowReRegistration = process.env.IS_WORDPRESS_CORE ? false : true; + allowReRegistration = globalThis.IS_WORDPRESS_CORE ? false : true; } catch ( error ) { allowReRegistration = true; } diff --git a/test/integration/full-content/full-content.test.js b/test/integration/full-content/full-content.test.js index f825de0477144..4522dd7b88e45 100644 --- a/test/integration/full-content/full-content.test.js +++ b/test/integration/full-content/full-content.test.js @@ -82,7 +82,7 @@ describe( 'full post content fixture', () => { formSubmissionNotification, ] ); - if ( process.env.IS_GUTENBERG_PLUGIN ) { + if ( globalThis.IS_GUTENBERG_PLUGIN ) { __experimentalRegisterExperimentalCoreBlocks( { enableFSEBlocks: true, } ); From 6f02f98f95741dd8a62c372e4fbc71046e850f9c Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Tue, 21 May 2024 16:36:46 +0200 Subject: [PATCH 37/40] Fix the automatic fixes --- packages/interactivity/src/utils.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/interactivity/src/utils.ts b/packages/interactivity/src/utils.ts index b1cacf4ab8e35..e709ba1ce3b0e 100644 --- a/packages/interactivity/src/utils.ts +++ b/packages/interactivity/src/utils.ts @@ -316,11 +316,7 @@ const logged: Set< string > = new Set(); * @param message Message to show in the warning. */ export const warn = ( message: string ): void => { - // @ts-expect-error - if ( - typeof globalThis.SCRIPT_DEBUG !== 'undefined' && - globalThis.SCRIPT_DEBUG === true - ) { + if ( globalThis.SCRIPT_DEBUG ) { if ( logged.has( message ) ) { return; } From 89118b1b827d924176534ad3d3878621749f446c Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Tue, 21 May 2024 16:45:09 +0200 Subject: [PATCH 38/40] Cleanup unused ts-ignores --- packages/interactivity-router/src/index.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/interactivity-router/src/index.ts b/packages/interactivity-router/src/index.ts index 49c793267d379..79b67eeb98e65 100644 --- a/packages/interactivity-router/src/index.ts +++ b/packages/interactivity-router/src/index.ts @@ -85,7 +85,6 @@ const fetchPage = async ( url: string, { html }: { html: string } ) => { const regionsToVdom: RegionsToVdom = async ( dom, { vdom } = {} ) => { const regions = { body: undefined }; let head: HTMLElement[]; - // @ts-ignore if ( globalThis.IS_GUTENBERG_PLUGIN ) { if ( navigationMode === 'fullPage' ) { head = await fetchHeadAssets( dom, headElements ); @@ -111,7 +110,6 @@ const regionsToVdom: RegionsToVdom = async ( dom, { vdom } = {} ) => { // Render all interactive regions contained in the given page. const renderRegions = ( page: Page ) => { batch( () => { - // @ts-ignore if ( globalThis.IS_GUTENBERG_PLUGIN ) { if ( navigationMode === 'fullPage' ) { // Once this code is tested and more mature, the head should be updated for region based navigation as well. @@ -169,7 +167,6 @@ window.addEventListener( 'popstate', async () => { // Initialize the router and cache the initial page using the initial vDOM. // Once this code is tested and more mature, the head should be updated for // region based navigation as well. -// @ts-ignore if ( globalThis.IS_GUTENBERG_PLUGIN ) { if ( navigationMode === 'fullPage' ) { // Cache the scripts. Has to be called before fetching the assets. @@ -367,7 +364,6 @@ export const { state, actions } = store( 'core/router', { } ); // Add click and prefetch to all links. -// @ts-ignore if ( globalThis.IS_GUTENBERG_PLUGIN ) { if ( navigationMode === 'fullPage' ) { // Navigate on click. From f28585c852751e6bf3e910947b05852071ed04e7 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Tue, 21 May 2024 16:53:16 +0200 Subject: [PATCH 39/40] Add breaking changes to affected packages --- packages/block-library/CHANGELOG.md | 4 ++++ packages/blocks/CHANGELOG.md | 4 ++++ packages/components/CHANGELOG.md | 4 ++++ packages/core-data/CHANGELOG.md | 4 ++++ packages/customize-widgets/CHANGELOG.md | 4 ++++ packages/dataviews/CHANGELOG.md | 4 ++++ packages/e2e-tests/CHANGELOG.md | 4 ++++ packages/edit-post/CHANGELOG.md | 4 ++++ packages/edit-site/CHANGELOG.md | 4 ++++ packages/edit-widgets/CHANGELOG.md | 4 ++++ packages/editor/CHANGELOG.md | 4 ++++ packages/interactivity-router/CHANGELOG.md | 4 ++++ packages/interactivity/CHANGELOG.md | 4 ++++ packages/jest-preset-default/CHANGELOG.md | 4 ++++ packages/plugins/CHANGELOG.md | 4 ++++ packages/private-apis/CHANGELOG.md | 4 ++++ packages/scripts/CHANGELOG.md | 1 + packages/warning/CHANGELOG.md | 4 ++++ 18 files changed, 69 insertions(+) diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index c938638b9d06f..f31bd4a85e27a 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). + ## 8.35.0 (2024-05-16) ### Internal diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index 85f09d262242c..c5235ee9b07f8 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). + ## 12.35.0 (2024-05-16) ## 12.34.0 (2024-05-02) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 914e9e771ddff..8f0bb75790397 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). + ### Enhancements - `ComboboxControl`: Introduce Combobox expandOnFocus prop ([#61705](https://github.com/WordPress/gutenberg/pull/61705)). diff --git a/packages/core-data/CHANGELOG.md b/packages/core-data/CHANGELOG.md index 31df8b2074dbd..528c94b9e7fe8 100644 --- a/packages/core-data/CHANGELOG.md +++ b/packages/core-data/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). + ## 6.35.0 (2024-05-16) ## 6.34.0 (2024-05-02) diff --git a/packages/customize-widgets/CHANGELOG.md b/packages/customize-widgets/CHANGELOG.md index 9c2687cf60b9c..d6f184afe9736 100644 --- a/packages/customize-widgets/CHANGELOG.md +++ b/packages/customize-widgets/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). + ## 4.35.0 (2024-05-16) ## 4.34.0 (2024-05-02) diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 711836f69eab2..ba4cd177561df 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). + ## 1.2.0 (2024-05-16) ### Internal diff --git a/packages/e2e-tests/CHANGELOG.md b/packages/e2e-tests/CHANGELOG.md index 1293ba8a6f208..0f38422f84d4c 100644 --- a/packages/e2e-tests/CHANGELOG.md +++ b/packages/e2e-tests/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). + ## 7.29.0 (2024-05-16) ## 7.28.0 (2024-05-02) diff --git a/packages/edit-post/CHANGELOG.md b/packages/edit-post/CHANGELOG.md index 03d6585fbfdf8..763952b71ab60 100644 --- a/packages/edit-post/CHANGELOG.md +++ b/packages/edit-post/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). + ## 7.35.0 (2024-05-16) ### Internal diff --git a/packages/edit-site/CHANGELOG.md b/packages/edit-site/CHANGELOG.md index d2eab07c746da..3437c7c35fd9c 100644 --- a/packages/edit-site/CHANGELOG.md +++ b/packages/edit-site/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). + ## 5.35.0 (2024-05-16) ### Internal diff --git a/packages/edit-widgets/CHANGELOG.md b/packages/edit-widgets/CHANGELOG.md index 61bb76814f4db..1c76fff573a05 100644 --- a/packages/edit-widgets/CHANGELOG.md +++ b/packages/edit-widgets/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). + ## 5.35.0 (2024-05-16) ### Internal diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md index 73b00e61139c8..b33b049d245a4 100644 --- a/packages/editor/CHANGELOG.md +++ b/packages/editor/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). + ## 13.35.0 (2024-05-16) ### Internal diff --git a/packages/interactivity-router/CHANGELOG.md b/packages/interactivity-router/CHANGELOG.md index bae126d002318..496d76e7bdecc 100644 --- a/packages/interactivity-router/CHANGELOG.md +++ b/packages/interactivity-router/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). + ## 1.8.0 (2024-05-16) ## 1.7.0 (2024-05-02) diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index c976f26dc7136..5e2f74bb48d2c 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). + ## 5.7.0 (2024-05-16) ### Enhancements diff --git a/packages/jest-preset-default/CHANGELOG.md b/packages/jest-preset-default/CHANGELOG.md index d709168df3704..6bde10d348a5b 100644 --- a/packages/jest-preset-default/CHANGELOG.md +++ b/packages/jest-preset-default/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). + ## 11.29.0 (2024-05-16) ## 11.28.0 (2024-05-02) diff --git a/packages/plugins/CHANGELOG.md b/packages/plugins/CHANGELOG.md index 7f9cdc62909fa..49ff11a846d8e 100644 --- a/packages/plugins/CHANGELOG.md +++ b/packages/plugins/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). + ## 6.26.0 (2024-05-16) ## 6.25.0 (2024-05-02) diff --git a/packages/private-apis/CHANGELOG.md b/packages/private-apis/CHANGELOG.md index f1564b6ef5db1..07c8caaa3f8fe 100644 --- a/packages/private-apis/CHANGELOG.md +++ b/packages/private-apis/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). + ## 0.40.0 (2024-05-16) ## 0.39.0 (2024-05-02) diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 8c5aa8c623ef0..124a5e99bfdf6 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -5,6 +5,7 @@ ### Breaking Changes - Use React's automatic runtime to transform JSX ([#61692](https://github.com/WordPress/gutenberg/pull/61692)). +- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). ## 27.9.0 (2024-05-16) diff --git a/packages/warning/CHANGELOG.md b/packages/warning/CHANGELOG.md index 90c1ca7e83f6b..6eee478e47dbf 100644 --- a/packages/warning/CHANGELOG.md +++ b/packages/warning/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). + ## 2.58.0 (2024-05-16) ## 2.57.0 (2024-05-02) From 926ab278c9184d94e43b9f571d378946fae39e24 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Tue, 21 May 2024 16:53:29 +0200 Subject: [PATCH 40/40] Autoformat modified changelogs --- packages/block-library/CHANGELOG.md | 2 +- packages/blocks/CHANGELOG.md | 3 ++- packages/core-data/CHANGELOG.md | 3 ++- packages/e2e-tests/CHANGELOG.md | 2 +- packages/interactivity/CHANGELOG.md | 8 ++++---- packages/jest-preset-default/CHANGELOG.md | 2 +- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index f31bd4a85e27a..ee42f9653ad8a 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -88,7 +88,7 @@ ### Breaking Changes -- Updated dependencies to require React 18 ([45235](https://github.com/WordPress/gutenberg/pull/45235)) +- Updated dependencies to require React 18 ([#45235](https://github.com/WordPress/gutenberg/pull/45235)) ## 7.19.0 (2022-11-16) diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index c5235ee9b07f8..db9afca0d285a 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -96,7 +96,8 @@ ## 11.17.0 (2022-09-21) -- The block attribute sources `children` and `node` have been deprecated. Please use the `html` source instead. See https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/ and the core blocks for examples. +- The block attribute sources `children` and `node` have been deprecated. Please use the `html` source instead. See https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/ and the core blocks for examples. + ## 11.16.0 (2022-09-13) ## 11.15.0 (2022-08-24) diff --git a/packages/core-data/CHANGELOG.md b/packages/core-data/CHANGELOG.md index 528c94b9e7fe8..348e1e7ea0e78 100644 --- a/packages/core-data/CHANGELOG.md +++ b/packages/core-data/CHANGELOG.md @@ -101,7 +101,7 @@ ### Breaking Changes -– Add TypeScript types to the built package (via "types": "build-types" in the package.json) +– Add TypeScript types to the built package (via "types": "build-types" in the package.json) ## 4.14.0 (2022-08-24) @@ -136,6 +136,7 @@ ## 4.3.0 (2022-03-23) ### New Features + - The saveEntityRecord, saveEditedEntityRecord, and deleteEntityRecord actions now accept an optional throwOnError option (defaults to false). When set to true, any exceptions occurring when the action was executing are re-thrown, causing dispatch().saveEntityRecord() to reject with an error. ([#39258](https://github.com/WordPress/gutenberg/pull/39258)) - Added support for fetching block patterns and their categories, with the `getBlockPatterns` and `getBlockPatternCategories` selectors. diff --git a/packages/e2e-tests/CHANGELOG.md b/packages/e2e-tests/CHANGELOG.md index 0f38422f84d4c..95cbb721932d5 100644 --- a/packages/e2e-tests/CHANGELOG.md +++ b/packages/e2e-tests/CHANGELOG.md @@ -68,7 +68,7 @@ ### Breaking Changes -- Started requiring Jest v29 instead of v27 as a peer dependency. See [breaking changes in Jest 28](https://jestjs.io/blog/2022/04/25/jest-28) and [in jest 29](https://jestjs.io/blog/2022/08/25/jest-29) ([#47388](https://github.com/WordPress/gutenberg/pull/47388)) +- Started requiring Jest v29 instead of v27 as a peer dependency. See [breaking changes in Jest 28](https://jestjs.io/blog/2022/04/25/jest-28) and [in jest 29](https://jestjs.io/blog/2022/08/25/jest-29) ([#47388](https://github.com/WordPress/gutenberg/pull/47388)) ## 6.5.0 (2023-03-01) diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index 5e2f74bb48d2c..bcc1ffcf8a3fc 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -14,9 +14,9 @@ ### Bug Fixes -- Allow multiple event handlers for the same type with `data-wp-on-document` and `data-wp-on-window`. ([#61009](https://github.com/WordPress/gutenberg/pull/61009)) -- Prevent wrong written directives from killing the runtime ([#61249](https://github.com/WordPress/gutenberg/pull/61249)) -- Prevent empty namespace or different namespaces from killing the runtime ([#61409](https://github.com/WordPress/gutenberg/pull/61409)) +- Allow multiple event handlers for the same type with `data-wp-on-document` and `data-wp-on-window`. ([#61009](https://github.com/WordPress/gutenberg/pull/61009)) +- Prevent wrong written directives from killing the runtime ([#61249](https://github.com/WordPress/gutenberg/pull/61249)) +- Prevent empty namespace or different namespaces from killing the runtime ([#61409](https://github.com/WordPress/gutenberg/pull/61409)) ## 5.6.0 (2024-05-02) @@ -24,7 +24,7 @@ ### Enhancements -- Improve data-wp-context debugging by validating it as a stringified JSON Object. ([#61045](https://github.com/WordPress/gutenberg/pull/61045)) +- Improve data-wp-context debugging by validating it as a stringified JSON Object. ([#61045](https://github.com/WordPress/gutenberg/pull/61045)) ### Bug Fixes diff --git a/packages/jest-preset-default/CHANGELOG.md b/packages/jest-preset-default/CHANGELOG.md index 6bde10d348a5b..f891b892ed8ba 100644 --- a/packages/jest-preset-default/CHANGELOG.md +++ b/packages/jest-preset-default/CHANGELOG.md @@ -68,7 +68,7 @@ ### Breaking Changes -- Started requiring Jest v29 instead of v27 as a peer dependency. See [breaking changes in Jest 28](https://jestjs.io/blog/2022/04/25/jest-28) and [in jest 29](https://jestjs.io/blog/2022/08/25/jest-29) ([#47388](https://github.com/WordPress/gutenberg/pull/47388)) +- Started requiring Jest v29 instead of v27 as a peer dependency. See [breaking changes in Jest 28](https://jestjs.io/blog/2022/04/25/jest-28) and [in jest 29](https://jestjs.io/blog/2022/08/25/jest-29) ([#47388](https://github.com/WordPress/gutenberg/pull/47388)) ## 10.9.0 (2023-03-01)