Skip to content

Commit

Permalink
color picker crashes studio inside iframe (#1989)
Browse files Browse the repository at this point in the history
  • Loading branch information
igorDykhta committed Sep 30, 2022
1 parent 73dba52 commit 51a05ff
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 1 deletion.
17 changes: 17 additions & 0 deletions src/components/src/common/portaled.tsx
Expand Up @@ -161,6 +161,13 @@ interface PortaledState {
}

class Portaled extends Component<PortaledProps, PortaledState> {
// Make Portaled a component with Error Boundary, so React can recreate
// this component if the child 'ColorPicker' throws cross-origin error.
// see function componentDidCatch()
static getDerivedStateFromError() {
return {hasError: true};
}

static defaultProps = {
component: 'div',
onClose: noop,
Expand Down Expand Up @@ -194,6 +201,16 @@ class Portaled extends Component<PortaledProps, PortaledState> {
this.handleScroll();
}

// ColorPicker will throw a cross-origin error when it is closed
// when the app is within an iframe.
// This is a known issue of react-color component:
// see: https://github.com/casesandberg/react-color/issues/806
componentDidCatch() {
// Do nothing here, since React will try to recreate this component
// tree from scratch using the error boundary, which is this component
// itself. This is a temporal fix for a crash.
}

componentWillUnmount() {
this._unmounted = true;
// @ts-ignore
Expand Down
9 changes: 8 additions & 1 deletion test/browser/components/side-panel/color-selector-test.js
Expand Up @@ -41,7 +41,8 @@ import {
ColorPalette,
CustomPalette,
CustomPicker,
Button
Button,
Portaled
} from '@kepler.gl/components';

import {COLOR_RANGES} from '@kepler.gl/constants';
Expand Down Expand Up @@ -781,5 +782,11 @@ test('Components -> LayerColorRangeSelector.render -> ColorSelector -> ColorRang
const picker = cp.find(CustomPicker);
t.equal(picker.length, 1, 'should render 1 CustomPicker');

// SecurityError (e.g. cross-origin error) should be handled in Portaled component
t.doesNotThrow(() => {
picker.simulateError({name: 'SecurityError', message: '', stack: []});
t.equal(wrapper.find(Portaled).length, 1);
}, 'Should not fail with SecurityError when close CustomPicker');

t.end();
});

0 comments on commit 51a05ff

Please sign in to comment.