chore: implement moveable (#10803)

This commit is contained in:
jrandolf 2023-08-29 22:48:37 +02:00 committed by GitHub
parent 8c07631bd1
commit 2401bb46b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 212 additions and 53 deletions

View File

@ -106,6 +106,7 @@ sidebar_label: API
| [MouseMoveOptions](./puppeteer.mousemoveoptions.md) | | | [MouseMoveOptions](./puppeteer.mousemoveoptions.md) | |
| [MouseOptions](./puppeteer.mouseoptions.md) | | | [MouseOptions](./puppeteer.mouseoptions.md) | |
| [MouseWheelOptions](./puppeteer.mousewheeloptions.md) | | | [MouseWheelOptions](./puppeteer.mousewheeloptions.md) | |
| [Moveable](./puppeteer.moveable.md) | |
| [NetworkConditions](./puppeteer.networkconditions.md) | | | [NetworkConditions](./puppeteer.networkconditions.md) | |
| [NewDocumentScriptEvaluation](./puppeteer.newdocumentscriptevaluation.md) | | | [NewDocumentScriptEvaluation](./puppeteer.newdocumentscriptevaluation.md) | |
| [Offset](./puppeteer.offset.md) | | | [Offset](./puppeteer.offset.md) | |

View File

@ -1,17 +0,0 @@
---
sidebar_label: ElementHandle.[Symbol.asyncDispose]
---
# ElementHandle.\[Symbol.asyncDispose\]() method
#### Signature:
```typescript
class ElementHandle {
[Symbol.asyncDispose](): Promise<void>;
}
```
**Returns:**
Promise&lt;void&gt;

View File

@ -1,17 +0,0 @@
---
sidebar_label: ElementHandle.[Symbol.dispose]
---
# ElementHandle.\[Symbol.dispose\]() method
#### Signature:
```typescript
class ElementHandle {
[Symbol.dispose](): void;
}
```
**Returns:**
void

View File

@ -49,8 +49,6 @@ The constructor for this class is marked as internal. Third-party code should no
| Method | Modifiers | Description | | Method | Modifiers | Description |
| -------------------------------------------------------------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | -------------------------------------------------------------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [\[Symbol.asyncDispose\]()](./puppeteer.elementhandle._symbol.asyncdispose_.md) | | |
| [\[Symbol.dispose\]()](./puppeteer.elementhandle._symbol.dispose_.md) | | |
| [$(selector)](./puppeteer.elementhandle._.md) | | Queries the current element for an element matching the given selector. | | [$(selector)](./puppeteer.elementhandle._.md) | | Queries the current element for an element matching the given selector. |
| [$$(selector)](./puppeteer.elementhandle.__.md) | | Queries the current element for all elements matching the given selector. | | [$$(selector)](./puppeteer.elementhandle.__.md) | | Queries the current element for all elements matching the given selector. |
| [$$eval(selector, pageFunction, args)](./puppeteer.elementhandle.__eval.md) | | <p>Runs the given function on an array of elements matching the given selector in the current element.</p><p>If the given function returns a promise, then this method will wait till the promise resolves.</p> | | [$$eval(selector, pageFunction, args)](./puppeteer.elementhandle.__eval.md) | | <p>Runs the given function on an array of elements matching the given selector in the current element.</p><p>If the given function returns a promise, then this method will wait till the promise resolves.</p> |

View File

@ -13,10 +13,10 @@ Handles can be used as arguments for any evaluation function such as [Page.$eval
#### Signature: #### Signature:
```typescript ```typescript
export declare abstract class JSHandle<T = unknown> implements Disposable, AsyncDisposable export declare abstract class JSHandle<T = unknown> implements Disposable, AsyncDisposable, Moveable
``` ```
**Implements:** Disposable, AsyncDisposable **Implements:** Disposable, AsyncDisposable, [Moveable](./puppeteer.moveable.md)
## Remarks ## Remarks
@ -30,9 +30,10 @@ const windowHandle = await page.evaluateHandle(() => window);
## Properties ## Properties
| Property | Modifiers | Type | Description | | Property | Modifiers | Type | Description |
| -------- | --------------------- | ---- | -------------------------------------------------------------- | | -------- | --------------------- | ------------- | -------------------------------------------------------------- |
| \_ | <code>optional</code> | T | Used for nominally typing [JSHandle](./puppeteer.jshandle.md). | | \_ | <code>optional</code> | T | Used for nominally typing [JSHandle](./puppeteer.jshandle.md). |
| move | | () =&gt; this | |
## Methods ## Methods

View File

@ -0,0 +1,17 @@
---
sidebar_label: Moveable
---
# Moveable interface
#### Signature:
```typescript
export interface Moveable
```
## Methods
| Method | Description |
| -------------------------------------- | -------------------------------- |
| [move()](./puppeteer.moveable.move.md) | Moves the resource when 'using'. |

View File

@ -0,0 +1,19 @@
---
sidebar_label: Moveable.move
---
# Moveable.move() method
Moves the resource when 'using'.
#### Signature:
```typescript
interface Moveable {
move(): this;
}
```
**Returns:**
this

View File

@ -140,7 +140,6 @@ export interface Point {
* *
* @public * @public
*/ */
export abstract class ElementHandle< export abstract class ElementHandle<
ElementType extends Node = Element, ElementType extends Node = Element,
> extends JSHandle<ElementType> { > extends JSHandle<ElementType> {
@ -1323,14 +1322,6 @@ export abstract class ElementHandle<
* ``` * ```
*/ */
abstract autofill(data: AutofillData): Promise<void>; abstract autofill(data: AutofillData): Promise<void>;
override [Symbol.dispose](): void {
return void this.dispose().catch(debugError);
}
override [Symbol.asyncDispose](): Promise<void> {
return this.dispose();
}
} }
/** /**

View File

@ -17,8 +17,14 @@
import Protocol from 'devtools-protocol'; import Protocol from 'devtools-protocol';
import {Symbol} from '../../third_party/disposablestack/disposablestack.js'; import {Symbol} from '../../third_party/disposablestack/disposablestack.js';
import {EvaluateFuncWith, HandleFor, HandleOr} from '../common/types.js'; import {
EvaluateFuncWith,
HandleFor,
HandleOr,
Moveable,
} from '../common/types.js';
import {debugError} from '../common/util.js'; import {debugError} from '../common/util.js';
import {moveable} from '../util/decorators.js';
import {ElementHandle} from './ElementHandle.js'; import {ElementHandle} from './ElementHandle.js';
@ -43,9 +49,12 @@ import {ElementHandle} from './ElementHandle.js';
* *
* @public * @public
*/ */
@moveable
export abstract class JSHandle<T = unknown> export abstract class JSHandle<T = unknown>
implements Disposable, AsyncDisposable implements Disposable, AsyncDisposable, Moveable
{ {
declare move: () => this;
/** /**
* Used for nominally typing {@link JSHandle}. * Used for nominally typing {@link JSHandle}.
*/ */

View File

@ -19,6 +19,16 @@ import type {JSHandle} from '../api/JSHandle.js';
import type {LazyArg} from './LazyArg.js'; import type {LazyArg} from './LazyArg.js';
/**
* @public
*/
export interface Moveable {
/**
* Moves the resource when 'using'.
*/
move(): this;
}
/** /**
* @internal * @internal
*/ */

View File

@ -0,0 +1,59 @@
/**
* Copyright 2023 Google 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 {Symbol} from '../../third_party/disposablestack/disposablestack.js';
import {Moveable} from '../common/types.js';
const instances = new WeakSet<object>();
export function moveable<
Class extends abstract new (...args: never[]) => Moveable,
>(Class: Class, _: ClassDecoratorContext<Class>): Class {
let hasDispose = false;
if (Class.prototype[Symbol.dispose]) {
const dispose = Class.prototype[Symbol.dispose];
Class.prototype[Symbol.dispose] = function (this: InstanceType<Class>) {
if (instances.has(this)) {
instances.delete(this);
return;
}
return dispose.call(this);
};
hasDispose = true;
}
if (Class.prototype[Symbol.asyncDispose]) {
const asyncDispose = Class.prototype[Symbol.asyncDispose];
Class.prototype[Symbol.asyncDispose] = function (
this: InstanceType<Class>
) {
if (instances.has(this)) {
instances.delete(this);
return;
}
return asyncDispose.call(this);
};
hasDispose = true;
}
if (hasDispose) {
Class.prototype.move = function (
this: InstanceType<Class>
): InstanceType<Class> {
instances.add(this);
return this;
};
}
return Class;
}

View File

@ -904,7 +904,7 @@ describe('ElementHandle specs', function () {
}); });
}); });
describe('Element.toElement', () => { describe('ElementHandle.toElement', () => {
it('should work', async () => { it('should work', async () => {
const {page} = await getTestState(); const {page} = await getTestState();
await page.setContent('<div class="foo">Foo1</div>'); await page.setContent('<div class="foo">Foo1</div>');
@ -913,4 +913,47 @@ describe('ElementHandle specs', function () {
expect(div).toBeDefined(); expect(div).toBeDefined();
}); });
}); });
describe('ElementHandle[Symbol.dispose]', () => {
it('should work', async () => {
const {page} = await getTestState();
const handle = await page.evaluateHandle('document');
const spy = sinon.spy(handle, Symbol.dispose);
{
using _ = handle;
}
expect(handle).toBeInstanceOf(ElementHandle);
expect(spy.calledOnce).toBeTruthy();
expect(handle.disposed).toBeTruthy();
});
});
describe('ElementHandle[Symbol.asyncDispose]', () => {
it('should work', async () => {
const {page} = await getTestState();
const handle = await page.evaluateHandle('document');
const spy = sinon.spy(handle, Symbol.asyncDispose);
{
await using _ = handle;
}
expect(handle).toBeInstanceOf(ElementHandle);
expect(spy.calledOnce).toBeTruthy();
expect(handle.disposed).toBeTruthy();
});
});
describe('ElementHandle.move', () => {
it('should work', async () => {
const {page} = await getTestState();
const handle = await page.evaluateHandle('document');
const spy = sinon.spy(handle, Symbol.dispose);
{
using _ = handle;
handle.move();
}
expect(handle).toBeInstanceOf(ElementHandle);
expect(spy.calledOnce).toBeTruthy();
expect(handle.disposed).toBeFalsy();
});
});
}); });

View File

@ -15,6 +15,8 @@
*/ */
import expect from 'expect'; import expect from 'expect';
import {JSHandle} from 'puppeteer-core/internal/api/JSHandle.js';
import sinon from 'sinon';
import {getTestState, setupTestBrowserHooks} from './mocha-utils.js'; import {getTestState, setupTestBrowserHooks} from './mocha-utils.js';
@ -331,4 +333,47 @@ describe('JSHandle', function () {
); );
}); });
}); });
describe('JSHandle[Symbol.dispose]', () => {
it('should work', async () => {
const {page} = await getTestState();
const handle = await page.evaluateHandle('new Set()');
const spy = sinon.spy(handle, Symbol.dispose);
{
using _ = handle;
}
expect(handle).toBeInstanceOf(JSHandle);
expect(spy.calledOnce).toBeTruthy();
expect(handle.disposed).toBeTruthy();
});
});
describe('JSHandle[Symbol.asyncDispose]', () => {
it('should work', async () => {
const {page} = await getTestState();
const handle = await page.evaluateHandle('new Set()');
const spy = sinon.spy(handle, Symbol.asyncDispose);
{
await using _ = handle;
}
expect(handle).toBeInstanceOf(JSHandle);
expect(spy.calledOnce).toBeTruthy();
expect(handle.disposed).toBeTruthy();
});
});
describe('JSHandle.move', () => {
it('should work', async () => {
const {page} = await getTestState();
const handle = await page.evaluateHandle('new Set()');
const spy = sinon.spy(handle, Symbol.dispose);
{
using _ = handle;
handle.move();
}
expect(handle).toBeInstanceOf(JSHandle);
expect(spy.calledOnce).toBeTruthy();
expect(handle.disposed).toBeFalsy();
});
});
}); });