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( { '' } );