mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
fix(dispose): do not await inner handle dispose (#1230)
This commit is contained in:
parent
5ee744cd26
commit
3bedc60b2b
@ -483,7 +483,7 @@ export class CRPage implements PageDelegate {
|
||||
});
|
||||
const frameId = nodeInfo && typeof nodeInfo.node.frameId === 'string' ?
|
||||
nodeInfo.node.frameId : null;
|
||||
await documentElement.dispose();
|
||||
documentElement.dispose();
|
||||
return frameId;
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { assert, debugError } from '../helper';
|
||||
import { assert } from '../helper';
|
||||
import { CRSession } from './crConnection';
|
||||
import { Protocol } from './protocol';
|
||||
import * as platform from '../platform';
|
||||
@ -58,11 +58,7 @@ export function valueFromRemoteObject(remoteObject: Protocol.Runtime.RemoteObjec
|
||||
export async function releaseObject(client: CRSession, remoteObject: Protocol.Runtime.RemoteObject) {
|
||||
if (!remoteObject.objectId)
|
||||
return;
|
||||
await client.send('Runtime.releaseObject', {objectId: remoteObject.objectId}).catch(error => {
|
||||
// Exceptions might happen in case of a page been navigated or closed.
|
||||
// Swallow these since they are harmless and we don't leak anything in this case.
|
||||
debugError(error);
|
||||
});
|
||||
await client.send('Runtime.releaseObject', {objectId: remoteObject.objectId}).catch(error => {});
|
||||
}
|
||||
|
||||
export async function readProtocolStream(client: CRSession, handle: string, path: string | null): Promise<platform.BufferType> {
|
||||
|
12
src/dom.ts
12
src/dom.ts
@ -67,7 +67,7 @@ export class FrameExecutionContext extends js.ExecutionContext {
|
||||
try {
|
||||
result = await this._delegate.evaluate(this, returnByValue, pageFunction, ...adopted);
|
||||
} finally {
|
||||
await Promise.all(toDispose.map(handlePromise => handlePromise.then(handle => handle.dispose())));
|
||||
toDispose.map(handlePromise => handlePromise.then(handle => handle.dispose()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -105,7 +105,7 @@ export class FrameExecutionContext extends js.ExecutionContext {
|
||||
await this._injected(), selector, scope
|
||||
);
|
||||
if (!handle.asElement())
|
||||
await handle.dispose();
|
||||
handle.dispose();
|
||||
return handle.asElement() as ElementHandle<Element>;
|
||||
}
|
||||
|
||||
@ -120,14 +120,14 @@ export class FrameExecutionContext extends js.ExecutionContext {
|
||||
async _$$(selector: string, scope?: ElementHandle): Promise<ElementHandle<Element>[]> {
|
||||
const arrayHandle = await this._$array(selector, scope);
|
||||
const properties = await arrayHandle.getProperties();
|
||||
await arrayHandle.dispose();
|
||||
arrayHandle.dispose();
|
||||
const result: ElementHandle<Element>[] = [];
|
||||
for (const property of properties.values()) {
|
||||
const elementHandle = property.asElement() as ElementHandle<Element>;
|
||||
if (elementHandle)
|
||||
result.push(elementHandle);
|
||||
else
|
||||
await property.dispose();
|
||||
property.dispose();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -378,14 +378,14 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
|
||||
if (!elementHandle)
|
||||
throw new Error(`Error: failed to find element matching selector "${selector}"`);
|
||||
const result = await elementHandle.evaluate(pageFunction, ...args as any);
|
||||
await elementHandle.dispose();
|
||||
elementHandle.dispose();
|
||||
return result;
|
||||
}
|
||||
|
||||
$$eval: types.$$Eval = async (selector, pageFunction, ...args) => {
|
||||
const arrayHandle = await this._context._$array(selector, this);
|
||||
const result = await arrayHandle.evaluate(pageFunction, ...args as any);
|
||||
await arrayHandle.dispose();
|
||||
arrayHandle.dispose();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {helper, debugError} from '../helper';
|
||||
import { helper } from '../helper';
|
||||
import * as js from '../javascript';
|
||||
import { FFSession } from './ffConnection';
|
||||
import { Protocol } from './protocol';
|
||||
@ -122,11 +122,7 @@ export class FFExecutionContext implements js.ExecutionContextDelegate {
|
||||
await this._session.send('Runtime.disposeObject', {
|
||||
executionContextId: this._executionContextId,
|
||||
objectId: handle._remoteObject.objectId,
|
||||
}).catch(error => {
|
||||
// Exceptions might happen in case of a page been navigated or closed.
|
||||
// Swallow these since they are harmless and we don't leak anything in this case.
|
||||
debugError(error);
|
||||
});
|
||||
}).catch(error => {});
|
||||
}
|
||||
|
||||
async handleJSONValue<T>(handle: js.JSHandle<T>): Promise<T> {
|
||||
|
@ -447,7 +447,7 @@ export class FFPage implements PageDelegate {
|
||||
return { handle, frame };
|
||||
}));
|
||||
const result = items.find(item => item.frame === frame);
|
||||
await Promise.all(items.map(item => item === result ? Promise.resolve() : item.handle.dispose()));
|
||||
items.map(item => item === result ? Promise.resolve() : item.handle.dispose());
|
||||
if (!result)
|
||||
throw new Error('Frame has been detached.');
|
||||
return result.handle;
|
||||
|
@ -549,7 +549,7 @@ export class Frame {
|
||||
const handle = await utilityContext._$(selector);
|
||||
if (handle && handle._context !== mainContext) {
|
||||
const adopted = this._page._delegate.adoptElementHandle(handle, mainContext);
|
||||
await handle.dispose();
|
||||
handle.dispose();
|
||||
return adopted;
|
||||
}
|
||||
return handle;
|
||||
@ -561,7 +561,7 @@ export class Frame {
|
||||
const mainContext = await this._mainContext();
|
||||
if (handle && handle._context !== mainContext) {
|
||||
const adopted = this._page._delegate.adoptElementHandle(handle, mainContext);
|
||||
await handle.dispose();
|
||||
handle.dispose();
|
||||
return adopted;
|
||||
}
|
||||
return handle;
|
||||
@ -577,7 +577,7 @@ export class Frame {
|
||||
if (!elementHandle)
|
||||
throw new Error(`Error: failed to find element matching selector "${selector}"`);
|
||||
const result = await elementHandle.evaluate(pageFunction, ...args as any);
|
||||
await elementHandle.dispose();
|
||||
elementHandle.dispose();
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -585,7 +585,7 @@ export class Frame {
|
||||
const context = await this._mainContext();
|
||||
const arrayHandle = await context._$array(selector);
|
||||
const result = await arrayHandle.evaluate(pageFunction, ...args as any);
|
||||
await arrayHandle.dispose();
|
||||
arrayHandle.dispose();
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -782,63 +782,63 @@ export class Frame {
|
||||
async click(selector: string, options?: dom.ClickOptions & types.WaitForOptions) {
|
||||
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
|
||||
await handle.click(options);
|
||||
await handle.dispose();
|
||||
handle.dispose();
|
||||
}
|
||||
|
||||
async dblclick(selector: string, options?: dom.MultiClickOptions & types.WaitForOptions) {
|
||||
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
|
||||
await handle.dblclick(options);
|
||||
await handle.dispose();
|
||||
handle.dispose();
|
||||
}
|
||||
|
||||
async tripleclick(selector: string, options?: dom.MultiClickOptions & types.WaitForOptions) {
|
||||
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
|
||||
await handle.tripleclick(options);
|
||||
await handle.dispose();
|
||||
handle.dispose();
|
||||
}
|
||||
|
||||
async fill(selector: string, value: string, options?: types.WaitForOptions) {
|
||||
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
|
||||
await handle.fill(value);
|
||||
await handle.dispose();
|
||||
handle.dispose();
|
||||
}
|
||||
|
||||
async focus(selector: string, options?: types.WaitForOptions) {
|
||||
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
|
||||
await handle.focus();
|
||||
await handle.dispose();
|
||||
handle.dispose();
|
||||
}
|
||||
|
||||
async hover(selector: string, options?: dom.PointerActionOptions & types.WaitForOptions) {
|
||||
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
|
||||
await handle.hover(options);
|
||||
await handle.dispose();
|
||||
handle.dispose();
|
||||
}
|
||||
|
||||
async select(selector: string, value: string | dom.ElementHandle | types.SelectOption | string[] | dom.ElementHandle[] | types.SelectOption[], options?: types.WaitForOptions): Promise<string[]> {
|
||||
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
|
||||
const values = Array.isArray(value) ? value : [value];
|
||||
const result = await handle.select(...values);
|
||||
await handle.dispose();
|
||||
handle.dispose();
|
||||
return result;
|
||||
}
|
||||
|
||||
async type(selector: string, text: string, options?: { delay?: number } & types.WaitForOptions) {
|
||||
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
|
||||
await handle.type(text, options);
|
||||
await handle.dispose();
|
||||
handle.dispose();
|
||||
}
|
||||
|
||||
async check(selector: string, options?: types.WaitForOptions) {
|
||||
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
|
||||
await handle.check(options);
|
||||
await handle.dispose();
|
||||
handle.dispose();
|
||||
}
|
||||
|
||||
async uncheck(selector: string, options?: types.WaitForOptions) {
|
||||
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
|
||||
await handle.uncheck(options);
|
||||
await handle.dispose();
|
||||
handle.dispose();
|
||||
}
|
||||
|
||||
async waitFor(selectorOrFunctionOrTimeout: (string | number | Function), options: types.WaitForFunctionOptions & { visibility?: types.Visibility } = {}, ...args: any[]): Promise<js.JSHandle | null> {
|
||||
@ -879,7 +879,7 @@ export class Frame {
|
||||
const task = dom.waitForSelectorTask(selector, visibility, timeout);
|
||||
const result = await this._scheduleRerunnableTask(task, 'utility', timeout, `selector "${selectorToString(selector, visibility)}"`);
|
||||
if (!result.asElement()) {
|
||||
await result.dispose();
|
||||
result.dispose();
|
||||
return null;
|
||||
}
|
||||
return result.asElement() as dom.ElementHandle<Element>;
|
||||
@ -993,7 +993,7 @@ class RerunnableTask {
|
||||
|
||||
if (this._terminated || runCount !== this._runCount) {
|
||||
if (success)
|
||||
await success.dispose();
|
||||
success.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1001,7 +1001,7 @@ class RerunnableTask {
|
||||
// If execution context has been already destroyed, `context.evaluate` will
|
||||
// throw an error - ignore this predicate run altogether.
|
||||
if (!error && await context.evaluate(s => !s, success).catch(e => true)) {
|
||||
await success!.dispose();
|
||||
success!.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ export class JSHandle<T = any> {
|
||||
}, propertyName);
|
||||
const properties = await objectHandle.getProperties();
|
||||
const result = properties.get(propertyName) || null;
|
||||
await objectHandle.dispose();
|
||||
objectHandle.dispose();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -187,7 +187,7 @@ export class Page extends platform.EventEmitter {
|
||||
async _onFileChooserOpened(handle: dom.ElementHandle) {
|
||||
const multiple = await handle.evaluate(element => !!(element as HTMLInputElement).multiple);
|
||||
if (!this.listenerCount(Events.Page.FileChooser)) {
|
||||
await handle.dispose();
|
||||
handle.dispose();
|
||||
return;
|
||||
}
|
||||
const fileChooser: FileChooser = { element: handle, multiple };
|
||||
|
@ -630,7 +630,7 @@ export class WKPage implements PageDelegate {
|
||||
return { handle, frame };
|
||||
}));
|
||||
const result = items.find(item => item.frame === frame);
|
||||
await Promise.all(items.map(item => item === result ? Promise.resolve() : item.handle.dispose()));
|
||||
items.map(item => item === result ? Promise.resolve() : item.handle.dispose());
|
||||
if (!result)
|
||||
throw new Error('Frame has been detached.');
|
||||
return result.handle;
|
||||
|
@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { assert, debugError } from '../helper';
|
||||
import { assert } from '../helper';
|
||||
import { WKSession } from './wkConnection';
|
||||
import { Protocol } from './protocol';
|
||||
|
||||
@ -46,10 +46,6 @@ export function valueFromRemoteObject(remoteObject: Protocol.Runtime.RemoteObjec
|
||||
export async function releaseObject(client: WKSession, remoteObject: Protocol.Runtime.RemoteObject) {
|
||||
if (!remoteObject.objectId)
|
||||
return;
|
||||
await client.send('Runtime.releaseObject', {objectId: remoteObject.objectId}).catch(error => {
|
||||
// Exceptions might happen in case of a page been navigated or closed.
|
||||
// Swallow these since they are harmless and we don't leak anything in this case.
|
||||
debugError(error);
|
||||
});
|
||||
await client.send('Runtime.releaseObject', {objectId: remoteObject.objectId}).catch(error => {});
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user