Sandbox: Patch array vector prototype methods inside the sandbox (#75835)

This commit is contained in:
Esteban Beltran 2023-10-03 09:02:55 +02:00 committed by GitHub
parent 0c404a4cd9
commit 677a2ad4d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 33 deletions

View File

@ -13,42 +13,46 @@ declare global {
// JS original sin
// this if condition is because Jest will re-exec this block multiple times (in a browser this only runs once)
if (!Object.getOwnPropertyDescriptor(Array.prototype, 'toArray')) {
Object.defineProperties(Array.prototype, {
get: {
value: function (idx: number) {
return this[idx];
export function patchArrayVectorProrotypeMethods() {
if (!Object.getOwnPropertyDescriptor(Array.prototype, 'toArray')) {
Object.defineProperties(Array.prototype, {
get: {
value: function (idx: number) {
return this[idx];
},
writable: true,
enumerable: false,
configurable: true,
},
writable: true,
enumerable: false,
configurable: true,
},
set: {
value: function (idx: number, value: unknown) {
this[idx] = value;
set: {
value: function (idx: number, value: unknown) {
this[idx] = value;
},
writable: true,
enumerable: false,
configurable: true,
},
writable: true,
enumerable: false,
configurable: true,
},
add: {
value: function (value: unknown) {
this.push(value);
add: {
value: function (value: unknown) {
this.push(value);
},
writable: true,
enumerable: false,
configurable: true,
},
writable: true,
enumerable: false,
configurable: true,
},
toArray: {
value: function () {
return this;
toArray: {
value: function () {
return this;
},
writable: true,
enumerable: false,
configurable: true,
},
writable: true,
enumerable: false,
configurable: true,
},
});
});
}
}
//this function call is intentional
patchArrayVectorProrotypeMethods();
/** @deprecated use a simple Array<T> */
export interface Vector<T = any> extends Array<T> {

View File

@ -1,4 +1,4 @@
import { PluginMeta } from '@grafana/data';
import { PluginMeta, patchArrayVectorProrotypeMethods } from '@grafana/data';
import { transformPluginSourceForCDN } from '../cdn/utils';
import { resolveWithCache } from '../loader/cache';
@ -91,3 +91,11 @@ function patchPluginSourceMap(meta: PluginMeta, pluginCode: string): string {
}
return pluginCode;
}
export function patchSandboxEnvironmentPrototype(sandboxEnvironment: SandboxEnvironment) {
// same as https://github.com/grafana/grafana/blob/main/packages/grafana-data/src/types/vector.ts#L16
// Array is a "reflective" type in Near-membrane and doesn't get an identify continuity
sandboxEnvironment.evaluate(
`${patchArrayVectorProrotypeMethods.toString()};${patchArrayVectorProrotypeMethods.name}()`
);
}

View File

@ -7,7 +7,7 @@ import { defaultTrustedTypesPolicy } from 'app/core/trustedTypePolicies';
import { getPluginSettings } from '../pluginSettings';
import { getPluginCode } from './code_loader';
import { getPluginCode, patchSandboxEnvironmentPrototype } from './code_loader';
import { getGeneralSandboxDistortionMap, distortLiveApis } from './distortion_map';
import {
getSafeSandboxDomElement,
@ -179,6 +179,8 @@ async function doImportPluginModuleInSandbox(meta: PluginMeta): Promise<System.M
},
});
patchSandboxEnvironmentPrototype(sandboxEnvironment);
// fetch plugin's code
let pluginCode = '';
try {