diff --git a/package-lock.json b/package-lock.json index a4184598a1d89..3074804685e8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11037,9 +11037,17 @@ "requires": { "@babel/runtime": "^7.8.3", "@wordpress/escape-html": "file:packages/escape-html", + "core-js-pure": "^3.6.4", "lodash": "^4.17.15", "react": "^16.9.0", "react-dom": "^16.9.0" + }, + "dependencies": { + "core-js-pure": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.4.tgz", + "integrity": "sha512-epIhRLkXdgv32xIUFaaAry2wdxZYBi6bgM7cB136dzzXXa+dFyRLTZeLUJxnd8ShrmyVXBub63n2NHo2JAt8Cw==" + } } }, "@wordpress/env": { diff --git a/packages/element/README.md b/packages/element/README.md index 1a51dea4046de..da805d2c5363d 100755 --- a/packages/element/README.md +++ b/packages/element/README.md @@ -313,7 +313,7 @@ Serializes a React element to string. _Parameters_ - _element_ `WPElement`: Element to serialize. -- _context_ `?Object`: Context object. +- _context_ `[Map]`: Context object. - _legacyContext_ `?Object`: Legacy context object. _Returns_ diff --git a/packages/element/package.json b/packages/element/package.json index 24a1efe4ef609..2f69438ba2825 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -25,6 +25,7 @@ "dependencies": { "@babel/runtime": "^7.8.3", "@wordpress/escape-html": "file:../escape-html", + "core-js-pure": "^3.6.4", "lodash": "^4.17.15", "react": "^16.9.0", "react-dom": "^16.9.0" diff --git a/packages/element/src/serialize.js b/packages/element/src/serialize.js index d5ef4e02a7758..54e63f824366d 100644 --- a/packages/element/src/serialize.js +++ b/packages/element/src/serialize.js @@ -36,6 +36,7 @@ import { kebabCase, isPlainObject, } from 'lodash'; +import CoreJSMap from 'core-js-pure/features/map'; /** * WordPress dependencies @@ -347,7 +348,7 @@ function getNormalStylePropertyValue( property, value ) { * Serializes a React element to string. * * @param {WPElement} element Element to serialize. - * @param {?Object} context Context object. + * @param {Map=} context Context object. * @param {?Object} legacyContext Legacy context object. * * @return {string} Serialized element. @@ -411,11 +412,18 @@ export function renderElement( element, context, legacyContext = {} ) { switch ( type && type.$$typeof ) { case Provider.$$typeof: - return renderChildren( props.children, props.value, legacyContext ); + context = context ? new CoreJSMap( context ) : new CoreJSMap(); + context.set( type, props.value ); + return renderChildren( props.children, context, legacyContext ); case Consumer.$$typeof: return renderElement( - props.children( context || type._currentValue ), + props.children( + ( context && + type._context && + context.get( type._context.Provider ) ) || + type._currentValue + ), context, legacyContext ); diff --git a/packages/element/src/test/serialize.js b/packages/element/src/test/serialize.js index d13cea967d41c..a3143345bb714 100644 --- a/packages/element/src/test/serialize.js +++ b/packages/element/src/test/serialize.js @@ -317,6 +317,75 @@ describe( 'renderElement()', () => { expect( result ).toBe( 'inner provided|outer provided' ); } ); + it( 'renders Context gracefully', () => { + const Context = createContext( 'Default' ); + + const result = renderElement( + { ( value ) => value } + ); + + expect( result ).toBe( 'Default' ); + } ); + + it( 'renders proper value through Context API when nested, distinct providers present', () => { + const { + Consumer: FirstConsumer, + Provider: FirstProvider, + } = createContext(); + const { + Consumer: SecondConsumer, + Provider: SecondProvider, + } = createContext(); + + const result = renderElement( + + + { ( first ) => ( + + + { ( second ) => + `First: ${ first }, Second: ${ second }` + } + + + ) } + + + ); + + expect( result ).toBe( 'First: First, Second: Second' ); + } ); + + it( 'renders proper value through Context API when nested, distinct providers present (mixed order)', () => { + const { + Consumer: FirstConsumer, + Provider: FirstProvider, + } = createContext(); + const { + Consumer: SecondConsumer, + Provider: SecondProvider, + } = createContext(); + + const result = renderElement( + + + + { ( first ) => ( + <> + First: { first }, Second:{ ' ' } + + { ( second ) => second } + + + ) } + + + + ); + + expect( result ).toBe( 'First: First, Second: Second' ); + } ); + it( 'renders RawHTML as its unescaped children', () => { const result = renderElement( { '' } );