feat(worker): expose worker's owner frame
This commit is contained in:
parent
a64fc0e45f
commit
5614c75751
|
|
@ -3248,6 +3248,7 @@ for (const worker of page.workers())
|
|||
<!-- GEN:toc -->
|
||||
- [worker.evaluate(pageFunction[, ...args])](#workerevaluatepagefunction-args)
|
||||
- [worker.evaluateHandle(pageFunction[, ...args])](#workerevaluatehandlepagefunction-args)
|
||||
- [worker.frame()](#workerframe)
|
||||
- [worker.url()](#workerurl)
|
||||
<!-- GEN:stop -->
|
||||
|
||||
|
|
@ -3269,6 +3270,9 @@ The only difference between `worker.evaluate` and `worker.evaluateHandle` is tha
|
|||
|
||||
If the function passed to the `worker.evaluateHandle` returns a [Promise], then `worker.evaluateHandle` would wait for the promise to resolve and return its value.
|
||||
|
||||
#### worker.frame()
|
||||
- returns: <[Frame]> Frame which has created this worker.
|
||||
|
||||
#### worker.url()
|
||||
- returns: <[string]>
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
"playwright": {
|
||||
"chromium_revision": "733125",
|
||||
"firefox_revision": "1018",
|
||||
"webkit_revision": "1113"
|
||||
"webkit_revision": "1118"
|
||||
},
|
||||
"scripts": {
|
||||
"unit": "node test/test.js",
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ export class CRPage implements PageDelegate {
|
|||
return;
|
||||
const url = event.targetInfo.url;
|
||||
const session = CRConnection.fromSession(this._client).session(event.sessionId)!;
|
||||
const worker = new Worker(url);
|
||||
const worker = new Worker(url, null as any);
|
||||
this._page._addWorker(event.sessionId, worker);
|
||||
session.once('Runtime.executionContextCreated', async event => {
|
||||
worker._createExecutionContext(new CRExecutionContext(session, event.context));
|
||||
|
|
|
|||
|
|
@ -104,7 +104,8 @@ export class CRTarget {
|
|||
if (!this._workerPromise) {
|
||||
// TODO(einbinder): Make workers send their console logs.
|
||||
this._workerPromise = this._sessionFactory().then(session => {
|
||||
const worker = new Worker(this._targetInfo.url);
|
||||
// TODO: we should not reuse Worker class (which is web worker) for service workers.
|
||||
const worker = new Worker(this._targetInfo.url, null as any);
|
||||
session.once('Runtime.executionContextCreated', async event => {
|
||||
worker._createExecutionContext(new CRExecutionContext(session, event.context));
|
||||
});
|
||||
|
|
@ -132,6 +133,8 @@ export class CRTarget {
|
|||
}
|
||||
|
||||
opener(): CRTarget | null {
|
||||
if (this._targetInfo.type === 'worker')
|
||||
return null;
|
||||
const { openerId } = this._targetInfo;
|
||||
if (!openerId)
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ export class FFPage implements PageDelegate {
|
|||
|
||||
async _onWorkerCreated(event: Protocol.Page.workerCreatedPayload) {
|
||||
const workerId = event.workerId;
|
||||
const worker = new Worker(event.url);
|
||||
const worker = new Worker(event.url, this._page._frameManager.frame(event.frameId)!);
|
||||
const workerSession = new FFSession(this._session._connection, 'worker', workerId, (message: any) => {
|
||||
this._session.send('Page.sendMessageToWorker', {
|
||||
frameId: event.frameId,
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ export class FrameManager {
|
|||
frame._lastDocumentId = documentId;
|
||||
this.clearFrameLifecycle(frame);
|
||||
this.clearWebSockets(frame);
|
||||
this._page._clearWorkers(frame);
|
||||
if (!initial) {
|
||||
for (const watcher of this._lifecycleWatchers)
|
||||
watcher._onCommittedNewDocumentNavigation(frame);
|
||||
|
|
|
|||
14
src/page.ts
14
src/page.ts
|
|
@ -519,22 +519,26 @@ export class Page extends platform.EventEmitter {
|
|||
this._workers.delete(workerId);
|
||||
}
|
||||
|
||||
_clearWorkers() {
|
||||
_clearWorkers(frame: frames.Frame) {
|
||||
for (const [workerId, worker] of this._workers) {
|
||||
this.emit(Events.Page.WorkerDestroyed, worker);
|
||||
if (worker.frame() !== frame)
|
||||
continue;
|
||||
this._workers.delete(workerId);
|
||||
this.emit(Events.Page.WorkerDestroyed, worker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class Worker {
|
||||
private _url: string;
|
||||
private _frame: frames.Frame;
|
||||
private _executionContextPromise: Promise<js.ExecutionContext>;
|
||||
private _executionContextCallback: (value?: js.ExecutionContext) => void;
|
||||
_existingExecutionContext: js.ExecutionContext | null = null;
|
||||
|
||||
constructor(url: string) {
|
||||
constructor(url: string, frame: frames.Frame) {
|
||||
this._url = url;
|
||||
this._frame = frame;
|
||||
this._executionContextCallback = () => {};
|
||||
this._executionContextPromise = new Promise(x => this._executionContextCallback = x);
|
||||
}
|
||||
|
|
@ -548,6 +552,10 @@ export class Worker {
|
|||
return this._url;
|
||||
}
|
||||
|
||||
frame(): frames.Frame {
|
||||
return this._frame;
|
||||
}
|
||||
|
||||
evaluate: types.Evaluate = async (pageFunction, ...args) => {
|
||||
return (await this._executionContextPromise).evaluate(pageFunction, ...args as any);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export class WKWorkers {
|
|||
this.clear();
|
||||
this._sessionListeners = [
|
||||
helper.addEventListener(session, 'Worker.workerCreated', async (event: Protocol.Worker.workerCreatedPayload) => {
|
||||
const worker = new Worker(event.url);
|
||||
const worker = new Worker(event.url, this._page._frameManager.frame(event.frameId));
|
||||
const workerSession = new WKSession(session.connection, event.workerId, 'Most likely the worker has been closed.', (message: any) => {
|
||||
session.send('Worker.sendMessageToWorker', {
|
||||
workerId: event.workerId,
|
||||
|
|
@ -77,7 +77,6 @@ export class WKWorkers {
|
|||
}
|
||||
|
||||
clear() {
|
||||
this._page._clearWorkers();
|
||||
this._workerSessions.clear();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,25 @@ module.exports.describe = function({testRunner, expect, FFOX, CHROMIUM, WEBKIT})
|
|||
expect(destroyed).toBe(true);
|
||||
expect(page.workers().length).toBe(0);
|
||||
});
|
||||
it.skip(CHROMIUM)('should clear upon frame navigation', async function({server, page}) {
|
||||
await page.goto(server.PREFIX + '/frames/one-frame.html');
|
||||
const workerCreatedPromise = page.waitForEvent('workercreated');
|
||||
const frame = page.mainFrame().childFrames()[0];
|
||||
frame.evaluate(() => new Worker(URL.createObjectURL(new Blob(['console.log(1)'], {type: 'application/javascript'}))));
|
||||
await workerCreatedPromise;
|
||||
expect(page.workers().length).toBe(1);
|
||||
expect(page.workers()[0].frame()).toBe(frame);
|
||||
let destroyed = false;
|
||||
page.once('workerdestroyed', () => destroyed = true);
|
||||
let navigated = false;
|
||||
page.once('framenavigated', () => {
|
||||
expect(destroyed).toBe(true);
|
||||
expect(page.workers().length).toBe(0);
|
||||
navigated = true;
|
||||
});
|
||||
await frame.goto(server.PREFIX + '/one-style.html');
|
||||
expect(navigated).toBe(true);
|
||||
});
|
||||
it('should clear upon cross-process navigation', async function({server, page}) {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const workerCreatedPromise = page.waitForEvent('workercreated');
|
||||
|
|
|
|||
Loading…
Reference in a new issue