Skip to content

Commit e79584f

Browse files
committed
fix(puppet): non-popups getting opener
1 parent 3b452d8 commit e79584f

File tree

11 files changed

+42
-41
lines changed

11 files changed

+42
-41
lines changed

core/test/navigation.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ describe('PaintingStable tests', () => {
440440
koaServer.get('/grid/:filename', async ctx => {
441441
const filename = ctx.params.filename;
442442
if (filename === 'data.json') {
443+
await new Promise(resolve => setTimeout(resolve, 100));
443444
const records = [];
444445
for (let i = 0; i < 200; i += 1) {
445446
records.push(

puppet-chrome/lib/Browser.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ export class Browser extends TypedEventEmitter<IBrowserEvents> implements IPuppe
7777
private onAttachedToTarget(event: Protocol.Target.AttachedToTargetEvent) {
7878
const { targetInfo, sessionId } = event;
7979

80-
assert(targetInfo.browserContextId, `targetInfo: ${JSON.stringify(targetInfo, null, 2)}`);
80+
if (!targetInfo.browserContextId) {
81+
assert(targetInfo.browserContextId, `targetInfo: ${JSON.stringify(targetInfo, null, 2)}`);
82+
}
8183

8284
if (targetInfo.type === 'page') {
8385
const cdpSession = this.connection.getSession(sessionId);

puppet-chrome/lib/BrowserContext.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { IBoundLog } from '@secret-agent/core-interfaces/ILog';
1515
import { ProtocolMapping } from 'devtools-protocol/types/protocol-mapping';
1616
import IRegisteredEventListener from '@secret-agent/core-interfaces/IRegisteredEventListener';
1717
import { CanceledPromiseError } from '@secret-agent/commons/interfaces/IPendingWaitEvent';
18+
import { IPuppetPage } from '@secret-agent/puppet-interfaces/IPuppetPage';
1819
import { Page } from './Page';
1920
import { Browser } from './Browser';
2021
import { CDPSession } from './CDPSession';
@@ -41,6 +42,7 @@ export class BrowserContext
4142

4243
private _emulation: IBrowserEmulationSettings;
4344

45+
private readonly createdTargetIds = new Set<string>();
4446
private readonly pages: Page[] = [];
4547
private readonly browser: Browser;
4648
private readonly id: string;
@@ -76,6 +78,7 @@ export class BrowserContext
7678
url: 'about:blank',
7779
browserContextId: this.id,
7880
});
81+
this.createdTargetIds.add(targetId);
7982

8083
await this.attachToTarget(targetId);
8184

@@ -111,7 +114,7 @@ export class BrowserContext
111114

112115
let opener = targetInfo.openerId ? this.getPageWithId(targetInfo.openerId) || null : null;
113116
// make the first page the active page
114-
if (!opener && this.pages.length) opener = this.pages[0];
117+
if (!opener && !this.createdTargetIds.has(targetInfo.targetId)) opener = this.pages[0];
115118
const page = new Page(cdpSession, targetInfo.targetId, this, this.logger, opener);
116119
this.pages.push(page);
117120
// eslint-disable-next-line promise/catch-or-return

puppet-chrome/lib/CDPSession.ts

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@
1818
import { ProtocolMapping } from 'devtools-protocol/types/protocol-mapping';
1919
import { Protocol } from 'devtools-protocol';
2020
import { EventEmitter } from 'events';
21-
import { IConnectionCallback } from '@secret-agent/puppet-interfaces/IConnectionCallback';
2221
import { CanceledPromiseError } from '@secret-agent/commons/interfaces/IPendingWaitEvent';
2322
import { TypedEventEmitter } from '@secret-agent/commons/eventUtils';
23+
import IResolvablePromise from '@secret-agent/core-interfaces/IResolvablePromise';
24+
import { createPromise } from '@secret-agent/commons/utils';
2425
import ProtocolError from './ProtocolError';
2526
import { Connection } from './Connection';
2627
import RemoteObject = Protocol.Runtime.RemoteObject;
@@ -39,7 +40,10 @@ export class CDPSession extends EventEmitter {
3940

4041
private readonly sessionId: string;
4142
private readonly targetType: string;
42-
private readonly pendingMessages: Map<number, IConnectionCallback> = new Map();
43+
private readonly pendingMessages: Map<
44+
number,
45+
{ resolvable: IResolvablePromise<any>; method: string }
46+
> = new Map();
4347

4448
constructor(connection: Connection, targetType: string, sessionId: string) {
4549
super();
@@ -54,7 +58,7 @@ export class CDPSession extends EventEmitter {
5458
sendInitiator?: object,
5559
): Promise<ProtocolMapping.Commands[T]['returnType']> {
5660
if (!this.isConnected()) {
57-
throw new CanceledPromiseError(`Session closed before api call (${method})`);
61+
throw new CanceledPromiseError(`${method} called after session closed (${this.sessionId})`);
5862
}
5963

6064
const message = {
@@ -71,28 +75,29 @@ export class CDPSession extends EventEmitter {
7175
},
7276
sendInitiator,
7377
);
78+
const resolvable = createPromise<ProtocolMapping.Commands[T]['returnType']>();
7479

75-
return await new Promise((resolve, reject) => {
76-
this.pendingMessages.set(id, { resolve, reject, error: new CanceledPromiseError(), method });
77-
});
80+
this.pendingMessages.set(id, { resolvable, method });
81+
return await resolvable.promise;
7882
}
7983

8084
onMessage(object: ICDPSendResponseMessage & ICDPEventMessage): void {
8185
this.messageEvents.emit('receive', { ...object });
8286
if (!object.id) {
83-
setImmediate(() => this.emit(object.method, object.params));
87+
this.emit(object.method, object.params);
8488
return;
8589
}
8690

87-
const callback = this.pendingMessages.get(object.id);
88-
if (!callback) return;
91+
const pending = this.pendingMessages.get(object.id);
92+
if (!pending) return;
93+
94+
const { resolvable, method } = pending;
8995

9096
this.pendingMessages.delete(object.id);
9197
if (object.error) {
92-
const protocolError = new ProtocolError(callback.error.stack, callback.method, object.error);
93-
setImmediate(() => callback.reject(protocolError));
98+
resolvable.reject(new ProtocolError(resolvable.stack, method, object.error));
9499
} else {
95-
setImmediate(() => callback.resolve(object.result));
100+
resolvable.resolve(object.result);
96101
}
97102
}
98103

@@ -105,10 +110,13 @@ export class CDPSession extends EventEmitter {
105110
}
106111

107112
onClosed(): void {
108-
for (const callback of this.pendingMessages.values()) {
109-
const error = callback.error;
110-
error.message = `Cancel Pending Promise (${callback.method}): Target closed.`;
111-
callback.reject(error);
113+
for (const { resolvable, method } of this.pendingMessages.values()) {
114+
const error = new CanceledPromiseError(`Cancel Pending Promise (${method}): Target closed.`);
115+
error.stack += `\n${'------DEVTOOLS'.padEnd(
116+
50,
117+
'-',
118+
)}\n${`------DEVTOOLS-SESSION-ID =${this.sessionId}`.padEnd(50, '-')}\n${resolvable.stack}`;
119+
resolvable.reject(error);
112120
}
113121
this.pendingMessages.clear();
114122
this.connection = null;

puppet-chrome/lib/Connection.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,13 @@ import {
2222
import IConnectionTransport, {
2323
IConnectionTransportEvents,
2424
} from '@secret-agent/puppet-interfaces/IConnectionTransport';
25-
import { IPuppetConnectionEvents } from '@secret-agent/puppet-interfaces/IPuppetConnection';
2625
import IRegisteredEventListener from '@secret-agent/core-interfaces/IRegisteredEventListener';
2726
import Log from '@secret-agent/commons/Logger';
2827
import { CDPSession } from './CDPSession';
2928

3029
const { log } = Log(module);
3130

32-
export class Connection extends TypedEventEmitter<IPuppetConnectionEvents> {
31+
export class Connection extends TypedEventEmitter<{ disconnected: void }> {
3332
public readonly rootSession: CDPSession;
3433
public isClosed = false;
3534

@@ -85,7 +84,6 @@ export class Connection extends TypedEventEmitter<IPuppetConnectionEvents> {
8584

8685
const cdpSession = this.sessionsById.get(object.sessionId || '');
8786
if (cdpSession) {
88-
// make asynchronous so we don't have accidental bugs where things are behaving synchronous until stack backs up
8987
cdpSession.onMessage(object);
9088
} else {
9189
log.warn('MessageWithUnknownSession', { sessionId: null, message: object });

puppet-interfaces/IConnectionCallback.ts

Lines changed: 0 additions & 6 deletions
This file was deleted.

puppet-interfaces/IPuppetConnection.ts

Lines changed: 0 additions & 7 deletions
This file was deleted.

puppet-interfaces/IPuppetEngine.ts

Lines changed: 0 additions & 4 deletions
This file was deleted.

puppet-interfaces/IPuppetWorker.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export interface IPuppetWorker extends ITypedEventEmitter<IPuppetWorkerEvents> {
44
id: string;
55
url: string;
66
type: string;
7+
isReady: Promise<Error | null>;
78
evaluate<T>(expression: string): Promise<T>;
89
}
910

puppet/lib/PipeTransport.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export class PipeTransport
4444
log.error('PipeTransport.WriteError', { error, sessionId: null }),
4545
),
4646
);
47+
this.emit = this.emit.bind(this);
4748
}
4849

4950
send(message: string) {
@@ -68,15 +69,19 @@ export class PipeTransport
6869
return;
6970
}
7071
const message = this.pendingMessage + buffer.toString(undefined, 0, end);
71-
this.emit('message', message);
72+
this.emitMessage(message);
7273

7374
let start = end + 1;
7475
end = buffer.indexOf('\0', start);
7576
while (end !== -1) {
76-
this.emit('message', buffer.toString(undefined, start, end));
77+
this.emitMessage(buffer.toString(undefined, start, end));
7778
start = end + 1;
7879
end = buffer.indexOf('\0', start);
7980
}
8081
this.pendingMessage = buffer.toString(undefined, start);
8182
}
83+
84+
private emitMessage(message: string): void {
85+
setImmediate(this.emit, 'message', message);
86+
}
8287
}

0 commit comments

Comments
 (0)