runLoop function
Last updated: 2026-03-05T10:53:28.864Z
Metrics
LOC: 123
Complexity: 32
Params: 1
Signature
runLoop(signal: AbortSignal): : Promise<void>
Architecture violations
- [warning] max-cyclomatic-complexity: 'runLoop' has cyclomatic complexity 32 (max 10)
- [warning] max-lines: 'runLoop' has 123 lines (max 80)
Source Code
async function runLoop(signal: AbortSignal): Promise<void> {
if (!flow || !rng) return;
// Navigate to baseUrl before executing steps
if (flow.metadata.baseUrl) {
log.info(`Navigating to baseUrl: ${flow.metadata.baseUrl}`);
const loaded = await navigateAndWait(tabId, flow.metadata.baseUrl);
if (!loaded) {
log.warn(`Failed to navigate to baseUrl: ${flow.metadata.baseUrl}`);
}
await injectContentScript(tabId);
}
for (; stepIndex < flow.steps.length; stepIndex++) {
if (signal.aborted) return;
await waitIfPaused();
if (signal.aborted) return;
const step = flow.steps[stepIndex]!;
emitProgress(step);
// Apply delay before step
const delay =
config.useRecordedTimings && step.delayBefore
? step.delayBefore
: config.stepDelay;
if (delay > 0 && stepIndex > 0) {
try {
await sleep(delay, signal);
} catch {
return; // aborted during delay
}
}
// Resolve value for fill steps
let resolvedValue: string | undefined;
if (step.action === "fill" && step.valueSource) {
resolvedValue = resolveValueSource(step.valueSource, generate);
}
// Execute
let result: StepResult;
if (step.action === "navigate") {
result = await executeNavigateStep(step);
} else {
// Before interaction, move cursor (sent as separate message)
if (
step.selector &&
config.highlightDuration > 0 &&
config.showCursor !== false
) {
try {
await chrome.tabs.sendMessage(tabId, {
type: "DEMO_CURSOR_MOVE",
payload: { selector: step.selector, durationMs: 400 },
});
await sleep(config.highlightDuration, signal);
} catch {
// cursor overlay is optional — ignore
}
}
// Click effect
if (step.action === "click" && config.showCursor !== false) {
try {
await chrome.tabs.sendMessage(tabId, {
type: "DEMO_CURSOR_CLICK",
});
} catch {
// ignore
}
}
// Highlight element
if (config.highlightDuration > 0) {
try {
await chrome.tabs.sendMessage(tabId, {
type: "DEMO_HIGHLIGHT_ELEMENT",
payload: { step, durationMs: config.highlightDuration },
});
} catch {
// ignore
}
}
result = await sendStepToContentScript(step, resolvedValue);
}
stepResults.push({ stepId: step.id, result });
// Handle failure
if (result.status === "failed") {
if (step.optional) {
log.info(
`Optional step ${step.id} failed, continuing:`,
result.error,
);
} else {
log.warn(`Step ${step.id} failed:`, result.error);
setStatus("failed");
callbacks.onComplete?.(buildResult());
return;
}
}
// Apply delay after step
if (step.delayAfter && step.delayAfter > 0) {
try {
await sleep(step.delayAfter, signal);
} catch {
return;
}
}
}
// All steps complete
setStatus("completed");
chrome.tabs
.sendMessage(tabId, { type: "DEMO_CURSOR_DESTROY" })
.catch(() => {});
callbacks.onComplete?.(buildResult());
}
Dependencies (Outgoing)
| Target | Type |
|---|---|
| navigateAndWait | calls |
| injectContentScript | calls |
| waitIfPaused | calls |
| emitProgress | calls |
| sleep | calls |
| resolveValueSource | calls |
| executeNavigateStep | calls |
| sendStepToContentScript | calls |
| setStatus | calls |
| buildResult | calls |
Impact (Incoming)
| Source | Type |
|---|---|
| start | calls |