Skip to content

Commit

Permalink
Process Block Type: Copy deprecation to a new object instead of mutat…
Browse files Browse the repository at this point in the history
…ing when stabilizing supports (#66849)

* Process Block Type: Copy deprecation to a new object instead of mutating when stabilizing supports

* Update stabilizeSupports to carefully construct the newSupports object instead of updating the reference for the typography key

Co-authored-by: andrewserong <[email protected]>
Co-authored-by: aaronrobertshaw <[email protected]>
Co-authored-by: ramonjd <[email protected]>
Co-authored-by: Karen Attfield <[email protected]>
  • Loading branch information
5 people authored Nov 8, 2024
1 parent ab6e729 commit 457fcf8
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 15 deletions.
47 changes: 32 additions & 15 deletions packages/blocks/src/store/process-block-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,32 @@ function stabilizeSupports( rawSupports ) {
return rawSupports;
}

const supports = { ...rawSupports };
if ( supports?.typography && typeof supports.typography === 'object' ) {
supports.typography = Object.fromEntries(
Object.entries( supports.typography ).map( ( [ key, value ] ) => [
TYPOGRAPHY_SUPPORTS_EXPERIMENTAL_TO_STABLE[ key ] || key,
value,
] )
);
// Create a new object to avoid mutating the original. This ensures that
// custom block plugins that rely on immutable supports are not affected.
// See: https://github.com/WordPress/gutenberg/pull/66849#issuecomment-2463614281
const newSupports = {};
for ( const [ key, value ] of Object.entries( rawSupports ) ) {
if (
key === 'typography' &&
typeof value === 'object' &&
value !== null
) {
newSupports.typography = Object.fromEntries(
Object.entries( value ).map(
( [ typographyKey, typographyValue ] ) => [
TYPOGRAPHY_SUPPORTS_EXPERIMENTAL_TO_STABLE[
typographyKey
] || typographyKey,
typographyValue,
]
)
);
} else {
newSupports[ key ] = value;
}
}

return supports;
return newSupports;
}

/**
Expand Down Expand Up @@ -150,10 +165,12 @@ export const processBlockType =
if ( settings.deprecated ) {
settings.deprecated = settings.deprecated.map( ( deprecation ) => {
// Stabilize any experimental supports before applying filters.
deprecation.supports = stabilizeSupports(
deprecation.supports
);
const filteredDeprecation = // Only keep valid deprecation keys.
let filteredDeprecation = {
...deprecation,
supports: stabilizeSupports( deprecation.supports ),
};

filteredDeprecation = // Only keep valid deprecation keys.
applyFilters(
'blocks.registerBlockType',
// Merge deprecation keys with pre-filter settings
Expand All @@ -163,10 +180,10 @@ export const processBlockType =
// Omit deprecation keys here so that deprecations
// can opt out of specific keys like "supports".
...omit( blockType, DEPRECATED_ENTRY_KEYS ),
...deprecation,
...filteredDeprecation,
},
blockType.name,
deprecation
filteredDeprecation
);
// Re-stabilize any experimental supports after applying filters.
// This ensures that any supports updated by filters are also stabilized.
Expand Down
6 changes: 6 additions & 0 deletions packages/blocks/src/store/test/process-block-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,12 @@ describe( 'processBlockType', () => {
],
};

// Freeze the deprecated block object and its supports so that the original is not mutated.
// This ensures the test covers a regression where the original object was mutated.
// See: https://github.com/WordPress/gutenberg/pull/63401#discussion_r1832394335.
Object.freeze( blockSettings.deprecated[ 0 ] );
Object.freeze( blockSettings.deprecated[ 0 ].supports );

const processedBlockType = processBlockType(
'test/block',
blockSettings
Expand Down

0 comments on commit 457fcf8

Please sign in to comment.