feat(api): add method to force garbage collection (#32383)
This commit is contained in:
Родитель
5b28d2a84c
Коммит
f2a974b045
|
@ -256,6 +256,13 @@ class PageHandler {
|
||||||
return await this._contentPage.send('disposeObject', options);
|
return await this._contentPage.send('disposeObject', options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async ['Heap.collectGarbage']() {
|
||||||
|
Services.obs.notifyObservers(null, "child-gc-request");
|
||||||
|
Cu.forceGC();
|
||||||
|
Services.obs.notifyObservers(null, "child-cc-request");
|
||||||
|
Cu.forceCC();
|
||||||
|
}
|
||||||
|
|
||||||
async ['Network.getResponseBody']({requestId}) {
|
async ['Network.getResponseBody']({requestId}) {
|
||||||
return this._pageNetwork.getResponseBody(requestId);
|
return this._pageNetwork.getResponseBody(requestId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -487,6 +487,17 @@ const Browser = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Heap = {
|
||||||
|
targets: ['page'],
|
||||||
|
types: {},
|
||||||
|
events: {},
|
||||||
|
methods: {
|
||||||
|
'collectGarbage': {
|
||||||
|
params: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const Network = {
|
const Network = {
|
||||||
targets: ['page'],
|
targets: ['page'],
|
||||||
types: networkTypes,
|
types: networkTypes,
|
||||||
|
@ -1002,7 +1013,7 @@ const Accessibility = {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.protocol = {
|
this.protocol = {
|
||||||
domains: {Browser, Page, Runtime, Network, Accessibility},
|
domains: {Browser, Heap, Page, Runtime, Network, Accessibility},
|
||||||
};
|
};
|
||||||
this.checkScheme = checkScheme;
|
this.checkScheme = checkScheme;
|
||||||
this.EXPORTED_SYMBOLS = ['protocol', 'checkScheme'];
|
this.EXPORTED_SYMBOLS = ['protocol', 'checkScheme'];
|
||||||
|
|
|
@ -2333,6 +2333,11 @@ last redirect. If cannot go forward, returns `null`.
|
||||||
|
|
||||||
Navigate to the next page in history.
|
Navigate to the next page in history.
|
||||||
|
|
||||||
|
## async method: Page.forceGarbageCollection
|
||||||
|
* since: v1.47
|
||||||
|
|
||||||
|
Force the browser to perform garbage collection.
|
||||||
|
|
||||||
### option: Page.goForward.waitUntil = %%-navigation-wait-until-%%
|
### option: Page.goForward.waitUntil = %%-navigation-wait-until-%%
|
||||||
* since: v1.8
|
* since: v1.8
|
||||||
|
|
||||||
|
|
|
@ -468,6 +468,10 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
|
||||||
return Response.fromNullable((await this._channel.goForward({ ...options, waitUntil })).response);
|
return Response.fromNullable((await this._channel.goForward({ ...options, waitUntil })).response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async forceGarbageCollection() {
|
||||||
|
await this._channel.forceGarbageCollection();
|
||||||
|
}
|
||||||
|
|
||||||
async emulateMedia(options: { media?: 'screen' | 'print' | null, colorScheme?: 'dark' | 'light' | 'no-preference' | null, reducedMotion?: 'reduce' | 'no-preference' | null, forcedColors?: 'active' | 'none' | null } = {}) {
|
async emulateMedia(options: { media?: 'screen' | 'print' | null, colorScheme?: 'dark' | 'light' | 'no-preference' | null, reducedMotion?: 'reduce' | 'no-preference' | null, forcedColors?: 'active' | 'none' | null } = {}) {
|
||||||
await this._channel.emulateMedia({
|
await this._channel.emulateMedia({
|
||||||
media: options.media === null ? 'no-override' : options.media,
|
media: options.media === null ? 'no-override' : options.media,
|
||||||
|
|
|
@ -1122,6 +1122,8 @@ scheme.PageGoForwardParams = tObject({
|
||||||
scheme.PageGoForwardResult = tObject({
|
scheme.PageGoForwardResult = tObject({
|
||||||
response: tOptional(tChannel(['Response'])),
|
response: tOptional(tChannel(['Response'])),
|
||||||
});
|
});
|
||||||
|
scheme.PageForceGarbageCollectionParams = tOptional(tObject({}));
|
||||||
|
scheme.PageForceGarbageCollectionResult = tOptional(tObject({}));
|
||||||
scheme.PageRegisterLocatorHandlerParams = tObject({
|
scheme.PageRegisterLocatorHandlerParams = tObject({
|
||||||
selector: tString,
|
selector: tString,
|
||||||
noWaitAfter: tOptional(tBoolean),
|
noWaitAfter: tOptional(tBoolean),
|
||||||
|
|
|
@ -323,6 +323,10 @@ export class BidiPage implements PageDelegate {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async forceGarbageCollection(): Promise<void> {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
async addInitScript(initScript: InitScript): Promise<void> {
|
async addInitScript(initScript: InitScript): Promise<void> {
|
||||||
const { script } = await this._session.send('script.addPreloadScript', {
|
const { script } = await this._session.send('script.addPreloadScript', {
|
||||||
// TODO: remove function call from the source.
|
// TODO: remove function call from the source.
|
||||||
|
|
|
@ -247,6 +247,10 @@ export class CRPage implements PageDelegate {
|
||||||
return this._go(+1);
|
return this._go(+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async forceGarbageCollection(): Promise<void> {
|
||||||
|
await this._mainFrameSession._client.send('HeapProfiler.collectGarbage');
|
||||||
|
}
|
||||||
|
|
||||||
async addInitScript(initScript: InitScript, world: types.World = 'main'): Promise<void> {
|
async addInitScript(initScript: InitScript, world: types.World = 'main'): Promise<void> {
|
||||||
await this._forAllFrameSessions(frame => frame._evaluateOnNewDocument(initScript, world));
|
await this._forAllFrameSessions(frame => frame._evaluateOnNewDocument(initScript, world));
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,6 +137,10 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, Brows
|
||||||
return { response: ResponseDispatcher.fromNullable(this.parentScope(), await this._page.goForward(metadata, params)) };
|
return { response: ResponseDispatcher.fromNullable(this.parentScope(), await this._page.goForward(metadata, params)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async forceGarbageCollection(params: channels.PageForceGarbageCollectionParams, metadata: CallMetadata): Promise<channels.PageForceGarbageCollectionResult> {
|
||||||
|
await this._page.forceGarbageCollection();
|
||||||
|
}
|
||||||
|
|
||||||
async registerLocatorHandler(params: channels.PageRegisterLocatorHandlerParams, metadata: CallMetadata): Promise<channels.PageRegisterLocatorHandlerResult> {
|
async registerLocatorHandler(params: channels.PageRegisterLocatorHandlerParams, metadata: CallMetadata): Promise<channels.PageRegisterLocatorHandlerResult> {
|
||||||
const uid = this._page.registerLocatorHandler(params.selector, params.noWaitAfter);
|
const uid = this._page.registerLocatorHandler(params.selector, params.noWaitAfter);
|
||||||
return { uid };
|
return { uid };
|
||||||
|
|
|
@ -400,6 +400,10 @@ export class FFPage implements PageDelegate {
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async forceGarbageCollection(): Promise<void> {
|
||||||
|
await this._session.send('Heap.collectGarbage');
|
||||||
|
}
|
||||||
|
|
||||||
async addInitScript(initScript: InitScript, worldName?: string): Promise<void> {
|
async addInitScript(initScript: InitScript, worldName?: string): Promise<void> {
|
||||||
this._initScripts.push({ initScript, worldName });
|
this._initScripts.push({ initScript, worldName });
|
||||||
await this._session.send('Page.setInitScripts', { scripts: this._initScripts.map(s => ({ script: s.initScript.source, worldName: s.worldName })) });
|
await this._session.send('Page.setInitScripts', { scripts: this._initScripts.map(s => ({ script: s.initScript.source, worldName: s.worldName })) });
|
||||||
|
|
|
@ -54,6 +54,7 @@ export interface PageDelegate {
|
||||||
reload(): Promise<void>;
|
reload(): Promise<void>;
|
||||||
goBack(): Promise<boolean>;
|
goBack(): Promise<boolean>;
|
||||||
goForward(): Promise<boolean>;
|
goForward(): Promise<boolean>;
|
||||||
|
forceGarbageCollection(): Promise<void>;
|
||||||
addInitScript(initScript: InitScript): Promise<void>;
|
addInitScript(initScript: InitScript): Promise<void>;
|
||||||
removeNonInternalInitScripts(): Promise<void>;
|
removeNonInternalInitScripts(): Promise<void>;
|
||||||
closePage(runBeforeUnload: boolean): Promise<void>;
|
closePage(runBeforeUnload: boolean): Promise<void>;
|
||||||
|
@ -430,6 +431,10 @@ export class Page extends SdkObject {
|
||||||
}), this._timeoutSettings.navigationTimeout(options));
|
}), this._timeoutSettings.navigationTimeout(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
forceGarbageCollection(): Promise<void> {
|
||||||
|
return this._delegate.forceGarbageCollection();
|
||||||
|
}
|
||||||
|
|
||||||
registerLocatorHandler(selector: string, noWaitAfter: boolean | undefined) {
|
registerLocatorHandler(selector: string, noWaitAfter: boolean | undefined) {
|
||||||
const uid = ++this._lastLocatorHandlerUid;
|
const uid = ++this._lastLocatorHandlerUid;
|
||||||
this._locatorHandlers.set(uid, { selector, noWaitAfter });
|
this._locatorHandlers.set(uid, { selector, noWaitAfter });
|
||||||
|
|
|
@ -768,6 +768,10 @@ export class WKPage implements PageDelegate {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async forceGarbageCollection(): Promise<void> {
|
||||||
|
await this._session.send('Heap.gc');
|
||||||
|
}
|
||||||
|
|
||||||
async addInitScript(initScript: InitScript): Promise<void> {
|
async addInitScript(initScript: InitScript): Promise<void> {
|
||||||
await this._updateBootstrapScript();
|
await this._updateBootstrapScript();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2554,6 +2554,11 @@ export interface Page {
|
||||||
timeout?: number;
|
timeout?: number;
|
||||||
}): Promise<void>;
|
}): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force the browser to perform garbage collection.
|
||||||
|
*/
|
||||||
|
forceGarbageCollection(): Promise<void>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns frame matching the specified criteria. Either `name` or `url` must be specified.
|
* Returns frame matching the specified criteria. Either `name` or `url` must be specified.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1933,6 +1933,7 @@ export interface PageChannel extends PageEventTarget, EventTargetChannel {
|
||||||
exposeBinding(params: PageExposeBindingParams, metadata?: CallMetadata): Promise<PageExposeBindingResult>;
|
exposeBinding(params: PageExposeBindingParams, metadata?: CallMetadata): Promise<PageExposeBindingResult>;
|
||||||
goBack(params: PageGoBackParams, metadata?: CallMetadata): Promise<PageGoBackResult>;
|
goBack(params: PageGoBackParams, metadata?: CallMetadata): Promise<PageGoBackResult>;
|
||||||
goForward(params: PageGoForwardParams, metadata?: CallMetadata): Promise<PageGoForwardResult>;
|
goForward(params: PageGoForwardParams, metadata?: CallMetadata): Promise<PageGoForwardResult>;
|
||||||
|
forceGarbageCollection(params?: PageForceGarbageCollectionParams, metadata?: CallMetadata): Promise<PageForceGarbageCollectionResult>;
|
||||||
registerLocatorHandler(params: PageRegisterLocatorHandlerParams, metadata?: CallMetadata): Promise<PageRegisterLocatorHandlerResult>;
|
registerLocatorHandler(params: PageRegisterLocatorHandlerParams, metadata?: CallMetadata): Promise<PageRegisterLocatorHandlerResult>;
|
||||||
resolveLocatorHandlerNoReply(params: PageResolveLocatorHandlerNoReplyParams, metadata?: CallMetadata): Promise<PageResolveLocatorHandlerNoReplyResult>;
|
resolveLocatorHandlerNoReply(params: PageResolveLocatorHandlerNoReplyParams, metadata?: CallMetadata): Promise<PageResolveLocatorHandlerNoReplyResult>;
|
||||||
unregisterLocatorHandler(params: PageUnregisterLocatorHandlerParams, metadata?: CallMetadata): Promise<PageUnregisterLocatorHandlerResult>;
|
unregisterLocatorHandler(params: PageUnregisterLocatorHandlerParams, metadata?: CallMetadata): Promise<PageUnregisterLocatorHandlerResult>;
|
||||||
|
@ -2070,6 +2071,9 @@ export type PageGoForwardOptions = {
|
||||||
export type PageGoForwardResult = {
|
export type PageGoForwardResult = {
|
||||||
response?: ResponseChannel,
|
response?: ResponseChannel,
|
||||||
};
|
};
|
||||||
|
export type PageForceGarbageCollectionParams = {};
|
||||||
|
export type PageForceGarbageCollectionOptions = {};
|
||||||
|
export type PageForceGarbageCollectionResult = void;
|
||||||
export type PageRegisterLocatorHandlerParams = {
|
export type PageRegisterLocatorHandlerParams = {
|
||||||
selector: string,
|
selector: string,
|
||||||
noWaitAfter?: boolean,
|
noWaitAfter?: boolean,
|
||||||
|
|
|
@ -1430,6 +1430,8 @@ Page:
|
||||||
slowMo: true
|
slowMo: true
|
||||||
snapshot: true
|
snapshot: true
|
||||||
|
|
||||||
|
forceGarbageCollection:
|
||||||
|
|
||||||
registerLocatorHandler:
|
registerLocatorHandler:
|
||||||
parameters:
|
parameters:
|
||||||
selector: string
|
selector: string
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2024 Adobe Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { test, expect } from './pageTest';
|
||||||
|
|
||||||
|
test('should work', async ({ page }) => {
|
||||||
|
await page.evaluate(() => {
|
||||||
|
globalThis.objectToDestroy = {};
|
||||||
|
globalThis.weakRef = new WeakRef(globalThis.objectToDestroy);
|
||||||
|
});
|
||||||
|
await page.evaluate(() => globalThis.objectToDestroy = null);
|
||||||
|
await page.forceGarbageCollection();
|
||||||
|
expect(await page.evaluate(() => globalThis.weakRef.deref())).toBe(undefined);
|
||||||
|
});
|
Загрузка…
Ссылка в новой задаче