Skip to content

Commit 12df65c

Browse files
committed
move codegen to isomorphic, generate code on the client side
1 parent 03efc77 commit 12df65c

33 files changed

+214
-228
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[*]
22
../protocol/
33
../utils/isomorphic
4+
../utils/isomorphic/codegen

packages/playwright-core/src/client/browserContext.ts

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import { headersObjectToArray } from '../utils/isomorphic/headers';
4040
import { urlMatchesEqual } from '../utils/isomorphic/urlMatch';
4141
import { isRegExp, isString } from '../utils/isomorphic/rtti';
4242
import { rewriteErrorMessage } from '../utils/isomorphic/stackTrace';
43+
import { generateCode, languageSet } from '../utils/isomorphic/codegen/codegen';
4344

4445
import type { BrowserContextOptions, Headers, SetStorageState, StorageState, WaitForEventOptions } from './types';
4546
import type * as structs from '../../types/structs';
@@ -78,7 +79,6 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
7879
_closingStatus: 'none' | 'closing' | 'closed' = 'none';
7980
private _closeReason: string | undefined;
8081
private _harRouters: HarRouter[] = [];
81-
private _onRecorderEventSink: RecorderEventSink | undefined;
8282

8383
static from(context: channels.BrowserContextChannel): BrowserContext {
8484
return (context as any)._object;
@@ -148,14 +148,6 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
148148
this._channel.on('requestFailed', ({ request, failureText, responseEndTiming, page }) => this._onRequestFailed(network.Request.from(request), responseEndTiming, failureText, Page.fromNullable(page)));
149149
this._channel.on('requestFinished', params => this._onRequestFinished(params));
150150
this._channel.on('response', ({ response, page }) => this._onResponse(network.Response.from(response), Page.fromNullable(page)));
151-
this._channel.on('recorderEvent', ({ event, data, page, code }) => {
152-
if (event === 'actionAdded')
153-
this._onRecorderEventSink?.actionAdded?.(Page.from(page), data as actions.ActionInContext, code);
154-
else if (event === 'actionUpdated')
155-
this._onRecorderEventSink?.actionUpdated?.(Page.from(page), data as actions.ActionInContext, code);
156-
else if (event === 'signalAdded')
157-
this._onRecorderEventSink?.signalAdded?.(Page.from(page), data as actions.SignalInContext);
158-
});
159151
this._closedPromise = new Promise(f => this.once(Events.BrowserContext.Close, f));
160152

161153
this._setEventToSubscriptionMapping(new Map<string, channels.BrowserContextUpdateSubscriptionParams['event']>([
@@ -520,13 +512,35 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
520512
}
521513

522514
async _enableRecorder(params: channels.BrowserContextEnableRecorderParams, eventSink?: RecorderEventSink) {
523-
if (eventSink)
524-
this._onRecorderEventSink = eventSink;
515+
if (eventSink) {
516+
const languages = [...languageSet()];
517+
const languageGeneratorOptions = {
518+
browserName: this._browser?._name ?? 'chromium',
519+
launchOptions: { headless: false, ...params.launchOptions, tracesDir: undefined },
520+
contextOptions: { ...params.contextOptions },
521+
deviceName: params.device,
522+
saveStorage: params.saveStorage,
523+
};
524+
const languageGenerator = languages.find(l => l.id === params.language) ?? languages.find(l => l.id === 'playwright-test')!;
525+
526+
this._channel.on('recorderEvent', ({ event, data, page }) => {
527+
if (event === 'actionAdded') {
528+
const action = data as actions.ActionInContext;
529+
const { actionTexts } = generateCode([action], languageGenerator, languageGeneratorOptions);
530+
eventSink.actionAdded?.(Page.from(page), action, actionTexts.join('\n'));
531+
} else if (event === 'actionUpdated') {
532+
const action = data as actions.ActionInContext;
533+
const { actionTexts } = generateCode([action], languageGenerator, languageGeneratorOptions);
534+
eventSink.actionUpdated?.(Page.from(page), action, actionTexts.join('\n'));
535+
} else if (event === 'signalAdded') {
536+
eventSink.signalAdded?.(Page.from(page), data as actions.SignalInContext);
537+
}
538+
});
539+
}
525540
await this._channel.enableRecorder(params);
526541
}
527542

528543
async _disableRecorder() {
529-
this._onRecorderEventSink = undefined;
530544
await this._channel.disableRecorder();
531545
}
532546
}

packages/playwright-core/src/protocol/validator.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -968,7 +968,6 @@ scheme.BrowserContextRecorderEventEvent = tObject({
968968
event: tEnum(['actionAdded', 'actionUpdated', 'signalAdded']),
969969
data: tAny,
970970
page: tChannel(['Page']),
971-
code: tString,
972971
});
973972
scheme.BrowserContextAddCookiesParams = tObject({
974973
cookies: tArray(tType('SetNetworkCookie')),

packages/playwright-core/src/server/DEPS.list

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
../protocol/
44
../utils
55
../utils/isomorphic/
6+
../utils/isomorphic/codegen
67
../utilsBundle.ts
78
../zipBundle.ts
89
./

packages/playwright-core/src/server/browserContext.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ export abstract class BrowserContext extends SdkObject {
6464
RequestContinued: 'requestcontinued',
6565
BeforeClose: 'beforeclose',
6666
VideoStarted: 'videostarted',
67-
RecorderEvent: 'recorderevent',
6867
};
6968

7069
readonly _pageBindings = new Map<string, PageBinding>();

packages/playwright-core/src/server/codegen/DEPS.list

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

packages/playwright-core/src/server/codegen/languages.ts

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

packages/playwright-core/src/server/codegen/types.ts

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

packages/playwright-core/src/server/debugController.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ import { asLocator } from '../utils';
2121
import { parseAriaSnapshotUnsafe } from '../utils/isomorphic/ariaSnapshot';
2222
import { yaml } from '../utilsBundle';
2323
import { unsafeLocatorOrSelectorAsSelector } from '../utils/isomorphic/locatorParser';
24-
import { generateCode } from './codegen/language';
25-
import { JavaScriptLanguageGenerator } from './codegen/javascript';
24+
import { generateCode } from '../utils/isomorphic/codegen/codegen';
25+
import { JavaScriptLanguageGenerator } from '../utils/isomorphic/codegen/javascript';
2626

2727
import type { Language } from '../utils';
2828
import type { BrowserContext } from './browserContext';

packages/playwright-core/src/server/dispatchers/browserContextDispatcher.ts

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ import { WebSocketRouteDispatcher } from './webSocketRouteDispatcher';
3434
import { WritableStreamDispatcher } from './writableStreamDispatcher';
3535
import { createGuid } from '../utils/crypto';
3636
import { urlMatches } from '../../utils/isomorphic/urlMatch';
37-
import { Recorder } from '../recorder';
37+
import { Recorder, RecorderEvent } from '../recorder';
3838
import { RecorderApp } from '../recorder/recorderApp';
39+
import { eventsHelper, RegisteredListener } from '../utils/eventsHelper';
3940

4041
import type { Artifact } from '../artifact';
4142
import type { ConsoleMessage } from '../console';
@@ -45,6 +46,7 @@ import type { InitScript, Page, PageBinding } from '../page';
4546
import type { DispatcherScope } from './dispatcher';
4647
import type * as channels from '@protocol/channels';
4748
import type { Progress } from '@protocol/progress';
49+
import type * as actions from '@recorder/actions';
4850

4951
export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channels.BrowserContextChannel, DispatcherScope> implements channels.BrowserContextChannel {
5052
_type_EventTarget = true;
@@ -59,6 +61,7 @@ export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channel
5961
private _requestInterceptor: RouteHandler;
6062
private _interceptionUrlMatchers: (string | RegExp)[] = [];
6163
private _routeWebSocketInitScript: InitScript | undefined;
64+
private _recorderListeners: RegisteredListener[] = [];
6265

6366
static from(parentScope: DispatcherScope, context: BrowserContext): BrowserContextDispatcher {
6467
const result = parentScope.connection.existingDispatcher<BrowserContextDispatcher>(context);
@@ -200,9 +203,6 @@ export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channel
200203
page: PageDispatcher.fromNullable(this, request.frame()?._page.initializedOrUndefined()),
201204
});
202205
});
203-
this.addObjectListener(BrowserContext.Events.RecorderEvent, ({ event, data, page, code }: { event: 'actionAdded' | 'actionUpdated' | 'signalAdded', data: any, page: Page, code: string }) => {
204-
this._dispatchEvent('recorderEvent', { event, data, code, page: PageDispatcher.from(this, page) });
205-
});
206206
}
207207

208208
private _shouldDispatchNetworkEvent(request: Request, event: channels.BrowserContextUpdateSubscriptionParams['event'] & channels.PageUpdateSubscriptionParams['event']): boolean {
@@ -340,13 +340,37 @@ export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channel
340340
}
341341

342342
async enableRecorder(params: channels.BrowserContextEnableRecorderParams, progress: Progress): Promise<void> {
343-
await RecorderApp.show(this._context, params);
343+
if (params.recorderMode !== 'api') {
344+
await RecorderApp.show(this._context, params);
345+
return;
346+
}
347+
348+
const findPageByGuid = (guid: string) => this._context.pages().find(p => p.guid === guid);
349+
const recorder = await Recorder.forContext(this._context, params);
350+
this._recorderListeners = [
351+
eventsHelper.addEventListener(recorder, RecorderEvent.ActionAdded, (action: actions.ActionInContext) => {
352+
const page = findPageByGuid(action.frame.pageGuid);
353+
if (page)
354+
this._dispatchEvent('recorderEvent', { event: 'actionAdded', data: action, page: PageDispatcher.from(this, page) });
355+
}),
356+
eventsHelper.addEventListener(recorder, RecorderEvent.ActionUpdated, (action: actions.ActionInContext) => {
357+
const page = findPageByGuid(action.frame.pageGuid);
358+
if (page)
359+
this._dispatchEvent('recorderEvent', { event: 'actionUpdated', data: action, page: PageDispatcher.from(this, page) });
360+
}),
361+
eventsHelper.addEventListener(recorder, RecorderEvent.SignalAdded, (signal: actions.SignalInContext) => {
362+
const page = findPageByGuid(signal.frame.pageGuid);
363+
if (page)
364+
this._dispatchEvent('recorderEvent', { event: 'signalAdded', data: signal, page: PageDispatcher.from(this, page) });
365+
}),
366+
];
344367
}
345368

346369
async disableRecorder(params: channels.BrowserContextDisableRecorderParams, progress: Progress): Promise<void> {
347370
const recorder = Recorder.existingForContext(this._context);
348371
if (recorder)
349372
recorder.setMode('none');
373+
eventsHelper.removeEventListeners(this._recorderListeners);
350374
}
351375

352376
async pause(params: channels.BrowserContextPauseParams, progress: Progress) {
@@ -442,5 +466,6 @@ export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channel
442466
if (this._clockPaused)
443467
this._context.clock.resumeNoReply();
444468
this._clockPaused = false;
469+
eventsHelper.removeEventListeners(this._recorderListeners);
445470
}
446471
}

0 commit comments

Comments
 (0)