mirror of
https://github.com/bendtherules/ask262.git
synced 2026-08-18 13:21:55 +00:00
Merge commit '6e92d2345e8231a44556ce7d416451f5f3e6c398' as 'engine262'
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
import type { Protocol } from 'devtools-protocol';
|
||||
import { InspectorContext } from './context.mts';
|
||||
import * as impl from './methods.mts';
|
||||
import type { DebuggerContext, DebuggerPreference, DevtoolEvents } from './types.mts';
|
||||
import { getParsedEvent } from './internal-utils.mts';
|
||||
import {
|
||||
Agent, ManagedRealm, Realm, type Arguments,
|
||||
} from '#self';
|
||||
|
||||
const ignoreNamespaces = ['Network'];
|
||||
const ignoreMethods: string[] = [];
|
||||
|
||||
export type { DebuggerPreference } from './types.mts';
|
||||
export { createConsole } from './utils.mts';
|
||||
|
||||
interface AgentRecord {
|
||||
readonly agent: Agent;
|
||||
onDetach(): void;
|
||||
}
|
||||
export abstract class Inspector {
|
||||
#context = new InspectorContext(this);
|
||||
|
||||
#agents: AgentRecord[] = [];
|
||||
|
||||
attachAgent(agent: Agent, priorRealms: ManagedRealm[]) {
|
||||
const oldOnDebugger = agent.hostDefinedOptions.onDebugger;
|
||||
agent.hostDefinedOptions.onDebugger = () => {
|
||||
oldOnDebugger?.();
|
||||
this.sendEvent['Debugger.paused']({
|
||||
reason: 'debugCommand',
|
||||
callFrames: this.#context.getDebuggerCallFrame(),
|
||||
});
|
||||
};
|
||||
|
||||
const oldOnRealmCreated = agent.hostDefinedOptions.onRealmCreated;
|
||||
agent.hostDefinedOptions.onRealmCreated = (realm) => {
|
||||
oldOnRealmCreated?.(realm);
|
||||
this.#context.attachRealm(realm, agent);
|
||||
};
|
||||
|
||||
const oldOnScriptParsed = agent.hostDefinedOptions.onScriptParsed;
|
||||
agent.hostDefinedOptions.onScriptParsed = (script, id) => {
|
||||
oldOnScriptParsed?.(script, id);
|
||||
const realmId = this.#context.getRealm(script.Realm as ManagedRealm)?.descriptor.id;
|
||||
if (realmId === undefined) {
|
||||
return;
|
||||
}
|
||||
this.sendEvent['Debugger.scriptParsed'](getParsedEvent(script, id, realmId));
|
||||
};
|
||||
this.#agents.push({
|
||||
agent,
|
||||
onDetach: () => {
|
||||
agent.hostDefinedOptions.onDebugger = oldOnDebugger;
|
||||
agent.hostDefinedOptions.onRealmCreated = oldOnRealmCreated;
|
||||
agent.hostDefinedOptions.onScriptParsed = oldOnScriptParsed;
|
||||
this.#agents = this.#agents.filter((x) => x.agent !== agent);
|
||||
},
|
||||
});
|
||||
priorRealms.forEach((realm) => {
|
||||
this.#context.attachRealm(realm, agent);
|
||||
});
|
||||
}
|
||||
|
||||
detachAgent(agent: Agent) {
|
||||
const record = this.#agents.find((x) => x.agent === agent);
|
||||
record?.onDetach();
|
||||
this.#context.detachAgent(agent);
|
||||
}
|
||||
|
||||
protected abstract send(data: object): void;
|
||||
|
||||
readonly preference: DebuggerPreference = { previewDebug: false };
|
||||
|
||||
protected onMessage(id: unknown, methodArg: string, params: unknown): void {
|
||||
if (ignoreMethods.includes(methodArg)) {
|
||||
return;
|
||||
}
|
||||
const [namespace, method] = methodArg.split('.');
|
||||
if (ignoreNamespaces.includes(namespace)) {
|
||||
return;
|
||||
}
|
||||
if (!(namespace in impl)) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`Unknown namespace requested: ${namespace}`);
|
||||
return;
|
||||
}
|
||||
const ns = (impl as Record<string, object>)[namespace];
|
||||
if (!(method in ns)) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`Unknown method requested: ${namespace}.${method}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const f = (ns as Record<string, (args: unknown, context: DebuggerContext) => unknown>)[method];
|
||||
new Promise((resolve) => {
|
||||
resolve(f(params, this.#debugContext));
|
||||
}).then((result = {}) => {
|
||||
this.send({ id, result });
|
||||
});
|
||||
}
|
||||
|
||||
sendEvent: DevtoolEvents = Object.create(new Proxy({}, {
|
||||
get: (_, key: string) => {
|
||||
const f = (params: Record<string, unknown>) => {
|
||||
this.send({ method: key, params });
|
||||
};
|
||||
Object.defineProperty(this.sendEvent, key, { value: f });
|
||||
return f;
|
||||
},
|
||||
}));
|
||||
|
||||
console(realm: Realm, type: Protocol.Runtime.ConsoleAPICalledEventType, args: Arguments) {
|
||||
const context = this.#context.getRealm(realm as ManagedRealm);
|
||||
if (!context) {
|
||||
return;
|
||||
}
|
||||
this.sendEvent['Runtime.consoleAPICalled']({
|
||||
type,
|
||||
args: args.map((x) => this.#context.toRemoteObject(x, { })),
|
||||
executionContextId: context.descriptor.id,
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
}
|
||||
|
||||
#debugContext: DebuggerContext = {
|
||||
sendEvent: this.sendEvent,
|
||||
preference: this.preference,
|
||||
context: this.#context,
|
||||
onDebuggerAttached: () => {
|
||||
this.#context.realms.forEach((realm) => {
|
||||
if (realm) {
|
||||
this.sendEvent['Runtime.executionContextCreated']({
|
||||
context: realm.descriptor,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user