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 { forbiddenElements } from './constants';
|
||||||
|
import { isReactClassComponent } from './utils';
|
||||||
|
|
||||||
// IMPORTANT: NEVER export this symbol from a public (e.g `@grafana/*`) package
|
// IMPORTANT: NEVER export this symbol from a public (e.g `@grafana/*`) package
|
||||||
const SANDBOX_LIVE_VALUE = Symbol.for('@@SANDBOX_LIVE_VALUE');
|
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) {
|
export function isLiveTarget(el: ProxyTarget) {
|
||||||
return Object.hasOwn(el, SANDBOX_LIVE_VALUE);
|
return Object.hasOwn(el, SANDBOX_LIVE_VALUE);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
isDomElement,
|
isDomElement,
|
||||||
isLiveTarget,
|
isLiveTarget,
|
||||||
markDomElementStyleAsALiveTarget,
|
markDomElementStyleAsALiveTarget,
|
||||||
|
patchObjectAsLiveTarget,
|
||||||
} from './document_sandbox';
|
} from './document_sandbox';
|
||||||
import { sandboxPluginDependencies } from './plugin_dependencies';
|
import { sandboxPluginDependencies } from './plugin_dependencies';
|
||||||
import { sandboxPluginComponents } from './sandbox_components';
|
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
|
// the element.style attribute should be a live target to work in chrome
|
||||||
markDomElementStyleAsALiveTarget(element);
|
markDomElementStyleAsALiveTarget(element);
|
||||||
return element;
|
return element;
|
||||||
|
} else {
|
||||||
|
patchObjectAsLiveTarget(originalValue);
|
||||||
}
|
}
|
||||||
const distortion = generalDistortionMap.get(originalValue);
|
const distortion = generalDistortionMap.get(originalValue);
|
||||||
if (distortion) {
|
if (distortion) {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
import { SandboxedPluginObject } from './types';
|
import { SandboxedPluginObject } from './types';
|
||||||
|
|
||||||
export function isSandboxedPluginObject(value: unknown): value is SandboxedPluginObject {
|
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 {
|
export function assertNever(x: never): never {
|
||||||
throw new Error(`Unexpected object: ${x}. This should never happen.`);
|
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