From abbfb881535758ae628e62bc0e4d5bda97511336 Mon Sep 17 00:00:00 2001 From: Grzegorz Ziolkowski Date: Thu, 27 Apr 2023 10:49:58 +0200 Subject: [PATCH 1/3] Warning: Introduce `SCRIPT_DEBUG` to make the package compatible with webpack 5 --- .../configs/recommended-with-formatting.js | 1 + packages/scripts/config/webpack.config.js | 5 +++ packages/warning/README.md | 2 +- packages/warning/babel-plugin.js | 40 ++++--------------- packages/warning/src/index.js | 6 +-- packages/warning/src/test/index.js | 15 +++---- packages/warning/test/babel-plugin.js | 23 +++++------ tools/webpack/shared.js | 2 + typings/gutenberg-env/index.d.ts | 2 + 9 files changed, 38 insertions(+), 58 deletions(-) diff --git a/packages/eslint-plugin/configs/recommended-with-formatting.js b/packages/eslint-plugin/configs/recommended-with-formatting.js index 3c7ce025ce8fe..2499d8656d0c0 100644 --- a/packages/eslint-plugin/configs/recommended-with-formatting.js +++ b/packages/eslint-plugin/configs/recommended-with-formatting.js @@ -16,6 +16,7 @@ const config = { globals: { window: true, document: true, + SCRIPT_DEBUG: 'readonly', wp: 'readonly', }, settings: { diff --git a/packages/scripts/config/webpack.config.js b/packages/scripts/config/webpack.config.js index c02fbfcbea2c9..1a4872db9cdd1 100644 --- a/packages/scripts/config/webpack.config.js +++ b/packages/scripts/config/webpack.config.js @@ -4,6 +4,7 @@ const { BundleAnalyzerPlugin } = require( 'webpack-bundle-analyzer' ); const { CleanWebpackPlugin } = require( 'clean-webpack-plugin' ); const CopyWebpackPlugin = require( 'copy-webpack-plugin' ); +const { DefinePlugin } = require( 'webpack' ); const browserslist = require( 'browserslist' ); const MiniCSSExtractPlugin = require( 'mini-css-extract-plugin' ); const { basename, dirname, resolve } = require( 'path' ); @@ -243,6 +244,10 @@ const config = { ], }, plugins: [ + new DefinePlugin( { + // Inject the `SCRIPT_DEBUG` global, used for development features flagging. + SCRIPT_DEBUG: mode === 'development', + } ), // During rebuilds, all webpack assets that are not used anymore will be // removed automatically. There is an exception added in watch mode for // fonts and images. It is a known limitations: diff --git a/packages/warning/README.md b/packages/warning/README.md index 6adfe73b6d459..67b471d154ecc 100644 --- a/packages/warning/README.md +++ b/packages/warning/README.md @@ -20,7 +20,7 @@ To prevent that, you should: 1. Put `@wordpress/warning/babel-plugin` into your [babel config](https://babeljs.io/docs/en/plugins#plugin-options) or use [`@wordpress/babel-preset-default`](https://www.npmjs.com/package/@wordpress/babel-preset-default), which already includes the babel plugin. - This will make sure your `warning` calls are wrapped within a condition that checks if `process.env.NODE_ENV !== 'production'`. + This will make sure your `warning` calls are wrapped within a condition that checks if `SCRIPT_DEBUG === true`. 2. Use [UglifyJS](https://github.com/mishoo/UglifyJS2), [Terser](https://github.com/terser/terser) or any other JavaScript parser that performs [dead code elimination](https://en.wikipedia.org/wiki/Dead_code_elimination). This is usually used in conjunction with JavaScript bundlers, such as [webpack](https://github.com/webpack/webpack). diff --git a/packages/warning/babel-plugin.js b/packages/warning/babel-plugin.js index f94de3a4f4ca2..939b4f4e45e80 100644 --- a/packages/warning/babel-plugin.js +++ b/packages/warning/babel-plugin.js @@ -5,7 +5,7 @@ const pkg = require( './package.json' ); /** * Babel plugin which transforms `warning` function calls to wrap within a - * condition that checks if `process.env.NODE_ENV !== 'production'`. + * condition that checks if `SCRIPT_DEBUG === true`. * * @param {import('@babel/core')} babel Current Babel object. * @@ -14,36 +14,10 @@ const pkg = require( './package.json' ); function babelPlugin( { types: t } ) { const seen = Symbol(); - const typeofProcessExpression = t.binaryExpression( - '!==', - t.unaryExpression( 'typeof', t.identifier( 'process' ), false ), - t.stringLiteral( 'undefined' ) - ); - - const processEnvExpression = t.memberExpression( - t.identifier( 'process' ), - t.identifier( 'env' ), - false - ); - - const nodeEnvCheckExpression = t.binaryExpression( - '!==', - t.memberExpression( - processEnvExpression, - t.identifier( 'NODE_ENV' ), - false - ), - t.stringLiteral( 'production' ) - ); - - const logicalExpression = t.logicalExpression( - '&&', - t.logicalExpression( - '&&', - typeofProcessExpression, - processEnvExpression - ), - nodeEnvCheckExpression + const scriptDebugCheckExpression = t.binaryExpression( + '===', + t.identifier( 'SCRIPT_DEBUG' ), + t.booleanLiteral( true ) ); return { @@ -80,11 +54,11 @@ function babelPlugin( { types: t } ) { // Turns this code: // warning(argument); // into this: - // typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" ? warning(argument) : void 0; + // SCRIPT_DEBUG === true ? warning(argument) : void 0; 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 38afc42caf0b0..137de7cbb4cc3 100644 --- a/packages/warning/src/index.js +++ b/packages/warning/src/index.js @@ -4,11 +4,7 @@ import { logged } from './utils'; function isDev() { - return ( - typeof process !== 'undefined' && - process.env && - process.env.NODE_ENV !== 'production' - ); + return SCRIPT_DEBUG === true; } /** diff --git a/packages/warning/src/test/index.js b/packages/warning/src/test/index.js index a7ecbfb4a8ffe..a32e5f1e0fae4 100644 --- a/packages/warning/src/test/index.js +++ b/packages/warning/src/test/index.js @@ -4,27 +4,28 @@ import warning from '..'; import { logged } from '../utils'; -const initialNodeEnv = process.env.NODE_ENV; - describe( 'warning', () => { + const initialScriptDebug = global.SCRIPT_DEBUG; + afterEach( () => { - process.env.NODE_ENV = initialNodeEnv; + global.SCRIPT_DEBUG = initialScriptDebug; logged.clear(); } ); - it( 'logs to console.warn when NODE_ENV is not "production"', () => { - process.env.NODE_ENV = 'development'; + it( 'logs to console.warn when SCRIPT_DEBUG is set to `true`', () => { + global.SCRIPT_DEBUG = true; warning( 'warning' ); expect( console ).toHaveWarnedWith( 'warning' ); } ); - it( 'does not log to console.warn if NODE_ENV is "production"', () => { - process.env.NODE_ENV = 'production'; + it( 'does not log to console.warn if SCRIPT_DEBUG not set to `true`', () => { + global.SCRIPT_DEBUG = false; warning( 'warning' ); expect( console ).not.toHaveWarned(); } ); it( 'should show a message once', () => { + global.SCRIPT_DEBUG = true; warning( 'warning' ); warning( 'warning' ); diff --git a/packages/warning/test/babel-plugin.js b/packages/warning/test/babel-plugin.js index a98d270a9845b..c196ee8f6448b 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 process !== "undefined" && process.env && process.env.NODE_ENV !== "production" ? warning("a") : void 0;' + 'SCRIPT_DEBUG === true ? warning("a") : void 0;' ); expect( transformCode( input ) ).toEqual( expected ); @@ -44,8 +44,7 @@ describe( 'babel-plugin', () => { it( 'should replace warning calls without import declaration with plugin options', () => { const input = 'warning("a");'; const options = { callee: 'warning' }; - const expected = - 'typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" ? warning("a") : void 0;'; + const expected = 'SCRIPT_DEBUG === true ? warning("a") : void 0;'; expect( transformCode( input, options ) ).toEqual( expected ); } ); @@ -59,9 +58,9 @@ describe( 'babel-plugin', () => { ); const expected = join( 'import warning from "@wordpress/warning";', - 'typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" ? warning("a") : void 0;', - 'typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" ? warning("b") : void 0;', - 'typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" ? warning("c") : void 0;' + 'SCRIPT_DEBUG === true ? warning("a") : void 0;', + 'SCRIPT_DEBUG === true ? warning("b") : void 0;', + 'SCRIPT_DEBUG === true ? warning("c") : void 0;' ); expect( transformCode( input ) ).toEqual( expected ); @@ -76,9 +75,9 @@ describe( 'babel-plugin', () => { ); const expected = join( 'import warn from "@wordpress/warning";', - 'typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" ? warn("a") : void 0;', - 'typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" ? warn("b") : void 0;', - 'typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" ? warn("c") : void 0;' + 'SCRIPT_DEBUG === true ? warn("a") : void 0;', + 'SCRIPT_DEBUG === true ? warn("b") : void 0;', + 'SCRIPT_DEBUG === true ? warn("c") : void 0;' ); expect( transformCode( input ) ).toEqual( expected ); @@ -93,9 +92,9 @@ describe( 'babel-plugin', () => { ); const expected = join( 'import warn from "@wordpress/warning";', - 'typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" ? warn("a") : void 0;', - 'typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" ? warn("b") : void 0;', - 'typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" ? warn("c") : void 0;' + 'SCRIPT_DEBUG === true ? warn("a") : void 0;', + 'SCRIPT_DEBUG === true ? warn("b") : void 0;', + 'SCRIPT_DEBUG === true ? warn("c") : void 0;' ); expect( transformCode( input ) ).toEqual( expected ); diff --git a/tools/webpack/shared.js b/tools/webpack/shared.js index 9aaa35737400c..debd3fc93f6f6 100644 --- a/tools/webpack/shared.js +++ b/tools/webpack/shared.js @@ -69,6 +69,8 @@ const plugins = [ // Inject the `IS_WORDPRESS_CORE` global, used for feature flagging. 'process.env.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', } ), mode === 'production' && new ReadableJsAssetsWebpackPlugin(), ]; diff --git a/typings/gutenberg-env/index.d.ts b/typings/gutenberg-env/index.d.ts index e2876716bd8b7..ecf60a7ca094f 100644 --- a/typings/gutenberg-env/index.d.ts +++ b/typings/gutenberg-env/index.d.ts @@ -7,3 +7,5 @@ interface Process { env: Environment; } declare var process: Process; + +declare var SCRIPT_DEBUG: boolean; From f552753f3a29d58631285ef87145ed5eaed523d5 Mon Sep 17 00:00:00 2001 From: Grzegorz Ziolkowski Date: Thu, 27 Apr 2023 14:08:53 +0200 Subject: [PATCH 2/3] Improve the check for SCRIPT_DEBUG so it account for being undefined --- .../scripts/setup-globals.js | 3 +++ packages/warning/babel-plugin.js | 16 +++++++++++-- packages/warning/src/index.js | 2 +- packages/warning/test/babel-plugin.js | 23 ++++++++++--------- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/packages/jest-preset-default/scripts/setup-globals.js b/packages/jest-preset-default/scripts/setup-globals.js index 105e0ab508ab3..abd99f620dc89 100644 --- a/packages/jest-preset-default/scripts/setup-globals.js +++ b/packages/jest-preset-default/scripts/setup-globals.js @@ -1,3 +1,6 @@ +// Run all tests with development tools enabled. +global.SCRIPT_DEBUG = true; + // These are necessary to load TinyMCE successfully. global.URL = window.URL; global.window.tinyMCEPreInit = { diff --git a/packages/warning/babel-plugin.js b/packages/warning/babel-plugin.js index 939b4f4e45e80..02c466b5de24e 100644 --- a/packages/warning/babel-plugin.js +++ b/packages/warning/babel-plugin.js @@ -14,12 +14,24 @@ 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.booleanLiteral( true ) ); + const logicalExpression = t.logicalExpression( + '&&', + typeofProcessExpression, + scriptDebugCheckExpression + ); + return { visitor: { ImportDeclaration( path, state ) { @@ -54,11 +66,11 @@ function babelPlugin( { types: t } ) { // Turns this code: // warning(argument); // into this: - // SCRIPT_DEBUG === true ? warning(argument) : void 0; + // typeof SCRIPT_DEBUG !== 'undefined' && SCRIPT_DEBUG === true ? warning(argument) : void 0; node[ seen ] = true; path.replaceWith( t.ifStatement( - scriptDebugCheckExpression, + logicalExpression, t.blockStatement( [ t.expressionStatement( node ), ] ) diff --git a/packages/warning/src/index.js b/packages/warning/src/index.js index 137de7cbb4cc3..89ce71db112a2 100644 --- a/packages/warning/src/index.js +++ b/packages/warning/src/index.js @@ -4,7 +4,7 @@ import { logged } from './utils'; function isDev() { - return SCRIPT_DEBUG === true; + return typeof SCRIPT_DEBUG !== 'undefined' && SCRIPT_DEBUG === true; } /** diff --git a/packages/warning/test/babel-plugin.js b/packages/warning/test/babel-plugin.js index c196ee8f6448b..a3c4bd55745ef 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";', - 'SCRIPT_DEBUG === true ? warning("a") : void 0;' + 'typeof SCRIPT_DEBUG !== "undefined" && SCRIPT_DEBUG === true ? warning("a") : void 0;' ); expect( transformCode( input ) ).toEqual( expected ); @@ -44,7 +44,8 @@ describe( 'babel-plugin', () => { it( 'should replace warning calls without import declaration with plugin options', () => { const input = 'warning("a");'; const options = { callee: 'warning' }; - const expected = 'SCRIPT_DEBUG === true ? warning("a") : void 0;'; + const expected = + 'typeof SCRIPT_DEBUG !== "undefined" && SCRIPT_DEBUG === true ? warning("a") : void 0;'; expect( transformCode( input, options ) ).toEqual( expected ); } ); @@ -58,9 +59,9 @@ describe( 'babel-plugin', () => { ); const expected = join( 'import warning from "@wordpress/warning";', - 'SCRIPT_DEBUG === true ? warning("a") : void 0;', - 'SCRIPT_DEBUG === true ? warning("b") : void 0;', - 'SCRIPT_DEBUG === true ? warning("c") : void 0;' + '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;' ); expect( transformCode( input ) ).toEqual( expected ); @@ -75,9 +76,9 @@ describe( 'babel-plugin', () => { ); const expected = join( 'import warn from "@wordpress/warning";', - 'SCRIPT_DEBUG === true ? warn("a") : void 0;', - 'SCRIPT_DEBUG === true ? warn("b") : void 0;', - 'SCRIPT_DEBUG === true ? warn("c") : void 0;' + '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;' ); expect( transformCode( input ) ).toEqual( expected ); @@ -92,9 +93,9 @@ describe( 'babel-plugin', () => { ); const expected = join( 'import warn from "@wordpress/warning";', - 'SCRIPT_DEBUG === true ? warn("a") : void 0;', - 'SCRIPT_DEBUG === true ? warn("b") : void 0;', - 'SCRIPT_DEBUG === true ? warn("c") : void 0;' + '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;' ); expect( transformCode( input ) ).toEqual( expected ); From 1fe96b63f762e254dc17104cca97821b8884f28d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=B3=C5=82kowski?= Date: Thu, 27 Apr 2023 14:20:53 +0200 Subject: [PATCH 3/3] Update packages/scripts/config/webpack.config.js --- packages/scripts/config/webpack.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/scripts/config/webpack.config.js b/packages/scripts/config/webpack.config.js index 1a4872db9cdd1..29a25c9353ff3 100644 --- a/packages/scripts/config/webpack.config.js +++ b/packages/scripts/config/webpack.config.js @@ -246,7 +246,7 @@ const config = { plugins: [ new DefinePlugin( { // Inject the `SCRIPT_DEBUG` global, used for development features flagging. - SCRIPT_DEBUG: mode === 'development', + SCRIPT_DEBUG: ! isProduction, } ), // During rebuilds, all webpack assets that are not used anymore will be // removed automatically. There is an exception added in watch mode for