mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Sandbox: Fix react class components stale state (#70572)
This commit is contained in:
parent
6c25342ecb
commit
53231cb68d
@ -1,6 +1,7 @@
|
||||
import { ProxyTarget } from '@locker/near-membrane-shared';
|
||||
import { isNearMembraneProxy, ProxyTarget } from '@locker/near-membrane-shared';
|
||||
|
||||
import { forbiddenElements } from './constants';
|
||||
import { isReactClassComponent } from './utils';
|
||||
|
||||
// IMPORTANT: NEVER export this symbol from a public (e.g `@grafana/*`) package
|
||||
const SANDBOX_LIVE_VALUE = Symbol.for('@@SANDBOX_LIVE_VALUE');
|
||||
@ -72,6 +73,31 @@ export function markDomElementStyleAsALiveTarget(el: Element) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Some specific near membrane proxies interfere with plugins
|
||||
* an example of this is React class components state and their fast life cycles
|
||||
* with cached objects.
|
||||
*
|
||||
* This function marks an object as a live target inside the sandbox
|
||||
* but not all objects, only the ones that are allowed to be modified
|
||||
*/
|
||||
export function patchObjectAsLiveTarget(obj: unknown) {
|
||||
if (
|
||||
obj &&
|
||||
// do not define it twice
|
||||
!Object.hasOwn(obj, SANDBOX_LIVE_VALUE) &&
|
||||
// only for proxies
|
||||
isNearMembraneProxy(obj) &&
|
||||
// do not patch functions
|
||||
!(obj instanceof Function) &&
|
||||
// conditions for allowed objects
|
||||
// react class components
|
||||
isReactClassComponent(obj)
|
||||
) {
|
||||
Reflect.defineProperty(obj, SANDBOX_LIVE_VALUE, {});
|
||||
}
|
||||
}
|
||||
|
||||
export function isLiveTarget(el: ProxyTarget) {
|
||||
return Object.hasOwn(el, SANDBOX_LIVE_VALUE);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
isDomElement,
|
||||
isLiveTarget,
|
||||
markDomElementStyleAsALiveTarget,
|
||||
patchObjectAsLiveTarget,
|
||||
} from './document_sandbox';
|
||||
import { sandboxPluginDependencies } from './plugin_dependencies';
|
||||
import { sandboxPluginComponents } from './sandbox_components';
|
||||
@ -48,6 +49,8 @@ async function doImportPluginModuleInSandbox(meta: PluginMeta): Promise<unknown>
|
||||
// the element.style attribute should be a live target to work in chrome
|
||||
markDomElementStyleAsALiveTarget(element);
|
||||
return element;
|
||||
} else {
|
||||
patchObjectAsLiveTarget(originalValue);
|
||||
}
|
||||
const distortion = generalDistortionMap.get(originalValue);
|
||||
if (distortion) {
|
||||
|
@ -1,3 +1,5 @@
|
||||
import React from 'react';
|
||||
|
||||
import { SandboxedPluginObject } from './types';
|
||||
|
||||
export function isSandboxedPluginObject(value: unknown): value is SandboxedPluginObject {
|
||||
@ -7,3 +9,7 @@ export function isSandboxedPluginObject(value: unknown): value is SandboxedPlugi
|
||||
export function assertNever(x: never): never {
|
||||
throw new Error(`Unexpected object: ${x}. This should never happen.`);
|
||||
}
|
||||
|
||||
export function isReactClassComponent(obj: unknown): obj is React.Component {
|
||||
return obj instanceof React.Component;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user