Skip to content

Commit a176c68

Browse files
committed
Add a test for bad Map polyfill
1 parent 0a2ed64 commit a176c68

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

packages/react-reconciler/src/__tests__/ReactIncremental-test.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2715,4 +2715,72 @@ describe('ReactIncremental', () => {
27152715

27162716
expect(ReactNoop.flush()).toEqual([]);
27172717
});
2718+
2719+
it('does not break with a bad Map polyfill', () => {
2720+
const realMapSet = Map.prototype.set;
2721+
2722+
function triggerCodePathThatUsesFibersAsMapKeys() {
2723+
function Thing() {
2724+
throw new Error('No.');
2725+
}
2726+
class Boundary extends React.Component {
2727+
state = {didError: false};
2728+
componentDidCatch() {
2729+
this.setState({didError: true});
2730+
}
2731+
render() {
2732+
return this.state.didError ? null : <Thing />;
2733+
}
2734+
}
2735+
ReactNoop.render(<Boundary />);
2736+
ReactNoop.flush();
2737+
}
2738+
2739+
// First, verify that this code path normally receives Fibers as keys,
2740+
// and that they're not extensible.
2741+
jest.resetModules();
2742+
let receivedNonExtensibleObjects;
2743+
Map.prototype.set = function(key) {
2744+
if (typeof key === 'object' && key !== null) {
2745+
if (!Object.isExtensible(key)) {
2746+
receivedNonExtensibleObjects = true;
2747+
}
2748+
}
2749+
return realMapSet.apply(this, arguments);
2750+
};
2751+
React = require('react');
2752+
ReactNoop = require('react-noop-renderer');
2753+
try {
2754+
receivedNonExtensibleObjects = false;
2755+
triggerCodePathThatUsesFibersAsMapKeys();
2756+
} finally {
2757+
Map.prototype.set = realMapSet;
2758+
}
2759+
// If this fails, find another code path in Fiber
2760+
// that passes Fibers as keys to Maps.
2761+
// Note that we only expect them to be non-extensible
2762+
// in development.
2763+
expect(receivedNonExtensibleObjects).toBe(__DEV__);
2764+
2765+
// Next, verify that a Map polyfill that "writes" to keys
2766+
// doesn't cause a failure.
2767+
jest.resetModules();
2768+
Map.prototype.set = function(key, value) {
2769+
if (typeof key === 'object' && key !== null) {
2770+
// A polyfill could do something like this.
2771+
// It would throw if an object is not extensible.
2772+
key.__internalValueSlot = value;
2773+
}
2774+
};
2775+
React = require('react');
2776+
ReactNoop = require('react-noop-renderer');
2777+
try {
2778+
triggerCodePathThatUsesFibersAsMapKeys();
2779+
} finally {
2780+
Map.prototype.set = realMapSet;
2781+
}
2782+
// If we got this far, our feature detection worked.
2783+
// We knew that Map#set() throws for non-extensible objects,
2784+
// so we didn't set them as non-extensible for that reason.
2785+
});
27182786
});

0 commit comments

Comments
 (0)