Skip to content

Commit 0fbc7af

Browse files
authored
chore(targets): create page targets only when attached to them (#1278)
1 parent e650628 commit 0fbc7af

File tree

2 files changed

+46
-39
lines changed

2 files changed

+46
-39
lines changed

src/chromium/crBrowser.ts

+33-20
Original file line numberDiff line numberDiff line change
@@ -102,21 +102,19 @@ export class CRBrowser extends platform.EventEmitter implements Browser {
102102
return createPageInNewContext(this, options);
103103
}
104104

105-
async _onAttachedToTarget(event: Protocol.Target.attachedToTargetPayload) {
106-
if (!CRTarget.isPageType(event.targetInfo.type))
105+
async _onAttachedToTarget({targetInfo, sessionId, waitingForDebugger}: Protocol.Target.attachedToTargetPayload) {
106+
const session = this._connection.session(sessionId)!;
107+
if (!CRTarget.isPageType(targetInfo.type)) {
108+
assert(targetInfo.type === 'service_worker' || targetInfo.type === 'browser' || targetInfo.type === 'other');
109+
if (waitingForDebugger) {
110+
// Ideally, detaching should resume any target, but there is a bug in the backend.
111+
session.send('Runtime.runIfWaitingForDebugger').catch(debugError).then(() => {
112+
this._session.send('Target.detachFromTarget', { sessionId }).catch(debugError);
113+
});
114+
}
107115
return;
108-
const target = this._targets.get(event.targetInfo.targetId);
109-
const session = this._connection.session(event.sessionId)!;
110-
await target!.initializePageSession(session).catch(debugError);
111-
}
112-
113-
async _targetCreated({targetInfo}: Protocol.Target.targetCreatedPayload) {
114-
const {browserContextId} = targetInfo;
115-
const context = (browserContextId && this._contexts.has(browserContextId)) ? this._contexts.get(browserContextId)! : this._defaultContext;
116-
const target = new CRTarget(this, targetInfo, context, () => this._connection.createSession(targetInfo));
117-
assert(!this._targets.has(targetInfo.targetId), 'Target should not exist before targetCreated');
118-
this._targets.set(targetInfo.targetId, target);
119-
116+
}
117+
const { context, target } = this._createTarget(targetInfo, session);
120118
try {
121119
switch (targetInfo.type) {
122120
case 'page': {
@@ -135,27 +133,42 @@ export class CRBrowser extends platform.EventEmitter implements Browser {
135133
context.emit(Events.CRBrowserContext.BackgroundPage, event);
136134
break;
137135
}
138-
case 'service_worker': {
139-
const serviceWorker = await target.serviceWorker();
140-
context.emit(Events.CRBrowserContext.ServiceWorker, serviceWorker);
141-
break;
142-
}
143136
}
144137
} catch (e) {
145138
// Do not dispatch the event if initialization failed.
146139
debugError(e);
147140
}
148141
}
149142

143+
async _targetCreated({targetInfo}: Protocol.Target.targetCreatedPayload) {
144+
if (targetInfo.type !== 'service_worker')
145+
return;
146+
const { context, target } = this._createTarget(targetInfo, null);
147+
const serviceWorker = await target.serviceWorker();
148+
context.emit(Events.CRBrowserContext.ServiceWorker, serviceWorker);
149+
}
150+
151+
private _createTarget(targetInfo: Protocol.Target.TargetInfo, session: CRSession | null) {
152+
const {browserContextId} = targetInfo;
153+
const context = (browserContextId && this._contexts.has(browserContextId)) ? this._contexts.get(browserContextId)! : this._defaultContext;
154+
const target = new CRTarget(this, targetInfo, context, session, () => this._connection.createSession(targetInfo));
155+
assert(!this._targets.has(targetInfo.targetId), 'Target should not exist before targetCreated');
156+
this._targets.set(targetInfo.targetId, target);
157+
return { context, target };
158+
}
159+
150160
async _targetDestroyed(event: { targetId: string; }) {
151161
const target = this._targets.get(event.targetId)!;
162+
if (!target)
163+
return;
152164
this._targets.delete(event.targetId);
153165
target._didClose();
154166
}
155167

156168
_targetInfoChanged(event: Protocol.Target.targetInfoChangedPayload) {
157169
const target = this._targets.get(event.targetInfo.targetId)!;
158-
assert(target, 'target should exist before targetInfoChanged');
170+
if (!target)
171+
return;
159172
target._targetInfoChanged(event.targetInfo);
160173
}
161174

src/chromium/crTarget.ts

+13-19
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { CRBrowser, CRBrowserContext } from './crBrowser';
1919
import { CRSession, CRSessionEvents } from './crConnection';
2020
import { Page, Worker } from '../page';
2121
import { Protocol } from './protocol';
22-
import { debugError } from '../helper';
22+
import { debugError, assert } from '../helper';
2323
import { CRPage } from './crPage';
2424
import { CRExecutionContext } from './crExecutionContext';
2525

@@ -48,38 +48,32 @@ export class CRTarget {
4848
browser: CRBrowser,
4949
targetInfo: Protocol.Target.TargetInfo,
5050
browserContext: CRBrowserContext,
51+
session: CRSession | null,
5152
sessionFactory: () => Promise<CRSession>) {
5253
this._targetInfo = targetInfo;
5354
this._browser = browser;
5455
this._browserContext = browserContext;
5556
this._targetId = targetInfo.targetId;
5657
this.sessionFactory = sessionFactory;
57-
if (CRTarget.isPageType(targetInfo.type))
58-
this._pagePromise = new Promise<Page | Error>(f => this._pagePromiseCallback = f);
58+
if (CRTarget.isPageType(targetInfo.type)) {
59+
assert(session, 'Page target must be created with existing session');
60+
this._crPage = new CRPage(session, this._browser, this._browserContext);
61+
const page = this._crPage.page();
62+
(page as any)[targetSymbol] = this;
63+
session.once(CRSessionEvents.Disconnected, () => page._didDisconnect());
64+
this._pagePromise = this._crPage.initialize().then(() => page).catch(e => e);
65+
}
5966
}
6067

6168
_didClose() {
6269
if (this._crPage)
6370
this._crPage.didClose();
6471
}
6572

66-
async initializePageSession(session: CRSession) {
67-
this._crPage = new CRPage(session, this._browser, this._browserContext);
68-
const page = this._crPage.page();
69-
(page as any)[targetSymbol] = this;
70-
session.once(CRSessionEvents.Disconnected, () => page._didDisconnect());
71-
try {
72-
await this._crPage.initialize();
73-
this._pagePromiseCallback!(page);
74-
} catch (e) {
75-
this._pagePromiseCallback!(e);
76-
}
77-
}
78-
7973
async pageOrError(): Promise<Page | Error> {
80-
if (this._targetInfo.type !== 'page' && this._targetInfo.type !== 'background_page')
81-
throw new Error('Not a page.');
82-
return this._pagePromise!;
74+
if (CRTarget.isPageType(this.type()))
75+
return this._pagePromise!;
76+
throw new Error('Not a page.');
8377
}
8478

8579
async serviceWorker(): Promise<Worker | null> {

0 commit comments

Comments
 (0)