diff --git a/scripts/fiber/tests-passing.txt b/scripts/fiber/tests-passing.txt
index 34f94bffeee..82b33be0f6c 100644
--- a/scripts/fiber/tests-passing.txt
+++ b/scripts/fiber/tests-passing.txt
@@ -49,6 +49,8 @@ src/addons/__tests__/renderSubtreeIntoContainer-test.js
* should update context if it changes due to setState
* should update context if it changes due to re-render
* should render portal with non-context-provider parent
+* should get context through non-context-provider parent
+* should get context through middle non-context-provider layer
src/addons/__tests__/update-test.js
* pushes
diff --git a/src/addons/__tests__/renderSubtreeIntoContainer-test.js b/src/addons/__tests__/renderSubtreeIntoContainer-test.js
index 7ed20edeeaf..95db6c24351 100644
--- a/src/addons/__tests__/renderSubtreeIntoContainer-test.js
+++ b/src/addons/__tests__/renderSubtreeIntoContainer-test.js
@@ -215,4 +215,86 @@ describe('renderSubtreeIntoContainer', () => {
expect(portal.firstChild.innerHTML).toBe('hello');
});
+ it('should get context through non-context-provider parent', () => {
+ var container = document.createElement('div');
+ document.body.appendChild(container);
+ var portal = document.createElement('div');
+
+ class Parent extends React.Component {
+ render() {
+ return ;
+ }
+ getChildContext() {
+ return {value: this.props.value};
+ }
+ static childContextTypes = {
+ value: React.PropTypes.string.isRequired,
+ };
+ }
+
+ class Middle extends React.Component {
+ render() {
+ return null;
+ }
+ componentDidMount() {
+ renderSubtreeIntoContainer(this, , portal);
+ }
+ }
+
+ class Child extends React.Component {
+ static contextTypes = {
+ value: React.PropTypes.string.isRequired,
+ };
+ render() {
+ return
{this.context.value}
;
+ }
+ }
+
+ ReactDOM.render(, container);
+ expect(portal.textContent).toBe('foo');
+ });
+
+ it('should get context through middle non-context-provider layer', () => {
+ var container = document.createElement('div');
+ document.body.appendChild(container);
+ var portal1 = document.createElement('div');
+ var portal2 = document.createElement('div');
+
+ class Parent extends React.Component {
+ render() {
+ return null;
+ }
+ getChildContext() {
+ return {value: this.props.value};
+ }
+ componentDidMount() {
+ renderSubtreeIntoContainer(this, , portal1);
+ }
+ static childContextTypes = {
+ value: React.PropTypes.string.isRequired,
+ };
+ }
+
+ class Middle extends React.Component {
+ render() {
+ return null;
+ }
+ componentDidMount() {
+ renderSubtreeIntoContainer(this, , portal2);
+ }
+ }
+
+ class Child extends React.Component {
+ static contextTypes = {
+ value: React.PropTypes.string.isRequired,
+ };
+ render() {
+ return {this.context.value}
;
+ }
+ }
+
+ ReactDOM.render(, container);
+ expect(portal2.textContent).toBe('foo');
+ });
+
});
diff --git a/src/renderers/shared/fiber/ReactFiberContext.js b/src/renderers/shared/fiber/ReactFiberContext.js
index e18e35e2706..6cb171c6729 100644
--- a/src/renderers/shared/fiber/ReactFiberContext.js
+++ b/src/renderers/shared/fiber/ReactFiberContext.js
@@ -22,6 +22,7 @@ var {
} = require('ReactFiberTreeReflection');
var {
ClassComponent,
+ HostContainer,
} = require('ReactTypeOfWork');
if (__DEV__) {
@@ -137,12 +138,14 @@ exports.findCurrentUnmaskedContext = function(fiber: Fiber) : Object {
'Expected subtree parent to be a mounted class component'
);
- let node : ?Fiber = parent;
- while (node) {
- if (isContextProvider(fiber)) {
- return fiber.stateNode.__reactInternalMemoizedMergedChildContext;
+ let node : Fiber = fiber;
+ while (node.tag !== HostContainer) {
+ if (isContextProvider(node)) {
+ return node.stateNode.__reactInternalMemoizedMergedChildContext;
}
- node = node.return;
+ const parent = node.return;
+ invariant(parent, 'Found unexpected detached subtree parent');
+ node = parent;
}
- return emptyObject;
+ return node.stateNode.context;
};