fix: improve resolver error propagation, sanitization, and consistency

This commit is contained in:
Dariusz L
2026-07-16 11:11:48 +02:00
parent 20a83c7262
commit 28d24214aa
6 changed files with 28 additions and 15 deletions
@@ -2,6 +2,7 @@ import fs from 'node:fs';
import path from 'node:path';
import test from 'node:test';
import assert from 'node:assert/strict';
import { normalizePathIdentity } from '../web/resolver/utils/html_utils.js';
const projectRoot = path.resolve(import.meta.dirname, '..');
const queueMethodsSource = fs.readFileSync(
+2 -2
View File
@@ -495,7 +495,7 @@ export const queueMethods = {
if (typeof document === 'undefined') return null;
for (const selector of this.getWorkflowTabActiveSelectors()) {
let elements = [];
let elements;
try {
elements = Array.from(document.querySelectorAll(selector));
} catch (error) {
@@ -900,7 +900,7 @@ export const queueMethods = {
let bestMatch = null;
for (const selector of this.getWorkflowTabSearchSelectors()) {
let elements = [];
let elements;
try {
elements = Array.from(document.querySelectorAll(selector));
} catch (error) {
@@ -335,6 +335,9 @@ export const resolveDownloadMethods = {
const batchWorkflowKey = this.getWorkflowScopedQueueKey();
let completed = 0;
let failed = 0;
let cancelled;
let batchError;
let hasBatchError = false;
try {
for (const missing of targets) {
if (this.batchSearchCancelRequested) {
@@ -351,20 +354,25 @@ export const resolveDownloadMethods = {
completed += 1;
this.updateBatchFooterButtons();
}
} catch (error) {
batchError = error;
hasBatchError = true;
} finally {
const cancelled = this.batchSearchCancelRequested;
cancelled = this.batchSearchCancelRequested;
this.batchSearchRunning = false;
this.batchSearchCancelRequested = false;
this.persistSearchStateForActiveWorkflow();
this.updateBatchFooterButtons();
const suffix = failed ? `, ${failed} failed` : '';
if (cancelled) {
this.showNotification(`Stopped search after ${completed} of ${targets.length} model${targets.length === 1 ? '' : 's'}${suffix}.`, 'info');
return;
}
}
const suffix = failed ? `, ${failed} failed` : '';
if (cancelled) {
this.showNotification(`Stopped search after ${completed} of ${targets.length} model${targets.length === 1 ? '' : 's'}${suffix}.`, 'info');
return;
}
if (hasBatchError) {
throw batchError;
}
this.showNotification(`Finished search for ${completed} model${completed === 1 ? '' : 's'}${suffix}.`, failed ? 'error' : 'success');
},
@@ -2904,7 +2912,7 @@ export const resolveDownloadMethods = {
const url = btn.dataset.url;
const filename = btn.dataset.filename;
const category = btn.dataset.category;
let pathMetadata = null;
let pathMetadata;
try {
pathMetadata = btn.dataset.pathMetadata
? JSON.parse(decodeURIComponent(btn.dataset.pathMetadata))
@@ -2912,7 +2920,7 @@ export const resolveDownloadMethods = {
} catch (_error) {
pathMetadata = null;
}
let downloadMetadata = null;
let downloadMetadata;
try {
downloadMetadata = btn.dataset.downloadMetadata
? JSON.parse(decodeURIComponent(btn.dataset.downloadMetadata))
+3 -3
View File
@@ -885,7 +885,7 @@ export class ModelResolver {
const currentWorkflow = workflow || app?.graph?.serialize?.();
if (!currentWorkflow) return;
let signature = '';
let signature;
try {
signature = JSON.stringify((currentWorkflow.nodes || []).map((node) => [
node?.id,
@@ -1017,7 +1017,7 @@ export class ModelResolver {
for (const el of allElements) {
if (el.textContent?.includes('following models were not found') &&
el.children.length === 0) {
el.parentElement?.insertBefore(btnContainer, el.nextSibling);
el.parentElement?.insertBefore(autoResolveBtn, el.nextSibling);
break;
}
}
@@ -1082,7 +1082,7 @@ export class ModelResolver {
);
let node;
while (node = walker.nextNode()) {
while ((node = walker.nextNode())) {
if (node.textContent?.toLowerCase().includes(filename)) {
// Found text containing filename - now find parent with Download button
let parent = node.parentElement;
@@ -5,6 +5,10 @@ import { getSvgIcon } from "../../utils/icon_utils.js";
import { createFloatingTreePicker } from "../utils/tree_picker.js";
import { safeStorage } from "../utils/html_utils.js";
const localStorage = safeStorage;
const invalidWindowsPathCharacters = new RegExp(
`[<>:"|?*${Array.from({ length: 32 }, (_, code) => String.fromCharCode(code)).join('')}]+`,
'g'
);
export const downloadTargetMethods = {
/**
* Ensure all models are loaded for the dropdown.
@@ -1198,7 +1202,7 @@ export const downloadTargetMethods = {
let text = String(value || '').trim() || fallback;
text = text
.replace(/[\\/]+/g, '_')
.replace(/[<>:"|?*\x00-\x1f]+/g, '_')
.replace(invalidWindowsPathCharacters, '_')
.replace(/\s+/g, ' ')
.replace(/^[\s.]+|[\s.]+$/g, '');
if (!text || text === '.' || text === '..') {
+1 -1
View File
@@ -453,7 +453,7 @@ export const workflowStateMethods = {
},
cloneSearchState(state = {}, { preserveActive = false } = {}) {
let clone = {};
let clone;
try {
clone = JSON.parse(JSON.stringify(state || {}));
} catch (error) {