fix(reuse): clear storage after stopping all scripts (#16275)

This commit is contained in:
Pavel Feldman 2022-08-04 16:39:18 -07:00 committed by GitHub
parent 4b53be4849
commit 97fa2518e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 23 additions and 31 deletions

View File

@ -383,20 +383,20 @@ async function createDefaultTodos(page: Page) {
} }
} }
async function checkNumberOfTodosInLocalStorage(page: Page, expected: number) { async function checkNumberOfCompletedTodosInLocalStorage(page: Page, expected: number) {
return await page.waitForFunction(e => { await expect.poll(() => {
return JSON.parse(localStorage['react-todos']).length === e; return page.evaluate(() => JSON.parse(localStorage['react-todos']).filter(i => i.completed).length);
}, expected); }).toBe(expected);
} }
async function checkNumberOfCompletedTodosInLocalStorage(page: Page, expected: number) { async function checkNumberOfTodosInLocalStorage(page: Page, expected: number) {
return await page.waitForFunction(e => { await expect.poll(() => {
return JSON.parse(localStorage['react-todos']).filter(i => i.completed).length === e; return page.evaluate(() => JSON.parse(localStorage['react-todos']).length);
}, expected); }).toBe(expected);
} }
async function checkTodosInLocalStorage(page: Page, title: string) { async function checkTodosInLocalStorage(page: Page, title: string) {
return await page.waitForFunction(t => { await expect.poll(() => {
return JSON.parse(localStorage['react-todos']).map(i => i.title).includes(t); return page.evaluate(() => JSON.parse(localStorage['react-todos']).map(i => i.title));
}, title); }).toContain(title);
} }

View File

@ -178,10 +178,9 @@ export abstract class BrowserContext extends SdkObject {
// Unless I do this early, setting extra http headers below does not respond. // Unless I do this early, setting extra http headers below does not respond.
await page?._frameManager.closeOpenDialogs(); await page?._frameManager.closeOpenDialogs();
// This should be before the navigation to about:blank so that we could save on // Navigate to about:blank first to ensure no page scripts are running after this point.
// a navigation as we clear local storage.
await this._clearStorage();
await page?.mainFrame().goto(metadata, 'about:blank', { timeout: 0 }); await page?.mainFrame().goto(metadata, 'about:blank', { timeout: 0 });
await this._clearStorage();
await this._removeExposedBindings(); await this._removeExposedBindings();
await this._removeInitScripts(); await this._removeInitScripts();
// TODO: following can be optimized to not perform noops. // TODO: following can be optimized to not perform noops.
@ -475,15 +474,7 @@ export abstract class BrowserContext extends SdkObject {
if (!this._origins.size) if (!this._origins.size)
return; return;
let page = this.pages()[0]; let page = this.pages()[0];
const originArray = [...this._origins];
// Fast path.
if (page && originArray.length === 1 && page.mainFrame().url().startsWith(originArray[0])) {
await page.mainFrame().clearStorageForCurrentOriginBestEffort();
return;
}
// Slow path.
const internalMetadata = serverSideCallMetadata(); const internalMetadata = serverSideCallMetadata();
page = page || await this.newPage(internalMetadata); page = page || await this.newPage(internalMetadata);
await page._setServerRequestInterceptor(handler => { await page._setServerRequestInterceptor(handler => {
@ -495,6 +486,7 @@ export abstract class BrowserContext extends SdkObject {
await frame.clearStorageForCurrentOriginBestEffort(); await frame.clearStorageForCurrentOriginBestEffort();
} }
await page._setServerRequestInterceptor(undefined); await page._setServerRequestInterceptor(undefined);
// It is safe to not restore the URL to about:blank since we are doing it in Page::resetForReuse.
} }
isSettingStorageState(): boolean { isSettingStorageState(): boolean {

View File

@ -231,16 +231,12 @@ export class Page extends SdkObject {
this.setDefaultNavigationTimeout(undefined); this.setDefaultNavigationTimeout(undefined);
this.setDefaultTimeout(undefined); this.setDefaultTimeout(undefined);
// Do this first in order to unfreeze evaluates.
await this._frameManager.closeOpenDialogs();
await this._removeExposedBindings(); await this._removeExposedBindings();
await this._removeInitScripts(); await this._removeInitScripts();
// TODO: handle pending routes.
await this.setClientRequestInterceptor(undefined); await this.setClientRequestInterceptor(undefined);
await this._setServerRequestInterceptor(undefined); await this._setServerRequestInterceptor(undefined);
await this.setFileChooserIntercepted(false); await this.setFileChooserIntercepted(false);
// Re-navigate once init scripts are gone.
await this.mainFrame().goto(metadata, 'about:blank'); await this.mainFrame().goto(metadata, 'about:blank');
this._emulatedSize = undefined; this._emulatedSize = undefined;
this._emulatedMedia = {}; this._emulatedMedia = {};

View File

@ -184,10 +184,14 @@ test('should clean storage', async ({ runInlineTest }) => {
test('one', async ({ context, page }) => { test('one', async ({ context, page }) => {
lastContextGuid = context._guid; lastContextGuid = context._guid;
await page.evaluate(async () => { // Spam local storage.
localStorage.foo = 'bar'; page.evaluate(async () => {
sessionStorage.foo = 'bar'; while (true) {
}); localStorage.foo = 'bar';
sessionStorage.foo = 'bar';
await new Promise(f => setTimeout(f, 0));
}
}).catch(() => {});
const local = await page.evaluate('localStorage.foo'); const local = await page.evaluate('localStorage.foo');
const session = await page.evaluate('sessionStorage.foo'); const session = await page.evaluate('sessionStorage.foo');