fix: improve resolver error propagation, sanitization, and consistency
This commit is contained in:
@@ -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(
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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 === '..') {
|
||||
|
||||
@@ -453,7 +453,7 @@ export const workflowStateMethods = {
|
||||
},
|
||||
|
||||
cloneSearchState(state = {}, { preserveActive = false } = {}) {
|
||||
let clone = {};
|
||||
let clone;
|
||||
try {
|
||||
clone = JSON.parse(JSON.stringify(state || {}));
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user