Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(client): add serialized callstack #54

Merged
merged 1 commit into from
Dec 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions client/lib/CoreCommandQueue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export default class CoreCommandQueue {
return this.commandCounter?.lastCommandId;
}

public get lastCommand(): CoreCommandQueue['internalState']['lastCommand'] {
return this.internalState.lastCommand;
}

public get nextCommandId(): number {
return this.commandCounter?.nextCommandId;
}
Expand All @@ -22,6 +26,10 @@ export default class CoreCommandQueue {
queue: Queue;
commandsToRecord: ICoreRequestPayload['recordCommands'];
interceptFn?: (meta: ISessionMeta, command: string, ...args: any[]) => any;
lastCommand?: Pick<
ICoreRequestPayload,
'command' | 'commandId' | 'args' | 'callsite' | 'meta' | 'startDate'
>;
};

private readonly commandCounter?: ICommandCounter;
Expand Down Expand Up @@ -110,7 +118,7 @@ export default class CoreCommandQueue {

let callsite: string;
if (this.mode !== 'production') {
callsite = scriptInstance.getScriptCallSite();
callsite = JSON.stringify(scriptInstance.getScriptCallSite());
}
if (this.internalState.interceptFn) {
const result = this.internalState.interceptFn(this.meta, command, ...args);
Expand All @@ -121,20 +129,29 @@ export default class CoreCommandQueue {
return Promise.resolve(result as T);
}

const startTime = new Date();
const startDate = new Date();
const commandId = this.nextCommandId;

return this.internalQueue
.run<T>(async () => {
const recordCommands = [...this.internalState.commandsToRecord];
this.internalState.commandsToRecord.length = 0;
this.internalState.lastCommand = {
meta: this.meta,
command,
args,
startDate,
commandId,
callsite,
};

this.commandCounter?.emitter.emit('command', command, commandId, args);

const response = await this.connection.sendRequest({
meta: this.meta,
command,
args,
startDate: startTime,
startDate,
commandId,
recordCommands,
callsite,
Expand All @@ -161,6 +178,12 @@ export default class CoreCommandQueue {
}

public createSharedQueue(meta: ISessionMeta & { sessionName: string }): CoreCommandQueue {
return new CoreCommandQueue(meta, this.mode, this.connection, this.commandCounter, this.internalState);
return new CoreCommandQueue(
meta,
this.mode,
this.connection,
this.commandCounter,
this.internalState,
);
}
}
8 changes: 6 additions & 2 deletions client/lib/CoreEventHeap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ export default class CoreEventHeap {
startDate: new Date(),
command: 'Events.addEventListener',
args: [jsPath, type, options],
callsite: this.shouldIncludeCallSite() ? scriptInstance.getScriptCallSite() : null,
callsite: this.shouldIncludeCallSite()
? JSON.stringify(scriptInstance.getScriptCallSite())
: null,
});

this.pendingRegistrations = this.pendingRegistrations.then(() => subscriptionPromise);
Expand Down Expand Up @@ -98,7 +100,9 @@ export default class CoreEventHeap {
startDate: new Date(),
command: 'Events.removeEventListener',
args: [listenerId, options],
callsite: this.shouldIncludeCallSite() ? scriptInstance.getScriptCallSite() : null,
callsite: this.shouldIncludeCallSite()
? JSON.stringify(scriptInstance.getScriptCallSite())
: null,
})
.catch(error => {
log.error('removeEventListener Error: ', { error, sessionId: this.meta?.sessionId });
Expand Down
4 changes: 1 addition & 3 deletions client/lib/Hero.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,7 @@ export default class Hero extends AwaitedEventTarget<{
}

public detach(tab: Tab, key?: string): FrozenTab {
const callSitePath = getCallSite(module.filename, scriptInstance.entrypoint)
.map(x => `${x.getFileName()}:${x.getLineNumber()}:${x.getColumnNumber()}`)
.join('\n');
const callSitePath = JSON.stringify(getCallSite(module.filename, scriptInstance.entrypoint));

const coreTab = getCoreTab(tab);
const coreSession = getState(this).connection.getConnectedCoreSessionOrReject();
Expand Down
7 changes: 4 additions & 3 deletions client/lib/PageState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import IPageStateDefinitions, {
import Tab from './Tab';
import DisconnectedFromCoreError from '../connections/DisconnectedFromCoreError';
import { CanceledPromiseError } from '@ulixee/commons/interfaces/IPendingWaitEvent';
import ISourceCodeLocation from '@ulixee/commons/interfaces/ISourceCodeLocation';

let counter = 0;

Expand All @@ -27,7 +28,7 @@ export default class PageState<T extends IPageStateDefinitions, K = keyof T> {
readonly #coreTab: CoreTab;
readonly #tab: Tab;
readonly #states: T;
readonly #callsite: string;
readonly #callsite: ISourceCodeLocation[];
readonly #jsPath: IJsPath = ['page-state', (counter += 1)];
#idCounter = 0;

Expand All @@ -39,7 +40,7 @@ export default class PageState<T extends IPageStateDefinitions, K = keyof T> {
readonly #stateResolvable = new Resolvable<K>();
readonly #batchAssertionPathToId: Record<string, string> = {};

constructor(tab: Tab, coreTab: CoreTab, states: T, callSitePath: string) {
constructor(tab: Tab, coreTab: CoreTab, states: T, callSitePath: ISourceCodeLocation[]) {
this.#tab = tab;
this.#coreTab = coreTab;
this.#states = states ?? ({} as T);
Expand All @@ -54,7 +55,7 @@ export default class PageState<T extends IPageStateDefinitions, K = keyof T> {
const timer = new Timer(timeoutMs);
const pageStateOptions: IPageStateListenArgs = {
commands: this.#rawCommandsById,
callsite: this.#callsite,
callsite: JSON.stringify(this.#callsite),
states: Object.keys(this.#states),
};

Expand Down
13 changes: 7 additions & 6 deletions client/lib/ScriptInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { nanoid } from 'nanoid';
import IScriptInstanceMeta from '@ulixee/hero-interfaces/IScriptInstanceMeta';
import { getCallSite } from '@ulixee/commons/lib/utils';
import ISessionCreateOptions from '@ulixee/hero-interfaces/ISessionCreateOptions';
import ISourceCodeLocation from '@ulixee/commons/interfaces/ISourceCodeLocation';

const AwaitedDomPath = require.resolve('awaited-dom/package.json').replace('package.json', '');
const HeroLibPath = require.resolve('./Hero').replace(/\/Hero\.(?:ts|js)/, '');
Expand Down Expand Up @@ -50,27 +51,27 @@ export default class ScriptInstance {
return name;
}

public getScriptCallSite(ignoreMode = false): string {
if (!ignoreMode && this.mode === 'production') return;
public getScriptCallSite(getCallSiteRegardlessOfMode = false): ISourceCodeLocation[] {
if (!getCallSiteRegardlessOfMode && this.mode === 'production') return;
const stack = getCallSite(module.filename);

let stackLines: string[] = [];
let stackLines: ISourceCodeLocation[] = [];
let lastIndexOfEntrypoint = -1;
for (const callSite of stack) {
const filename = callSite.getFileName();
const { filename } = callSite;
if (!filename) continue;

if (filename.startsWith(HeroLibPath) || filename.startsWith(AwaitedDomPath)) continue;
if (filename.endsWith(this.entrypoint)) {
lastIndexOfEntrypoint = stackLines.length;
}

stackLines.push(`${filename}:${callSite.getLineNumber()}:${callSite.getColumnNumber()}`);
stackLines.push(callSite);
}

if (lastIndexOfEntrypoint >= 0) stackLines = stackLines.slice(0, lastIndexOfEntrypoint + 1);

return stackLines.join('\n');
return stackLines;
}
}

Expand Down
1 change: 0 additions & 1 deletion client/lib/Tab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,6 @@ export default class Tab extends AwaitedEventTarget<IEventType> {
states?: T,
options: Pick<IWaitForOptions, 'timeoutMs'> = { timeoutMs: 30e3 },
): Promise<keyof T> {

const callSitePath = scriptInstance.getScriptCallSite();

const coreTab = await getCoreTab(this);
Expand Down
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"require": "./index.cjs"
},
"dependencies": {
"@ulixee/commons": "1.5.8",
"@ulixee/commons": "1.5.9",
"@ulixee/hero-interfaces": "1.5.4",
"@ulixee/hero-plugin-utils": "1.5.4",
"awaited-dom": "1.3.0",
Expand Down
6 changes: 3 additions & 3 deletions client/test/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,16 @@ describe('basic Hero tests', () => {

const outgoingCommands = connectionToCore.outgoing.mock.calls;

expect(outgoingCommands.filter(c => c[0].callsite)).toHaveLength(0)
expect(outgoingCommands.filter(c => c[0].callsite)).toHaveLength(0);
});
});

describe('ScriptInstance tests', () => {
it('should be able to properly get a script location', () => {
expect(scriptInstance.getScriptCallSite().split(/\r?\n/)).toHaveLength(1);
expect(scriptInstance.getScriptCallSite()).toHaveLength(1);

(function testNested() {
expect(scriptInstance.getScriptCallSite().split(/\r?\n/)).toHaveLength(2);
expect(scriptInstance.getScriptCallSite()).toHaveLength(2);
})();
});
});
2 changes: 1 addition & 1 deletion core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"./connections/*": "./connections/*.js"
},
"dependencies": {
"@ulixee/commons": "1.5.8",
"@ulixee/commons": "1.5.9",
"@ulixee/default-browser-emulator": "1.5.4",
"@ulixee/default-human-emulator": "1.5.4",
"@ulixee/hero-interfaces": "1.5.4",
Expand Down
2 changes: 1 addition & 1 deletion fullstack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"require": "./index.cjs"
},
"dependencies": {
"@ulixee/commons": "1.5.8",
"@ulixee/commons": "1.5.9",
"@ulixee/hero": "1.5.4",
"@ulixee/hero-core": "1.5.4",
"@ulixee/hero-interfaces": "1.5.4",
Expand Down
2 changes: 1 addition & 1 deletion interfaces/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Core interfaces used by Hero",
"dependencies": {
"awaited-dom": "1.3.0",
"@ulixee/commons": "1.5.8",
"@ulixee/commons": "1.5.9",
"devtools-protocol": "^0.0.799653"
}
}
2 changes: 1 addition & 1 deletion mitm-socket/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"build-install": "npm run build"
},
"dependencies": {
"@ulixee/commons": "1.5.8",
"@ulixee/commons": "1.5.9",
"@ulixee/hero-interfaces": "1.5.4",
"nanoid": "^3.1.30"
},
Expand Down
2 changes: 1 addition & 1 deletion mitm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Man-in-the-middle proxy to fix chrome request/response",
"main": "index.js",
"dependencies": {
"@ulixee/commons": "1.5.8",
"@ulixee/commons": "1.5.9",
"@ulixee/hero-interfaces": "1.5.4",
"@ulixee/hero-mitm-socket": "1.5.4",
"better-sqlite3": "^7.4.1",
Expand Down
2 changes: 1 addition & 1 deletion plugin-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"scripts": {},
"dependencies": {
"@ulixee/chrome-app": "1.0.2",
"@ulixee/commons": "1.5.8",
"@ulixee/commons": "1.5.9",
"@ulixee/hero-interfaces": "1.5.4",
"progress": "^2.0.3",
"tar": "^6.1.11"
Expand Down
2 changes: 1 addition & 1 deletion plugins/default-browser-emulator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"main": "index.js",
"dependencies": {
"@ulixee/chrome-89-0": "^4389.128.4",
"@ulixee/commons": "1.5.8",
"@ulixee/commons": "1.5.9",
"@ulixee/hero-interfaces": "1.5.4",
"@ulixee/hero-plugin-utils": "1.5.4",
"compare-versions": "^3.6.0",
Expand Down
2 changes: 1 addition & 1 deletion plugins/default-human-emulator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"@ulixee/hero-plugin-utils": "1.5.4"
},
"devDependencies": {
"@ulixee/commons": "1.5.8"
"@ulixee/commons": "1.5.9"
}
}
2 changes: 1 addition & 1 deletion plugins/execute-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"@ulixee/hero-plugin-utils": "1.5.4"
},
"devDependencies": {
"@ulixee/commons": "1.5.8",
"@ulixee/commons": "1.5.9",
"@ulixee/hero-core": "1.5.4",
"@ulixee/hero-fullstack": "1.5.4",
"@ulixee/execute-js-plugin": "1.5.4",
Expand Down
2 changes: 1 addition & 1 deletion puppet-chrome/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "1.5.4",
"description": "Puppet driver for chrome",
"dependencies": {
"@ulixee/commons": "1.5.8",
"@ulixee/commons": "1.5.9",
"@ulixee/hero-interfaces": "1.5.4",
"devtools-protocol": "^0.0.799653"
}
Expand Down
2 changes: 1 addition & 1 deletion puppet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "1.5.4",
"description": "Puppet driver",
"dependencies": {
"@ulixee/commons": "1.5.8",
"@ulixee/commons": "1.5.9",
"@ulixee/hero-interfaces": "1.5.4",
"@ulixee/hero-puppet-chrome": "1.5.4",
"ws": "^7.4.6"
Expand Down
2 changes: 1 addition & 1 deletion testing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"dependencies": {
"@koa/multer": "^3.0.0",
"@koa/router": "^8.0.8",
"@ulixee/commons": "1.5.8",
"@ulixee/commons": "1.5.9",
"@ulixee/hero-core": "1.5.4",
"@ulixee/hero-interfaces": "1.5.4",
"@ulixee/hero-mitm-socket": "1.5.4",
Expand Down
2 changes: 1 addition & 1 deletion timetravel/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "1.5.4",
"description": "The interface to playback and examine previous Hero sessions",
"dependencies": {
"@ulixee/commons": "1.5.8",
"@ulixee/commons": "1.5.9",
"@ulixee/hero-interfaces": "1.5.4",
"@ulixee/hero-core": "1.5.4",
"nanoid": "^3.1.30"
Expand Down
7 changes: 6 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7509,6 +7509,11 @@ sort-keys@^4.0.0:
dependencies:
is-plain-obj "^2.0.0"

source-map-js@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.1.tgz#a1741c131e3c77d048252adfa24e23b908670caf"
integrity sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA==

source-map-loader@^0.2.4:
version "0.2.4"
resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-0.2.4.tgz#c18b0dc6e23bf66f6792437557c569a11e072271"
Expand All @@ -7517,7 +7522,7 @@ source-map-loader@^0.2.4:
async "^2.5.0"
loader-utils "^1.1.0"

source-map-support@^0.5.19, source-map-support@^0.5.6:
source-map-support@^0.5.6:
version "0.5.20"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9"
integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==
Expand Down