refactor: remove the RenderFrameFunctionStore and use privates to memory manage (#23592)

This commit is contained in:
Samuel Attard 2020-05-15 11:57:40 -07:00 committed by GitHub
parent 3cf97d5717
commit 9d7ba98209
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 166 additions and 261 deletions

View file

@ -78,7 +78,8 @@ describe('contextBridge', () => {
contextIsolation: true,
nodeIntegration: true,
sandbox: useSandbox,
preload: path.resolve(tmpDir, 'preload.js')
preload: path.resolve(tmpDir, 'preload.js'),
additionalArguments: ['--unsafely-expose-electron-internals-for-testing']
}
});
await w.loadURL(`http://127.0.0.1:${(server.address() as AddressInfo).port}`);
@ -88,15 +89,20 @@ describe('contextBridge', () => {
w.webContents.executeJavaScript(`(${fn.toString()})(window)`);
const getGCInfo = async (): Promise<{
functionCount: number
objectCount: number
liveFromValues: number
liveProxyValues: number
trackedValues: number;
}> => {
const [, info] = await emittedOnce(ipcMain, 'gc-info', () => w.webContents.send('get-gc-info'));
return info;
};
const forceGCOnWindow = async () => {
w.webContents.debugger.attach();
await w.webContents.debugger.sendCommand('HeapProfiler.enable');
await w.webContents.debugger.sendCommand('HeapProfiler.collectGarbage');
await w.webContents.debugger.sendCommand('HeapProfiler.disable');
w.webContents.debugger.detach();
};
it('should proxy numbers', async () => {
await makeBindingWindow(() => {
contextBridge.exposeInMainWorld('example', {
@ -341,45 +347,56 @@ describe('contextBridge', () => {
if (!useSandbox) {
it('should release the global hold on methods sent across contexts', async () => {
await makeBindingWindow(() => {
require('electron').ipcRenderer.on('get-gc-info', e => e.sender.send('gc-info', contextBridge.debugGC()));
require('electron').ipcRenderer.on('get-gc-info', e => e.sender.send('gc-info', { trackedValues: process.electronBinding('v8_util').getWeaklyTrackedValues().length }));
const { weaklyTrackValue } = process.electronBinding('v8_util');
contextBridge.exposeInMainWorld('example', {
getFunction: () => () => 123
getFunction: () => () => 123,
track: weaklyTrackValue
});
});
await callWithBindings(async (root: any) => {
root.GCRunner.run();
});
const baseValue = (await getGCInfo()).functionCount;
expect((await getGCInfo()).trackedValues).to.equal(0);
await callWithBindings(async (root: any) => {
root.x = [root.example.getFunction()];
const fn = root.example.getFunction();
root.example.track(fn);
root.x = [fn];
});
expect((await getGCInfo()).functionCount).to.equal(baseValue + 1);
expect((await getGCInfo()).trackedValues).to.equal(1);
await callWithBindings(async (root: any) => {
root.x = [];
root.GCRunner.run();
});
expect((await getGCInfo()).functionCount).to.equal(baseValue);
expect((await getGCInfo()).trackedValues).to.equal(0);
});
}
if (useSandbox) {
it('should not leak the global hold on methods sent across contexts when reloading a sandboxed renderer', async () => {
await makeBindingWindow(() => {
require('electron').ipcRenderer.on('get-gc-info', e => e.sender.send('gc-info', contextBridge.debugGC()));
require('electron').ipcRenderer.on('get-gc-info', e => e.sender.send('gc-info', { trackedValues: process.electronBinding('v8_util').getWeaklyTrackedValues().length }));
const { weaklyTrackValue } = process.electronBinding('v8_util');
contextBridge.exposeInMainWorld('example', {
getFunction: () => () => 123
getFunction: () => () => 123,
track: weaklyTrackValue
});
require('electron').ipcRenderer.send('window-ready-for-tasking');
});
const loadPromise = emittedOnce(ipcMain, 'window-ready-for-tasking');
const baseValue = (await getGCInfo()).functionCount;
expect((await getGCInfo()).trackedValues).to.equal(0);
await callWithBindings((root: any) => {
root.example.track(root.example.getFunction());
});
expect((await getGCInfo()).trackedValues).to.equal(1);
await callWithBindings((root: any) => {
root.location.reload();
});
await loadPromise;
await forceGCOnWindow();
// If this is ever "2" it means we leaked the exposed function and
// therefore the entire context after a reload
expect((await getGCInfo()).functionCount).to.equal(baseValue);
expect((await getGCInfo()).trackedValues).to.equal(0);
});
}