Commit 6a6312f06c for woocommerce
commit 6a6312f06cbff80ff1df79fb490d8ab7b2b5cade
Author: Lucio Giannotta <lucio.giannotta@a8c.com>
Date: Tue Dec 23 02:08:05 2025 -0500
Fix wp-editor script being enqueued on widgets screen (#62327) (#62438)
Replace static imports from @wordpress/editor with string-based store
selectors to avoid adding wp-editor as a script dependency. This fixes
the PHP notice on WordPress 5.8+ block-based widgets editor where
wp-editor should not be loaded.
Also, added a mock store registration for tests. Created a reusable test
utility for mocking the core/editor store.
This is needed because we use string-based store selectors instead of
importing the store from @wordpress/editor (to avoid wp-editor dependency).
diff --git a/plugins/woocommerce/changelog/62438-wooplug-5970-improve-wp-editor-script-enqueue-to-avoid-wordpress-php b/plugins/woocommerce/changelog/62438-wooplug-5970-improve-wp-editor-script-enqueue-to-avoid-wordpress-php
new file mode 100644
index 0000000000..a5e720e345
--- /dev/null
+++ b/plugins/woocommerce/changelog/62438-wooplug-5970-improve-wp-editor-script-enqueue-to-avoid-wordpress-php
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fixed enqueuing of the whole `wordpress/editor` script where unnecessary.
\ No newline at end of file
diff --git a/plugins/woocommerce/client/admin/client/wp-admin-scripts/command-palette-analytics/index.js b/plugins/woocommerce/client/admin/client/wp-admin-scripts/command-palette-analytics/index.js
index af45b858b6..90d01a74aa 100644
--- a/plugins/woocommerce/client/admin/client/wp-admin-scripts/command-palette-analytics/index.js
+++ b/plugins/woocommerce/client/admin/client/wp-admin-scripts/command-palette-analytics/index.js
@@ -7,7 +7,6 @@ import { useEffect } from '@wordpress/element';
import { registerPlugin } from '@wordpress/plugins';
import { addQueryArgs } from '@wordpress/url';
import { useSelect } from '@wordpress/data';
-import { store as editorStore } from '@wordpress/editor';
/**
* Internal dependencies
@@ -35,8 +34,9 @@ const registerWooCommerceAnalyticsCommand = ( { label, path, origin } ) => {
const WooCommerceAnalyticsCommands = () => {
const { editedPostType } = useSelect( ( select ) => {
+ const editor = select( 'core/editor' );
return {
- editedPostType: select( editorStore ).getCurrentPostType(),
+ editedPostType: editor?.getCurrentPostType?.() ?? null,
};
} );
const origin = editedPostType ? editedPostType + '-editor' : null;
diff --git a/plugins/woocommerce/client/admin/client/wp-admin-scripts/command-palette/index.js b/plugins/woocommerce/client/admin/client/wp-admin-scripts/command-palette/index.js
index 1462f93277..a093fd818c 100644
--- a/plugins/woocommerce/client/admin/client/wp-admin-scripts/command-palette/index.js
+++ b/plugins/woocommerce/client/admin/client/wp-admin-scripts/command-palette/index.js
@@ -6,7 +6,6 @@ import { __, sprintf } from '@wordpress/i18n';
import { box, plus, settings } from '@wordpress/icons';
import { useEffect, useMemo, useRef } from '@wordpress/element';
import { dispatch, useSelect } from '@wordpress/data';
-import { store as editorStore } from '@wordpress/editor';
import { store as coreStore } from '@wordpress/core-data';
import { addQueryArgs } from '@wordpress/url';
import { recordEvent, queueRecordEvent } from '@woocommerce/tracks';
@@ -41,8 +40,9 @@ const registerWooCommerceSettingsCommand = ( { label, tab, origin } ) => {
// https://github.com/WordPress/gutenberg/blob/8863b49b7e686f555e8b8adf70cc588c4feebfbf/packages/core-commands/src/site-editor-navigation-commands.js#L36C7-L36C44
function useProductCommandLoader( { search } ) {
const { editedPostType } = useSelect( ( select ) => {
+ const editor = select( 'core/editor' );
return {
- editedPostType: select( editorStore ).getCurrentPostType(),
+ editedPostType: editor?.getCurrentPostType?.() ?? null,
};
} );
const origin = editedPostType ? editedPostType + '-editor' : null;
@@ -122,8 +122,9 @@ function useProductCommandLoader( { search } ) {
const WooCommerceCommands = () => {
const { editedPostType } = useSelect( ( select ) => {
+ const editor = select( 'core/editor' );
return {
- editedPostType: select( editorStore ).getCurrentPostType(),
+ editedPostType: editor?.getCurrentPostType?.() ?? null,
};
} );
const origin = editedPostType ? editedPostType + '-editor' : null;
diff --git a/plugins/woocommerce/client/blocks/assets/js/atomic/blocks/product-elements/shared/use-is-descendent-of-single-product-template.tsx b/plugins/woocommerce/client/blocks/assets/js/atomic/blocks/product-elements/shared/use-is-descendent-of-single-product-template.tsx
index 8c5d887a23..bbdd08bb35 100644
--- a/plugins/woocommerce/client/blocks/assets/js/atomic/blocks/product-elements/shared/use-is-descendent-of-single-product-template.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/atomic/blocks/product-elements/shared/use-is-descendent-of-single-product-template.tsx
@@ -1,14 +1,15 @@
/**
* External dependencies
*/
-import { store as editorStore } from '@wordpress/editor';
import { useSelect } from '@wordpress/data';
import { isString } from '@woocommerce/types';
+import { CORE_EDITOR_STORE } from '@woocommerce/utils';
export const useIsDescendentOfSingleProductTemplate = () => {
const isDescendentOfSingleProductTemplate = useSelect( ( select ) => {
+ const editor = select( CORE_EDITOR_STORE );
// @ts-expect-error getEditedPostSlug is not typed
- const postSlug = select( editorStore ).getEditedPostSlug();
+ const postSlug = editor?.getEditedPostSlug?.();
return isString( postSlug )
? postSlug.includes( 'single-product' )
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/checkout/test/block.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/checkout/test/block.tsx
index f87e460a02..b012912a0a 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/checkout/test/block.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/checkout/test/block.tsx
@@ -43,13 +43,10 @@ import Taxes from '../inner-blocks/checkout-order-summary-taxes/frontend';
import { defaultCartState } from '../../../data/cart/default-state';
import Checkout from '../block';
-jest.mock( '@wordpress/data', () => {
- const wpData = jest.requireActual( 'wordpress-data-wp-6-7' );
- return {
- __esModule: true,
- ...wpData,
- };
-} );
+jest.mock( '@wordpress/data', () =>
+ // eslint-disable-next-line @typescript-eslint/no-var-requires -- Must use require due to Jest mock hoisting
+ require( '@woocommerce/blocks-test-utils/mock-editor-store' ).mockWordPressDataWithEditorStore()
+);
jest.mock( '@wordpress/compose', () => ( {
...jest.requireActual( '@wordpress/compose' ),
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/checkout/test/editor-integration.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/checkout/test/editor-integration.tsx
index 0531d74847..fdba1e57c5 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/checkout/test/editor-integration.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/checkout/test/editor-integration.tsx
@@ -7,6 +7,11 @@ import { type BlockAttributes } from '@wordpress/blocks';
import { getByLabelText, getByRole } from '@testing-library/dom';
import { userEvent } from '@testing-library/user-event';
+jest.mock( '@wordpress/data', () =>
+ // eslint-disable-next-line @typescript-eslint/no-var-requires -- Must use require due to Jest mock hoisting
+ require( '@woocommerce/blocks-test-utils/mock-editor-store' ).mockWordPressDataWithEditorStore()
+);
+
/**
* Internal dependencies
*/
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/classic-template/index.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/classic-template/index.tsx
index 2f8861bfe5..f294459bd4 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/classic-template/index.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/classic-template/index.tsx
@@ -20,7 +20,7 @@ import { useDispatch, useSelect } from '@wordpress/data';
import { useEffect, useState } from '@wordpress/element';
import { store as noticesStore } from '@wordpress/notices';
import { useEntityRecord } from '@wordpress/core-data';
-import { store as editorStore } from '@wordpress/editor';
+import { CORE_EDITOR_STORE } from '@woocommerce/utils';
/**
* Internal dependencies
@@ -184,7 +184,7 @@ const Edit = ( {
const { currentPostId } = useSelect( ( sel ) => {
return {
// @ts-expect-error getCurrentPostId is not typed
- currentPostId: sel( editorStore ).getCurrentPostId(),
+ currentPostId: sel( CORE_EDITOR_STORE )?.getCurrentPostId?.() ?? 0,
};
}, [] );
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/email-content/edit.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/email-content/edit.tsx
index bcaff96ec2..fe4814caf2 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/email-content/edit.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/email-content/edit.tsx
@@ -6,11 +6,10 @@ import { useState } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import ServerSideRender from '@wordpress/server-side-render';
import { useBlockProps } from '@wordpress/block-editor';
+import { CORE_EDITOR_STORE } from '@woocommerce/utils';
import {
__experimentalText as Text, // eslint-disable-line
} from '@wordpress/components';
-// eslint-disable-next-line @woocommerce/dependency-group
-import { store as editorStore } from '@wordpress/editor';
/**
* Internal dependencies
@@ -41,7 +40,7 @@ export default function Edit() {
const blockProps = useBlockProps();
const { postId } = useSelect(
( select ) => ( {
- postId: select( editorStore ).getCurrentPostId?.() ?? 0,
+ postId: select( CORE_EDITOR_STORE )?.getCurrentPostId?.() ?? 0,
} ),
[]
);
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/tracks-utils.ts b/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/tracks-utils.ts
index b5d1aa9a65..96c55ff733 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/tracks-utils.ts
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/tracks-utils.ts
@@ -2,7 +2,7 @@
* External dependencies
*/
import { useSelect } from '@wordpress/data';
-import { store as editorStore } from '@wordpress/editor';
+import { CORE_EDITOR_STORE } from '@woocommerce/utils';
enum Locations {
SINGLE_PRODUCT = 'single-product',
@@ -31,9 +31,10 @@ const templateSlugToTemplateMap: {
export const useTracksLocation = ( templateSlug: string | undefined ) => {
const postType = useSelect( ( select ) => {
+ const editor = select( CORE_EDITOR_STORE );
// @ts-expect-error Type definitions are missing
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/wordpress__blocks/store/selectors.d.ts
- return select( editorStore ).getCurrentPostType();
+ return editor?.getCurrentPostType?.();
}, [] );
if ( postType === Locations.PAGE || postType === Locations.POST ) {
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/utils.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/utils.tsx
index 97dfbc57cc..b2e46209c1 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/utils.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/utils.tsx
@@ -5,8 +5,8 @@ import { store as blockEditorStore } from '@wordpress/block-editor';
import { addFilter } from '@wordpress/hooks';
import { select, useSelect, useDispatch } from '@wordpress/data';
import { store as coreDataStore } from '@wordpress/core-data';
-import { store as editorStore } from '@wordpress/editor';
import type { BlockEditProps, Block } from '@wordpress/blocks';
+import { CORE_EDITOR_STORE } from '@woocommerce/utils';
import {
useEffect,
useLayoutEffect,
@@ -85,7 +85,8 @@ const isInProductArchive = () => {
];
// @ts-expect-error getEditedPostSlug is not typed
- const currentTemplateId = select( editorStore ).getEditedPostSlug();
+ const currentTemplateId =
+ select( CORE_EDITOR_STORE )?.getEditedPostSlug?.();
/**
* Set inherit value when Product Collection block is first added to the page.
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-query/variations/product-query.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/product-query/variations/product-query.tsx
index 5ef7c49e88..83f18e49ff 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-query/variations/product-query.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-query/variations/product-query.tsx
@@ -10,12 +10,11 @@ import { __ } from '@wordpress/i18n';
import { stacks } from '@woocommerce/icons';
import { getSettingWithCoercion } from '@woocommerce/settings';
import { select, subscribe } from '@wordpress/data';
-import { store as editorStore } from '@wordpress/editor';
import {
QueryBlockAttributes,
ProductQueryBlockQuery,
} from '@woocommerce/blocks/product-query/types';
-import { isSiteEditorPage } from '@woocommerce/utils';
+import { isSiteEditorPage, CORE_EDITOR_STORE } from '@woocommerce/utils';
import { isNumber, isString } from '@woocommerce/types';
/**
@@ -73,7 +72,7 @@ let currentTemplateSlug: string | undefined;
subscribe( () => {
const previousTemplateSlug = currentTemplateSlug;
// @ts-expect-error getEditedPostSlug is not typed
- currentTemplateSlug = select( editorStore )?.getEditedPostSlug();
+ currentTemplateSlug = select( CORE_EDITOR_STORE )?.getEditedPostSlug?.();
if ( previousTemplateSlug === currentTemplateSlug ) {
return;
}
diff --git a/plugins/woocommerce/client/blocks/assets/js/editor-components/default-notice/index.tsx b/plugins/woocommerce/client/blocks/assets/js/editor-components/default-notice/index.tsx
index 0ef002e501..6bea20c78c 100644
--- a/plugins/woocommerce/client/blocks/assets/js/editor-components/default-notice/index.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/editor-components/default-notice/index.tsx
@@ -2,12 +2,13 @@
* External dependencies
*/
import { __ } from '@wordpress/i18n';
-import { store as editorStore } from '@wordpress/editor';
import triggerFetch from '@wordpress/api-fetch';
import { store as coreStore } from '@wordpress/core-data';
import { Notice } from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
import { CHECKOUT_PAGE_ID, CART_PAGE_ID } from '@woocommerce/block-settings';
+import { CORE_EDITOR_STORE } from '@woocommerce/utils';
+
import {
useCallback,
useState,
@@ -30,17 +31,16 @@ export function DefaultNotice( { block }: { block: string } ) {
// Everything below works the same for Cart/Checkout
const { saveEntityRecord } = useDispatch( coreStore );
- const { editPost, savePost } = useDispatch( editorStore );
+ const { editPost, savePost } = useDispatch( CORE_EDITOR_STORE );
const { slug, postPublished, currentPostId } = useSelect( ( select ) => {
const { getEntityRecord } = select( coreStore );
- const { isCurrentPostPublished, getCurrentPostId } =
- select( editorStore );
+ const editor = select( CORE_EDITOR_STORE );
return {
slug:
getEntityRecord( 'postType', 'page', ORIGINAL_PAGE_ID )?.slug ||
block,
- postPublished: isCurrentPostPublished(),
- currentPostId: getCurrentPostId(),
+ postPublished: editor?.isCurrentPostPublished?.() ?? false,
+ currentPostId: editor?.getCurrentPostId?.() ?? 0,
};
}, [] );
const [ settingStatus, setStatus ] = useState( 'pristine' );
diff --git a/plugins/woocommerce/client/blocks/assets/js/utils/index.ts b/plugins/woocommerce/client/blocks/assets/js/utils/index.ts
index b54bdf78ea..8274da5dfa 100644
--- a/plugins/woocommerce/client/blocks/assets/js/utils/index.ts
+++ b/plugins/woocommerce/client/blocks/assets/js/utils/index.ts
@@ -11,6 +11,7 @@ export * from './shared-attributes';
export * from './is-site-editor-page';
export * from './is-widget-editor-page';
export * from './trim-words';
+export * from './wordpress-stores';
export * from './find-block';
export * from './get-unique-id';
export * from './html-entities';
diff --git a/plugins/woocommerce/client/blocks/assets/js/utils/is-site-editor-page.ts b/plugins/woocommerce/client/blocks/assets/js/utils/is-site-editor-page.ts
index 60dd090ac4..1b5b457b96 100644
--- a/plugins/woocommerce/client/blocks/assets/js/utils/is-site-editor-page.ts
+++ b/plugins/woocommerce/client/blocks/assets/js/utils/is-site-editor-page.ts
@@ -2,11 +2,15 @@
* External dependencies
*/
import { select } from '@wordpress/data';
-import { store as editorStore } from '@wordpress/editor';
+
+/**
+ * Internal dependencies
+ */
+import { CORE_EDITOR_STORE } from './wordpress-stores';
export const isSiteEditorPage = (): boolean => {
- // @ts-expect-error getCurrentPostType is not typed.
- const editedPostType = select( editorStore )?.getCurrentPostType();
+ const editor = select( CORE_EDITOR_STORE );
+ const editedPostType = editor?.getCurrentPostType?.();
return (
editedPostType === 'wp_template' ||
diff --git a/plugins/woocommerce/client/blocks/assets/js/utils/wordpress-stores.ts b/plugins/woocommerce/client/blocks/assets/js/utils/wordpress-stores.ts
new file mode 100644
index 0000000000..24000d566b
--- /dev/null
+++ b/plugins/woocommerce/client/blocks/assets/js/utils/wordpress-stores.ts
@@ -0,0 +1,10 @@
+/**
+ * WordPress store names for use with @wordpress/data select/dispatch.
+ *
+ * Using string-based store names instead of importing store objects avoids
+ * adding unnecessary script dependencies. For example, importing
+ * `store as editorStore from '@wordpress/editor'` would enqueue the whole
+ * wp-editor package as a dependency.
+ */
+
+export const CORE_EDITOR_STORE = 'core/editor' as const;
diff --git a/plugins/woocommerce/client/blocks/tests/js/jest.config.json b/plugins/woocommerce/client/blocks/tests/js/jest.config.json
index 9ae089ce81..512de9d3b0 100644
--- a/plugins/woocommerce/client/blocks/tests/js/jest.config.json
+++ b/plugins/woocommerce/client/blocks/tests/js/jest.config.json
@@ -36,6 +36,7 @@
"@woocommerce/resource-previews": "assets/js/previews",
"@woocommerce/shared-context": "assets/js/shared/context",
"@woocommerce/shared-hocs": "assets/js/shared/hocs",
+ "@woocommerce/blocks-test-utils/(.*)$": "tests/utils/$1",
"@woocommerce/blocks-test-utils": "tests/utils",
"@woocommerce/types": "assets/js/types",
"@woocommerce/utils": "assets/js/utils",
diff --git a/plugins/woocommerce/client/blocks/tests/utils/mock-editor-store.ts b/plugins/woocommerce/client/blocks/tests/utils/mock-editor-store.ts
new file mode 100644
index 0000000000..6965c40de8
--- /dev/null
+++ b/plugins/woocommerce/client/blocks/tests/utils/mock-editor-store.ts
@@ -0,0 +1,35 @@
+/**
+ * Jest mock factory for @wordpress/data that registers a mock core/editor store.
+ *
+ * This is needed because we use string-based store selectors ('core/editor')
+ * instead of importing the store from @wordpress/editor (which would add
+ * wp-editor as a script dependency). The import side-effect would normally
+ * register the store, but since we avoid the import, we need to register
+ * a mock in tests.
+ *
+ * Usage (must use require, not import, due to Jest hoisting):
+ * ```
+ * jest.mock( '@wordpress/data', () =>
+ * require( '@woocommerce/blocks-test-utils/mock-editor-store' ).mockWordPressDataWithEditorStore()
+ * );
+ * ```
+ */
+export const mockWordPressDataWithEditorStore = () => {
+ // Use require to avoid issues with Jest's module system
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
+ const wpData = require( 'wordpress-data-wp-6-7' );
+ const mockEditorStore = wpData.createReduxStore( 'core/editor', {
+ reducer: () => ( {} ),
+ selectors: {
+ getCurrentPostId: () => null,
+ getCurrentPostType: () => null,
+ getCurrentPost: () => null,
+ isCurrentPostPublished: () => false,
+ },
+ } );
+ wpData.register( mockEditorStore );
+ return {
+ __esModule: true,
+ ...wpData,
+ };
+};