Skip to content

Commit

Permalink
Future-proof clearing providers for future react-dom versions
Browse files Browse the repository at this point in the history
  • Loading branch information
overlookmotel committed Feb 16, 2019
1 parent d09d7a3 commit 7ec6279
Showing 1 changed file with 31 additions and 17 deletions.
48 changes: 31 additions & 17 deletions lib/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,30 +67,40 @@ class PartialRenderer extends ReactDOMServerRenderer {
}

/*
* `.destroy()` and `.clearProviders()` methods are added here to fix bug in ReactDOM 16.7.0.
* `.destroy()` and `.clearProviders()` methods are added here to fix bug in
* ReactDOM 16.7.0-16.8.2.
* See https://github.com/facebook/react/issues/14705
* This bug will have worse effects with this extension of the class, as contexts are added
* to the context stack without adding to the frame stack, so leftover context values
* crossing over into other threads will be much more common.
* These prototype methods are removed again at bottom of this script if `.clearProviders()`
* prototype method exists already on ReactDOMServerRenderer.
* TODO Alter this depending on outcome of ReactDOM issue and how it is fixed.
* This bug will have worse effects with this extension of the class, as
* contexts are added to the context stack without adding to the frame
* stack, so leftover context values crossing over into other threads will
* be much more common.
* `.destroy()` prototype method is removed again at bottom of this script
* if `.clearProviders()` prototype method exists already on
* ReactDOMServerRenderer.
*
* TODO Alter this when updating to ReactDOM > 16.8.2 which includes
* commit fixing this lands in stable release.
* https://github.com/facebook/react/commit/ab7a67b1dc0e44bf74545ccf51a8c143b3af7402
*/
destroy() {
if (!this.exhausted) this.clearProviders();
super.destroy();
}

clearProviders() {
while (this.contextIndex > -1) {
if (isDev) {
this.popProvider(this.contextProviderStack[this.contextIndex]);
} else {
this.popProvider();
}
// Restore any remaining providers on the stack to previous values
for (let index = this.contextIndex; index >= 0; index--) {
const context = this.contextStack[index];
const previousValue = this.contextValueStack[index];
context[this.threadID] = previousValue;
}
}

resetProviders() {
this.clearProviders();
this.contextIndex = -1;
}

/*
* Read async
*/
Expand Down Expand Up @@ -370,7 +380,7 @@ class PartialRenderer extends ReactDOMServerRenderer {
this.cycle();

// Clear contexts added in `.restoreStack()`
this.clearProviders();
this.resetProviders();
}

restoreStack(stackState, element) {
Expand Down Expand Up @@ -437,7 +447,7 @@ class PartialRenderer extends ReactDOMServerRenderer {
if (!boundaryFrame) {
// Clear current render cycle state
this.stack.length = 1;
this.clearProviders();
this.resetProviders();

// Restore stack and render fallback.
// NB Render cycle already in progress, so no need to call `.read()` again.
Expand Down Expand Up @@ -595,8 +605,12 @@ function abort(promise) {
if (typeof promise.abort === 'function') promise.abort();
}

// If ReactDOM is version which already has `.clearProviders()` method,
// remove the version added in the subclass (see comments above on methods)
/*
* If ReactDOM is version which already has `.clearProviders()` method on
* `PartialRenderer` class, remove `.destroy()` and `.clearProviders()` methods
* overrides in this subclass.
* (see comments above on `.destroy()` method)
*/
if (ReactDOMServerRenderer.prototype.clearProviders) {
delete PartialRenderer.prototype.clearProviders;
delete PartialRenderer.prototype.destroy;
Expand Down

0 comments on commit 7ec6279

Please sign in to comment.