fix: вернуть регистрацию activeXHR (onXHR) для отмены загрузки + тесты чистых функций
Deploy drhider / validate (push) Canceled after 0s

This commit is contained in:
“Naeel”
2026-08-25 19:14:30 +03:00
parent 52c3eb53f1
commit 0ad9e0047f
5 changed files with 49 additions and 0 deletions
+1
View File
@@ -363,6 +363,7 @@ async function uploadFiles() {
session: currentSid,
onStatus(k, html) { ss(sendIdx[k], html); },
onUploadStatus(text) { st.className = 'status progress'; st.textContent = text; },
onXHR(xhr) { activeXHR = xhr; },
});
if (!res.ok) {
st.className = 'status error';
+35
View File
@@ -18,6 +18,10 @@ import { listZipFiles } from './zip/list_zip_files.js';
import { parseZip } from './zip/parse_zip.js';
import { decodeZipName } from './zip/decode_zip_name.js';
import { addFileWithDedup } from './table/add_file_with_dedup.js';
import { esc } from './table/esc.js';
import { fs } from './table/fs.js';
import { fmtSec } from './table/fmt_sec.js';
import { estForFile } from './table/est_for_file.js';
const ALLOWED = ['.pdf', '.doc', '.docx', '.txt', '.md'];
@@ -194,6 +198,33 @@ function testSuffixes() {
console.log(' суффиксы _2/_3: ok');
}
function testEsc() {
assert.equal(esc('<a href="x">&\'</a>'), '&lt;a href=&quot;x&quot;&gt;&amp;&#39;&lt;/a&gt;');
console.log(' esc (XSS-экранирование): ok');
}
function testFs() {
assert.equal(fs(0), '0 B');
assert.equal(fs(1023), '1023 B');
assert.equal(fs(1024), '1.0 KB');
assert.equal(fs(1048576), '1.0 MB');
console.log(' fs (размер): ok');
}
function testFmtSec() {
assert.equal(fmtSec(0), '0с');
assert.equal(fmtSec(59), '59с');
assert.equal(fmtSec(60), '1м 0с');
assert.equal(fmtSec(125), '2м 5с');
console.log(' fmtSec: ok');
}
function testEstForFile() {
assert.equal(estForFile({ size: 1048576 }, 12), 12); // 1 МБ × 12 = 12с
assert.equal(estForFile(null, 12), 0);
console.log(' estForFile: ok');
}
// ── Прогон ──
const TESTS = [
['decodeZipName', testDecodeZipName],
@@ -204,6 +235,10 @@ const TESTS = [
['дедуп/суффиксы', testDedup],
['лимиты over', testLimits],
['суффиксы _2/_3', testSuffixes],
['esc XSS', testEsc],
['fs размер', testFs],
['fmtSec', testFmtSec],
['estForFile', testEstForFile],
];
let failed = 0;
+11
View File
@@ -87,6 +87,16 @@ async function testPutToVmTimeout() {
console.log(' putToVm timeout: ok');
}
async function testPutToVmOnXHR() {
let registered = null;
const p = putToVm(new File(['abc'], 'a.txt'), 'https://vm/tok_0', { onXHR(x) { registered = x; } });
assert.ok(registered, 'onXHR должен получить XHR для отмены');
registered.status = 200;
registered.onload();
await p;
console.log(' putToVm onXHR регистрация: ok');
}
// ── uploadViaVM ──
async function testUploadViaVMSuccess() {
installFetch(() => ({ ok: true, json: async () => ({ ok: true, session: 'sid123', count: 2 }) }));
@@ -172,6 +182,7 @@ const TESTS = [
['putToVm HTTP error', testPutToVmHttpError],
['putToVm network error', testPutToVmNetworkError],
['putToVm timeout', testPutToVmTimeout],
['putToVm onXHR', testPutToVmOnXHR],
['uploadViaVM success', testUploadViaVMSuccess],
['uploadViaVM PUT error', testUploadViaVMPutError],
['uploadViaVM POST error', testUploadViaVMPostError],
+1
View File
@@ -4,6 +4,7 @@
export function putToVm(file, url, options = {}) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
if (options.onXHR) options.onXHR(xhr); // регистрация для отмены (abort)
xhr.open('PUT', url);
xhr.timeout = options.timeoutMs || 300000; // 300с: большие файлы
xhr.upload.onprogress = function(e) {
+1
View File
@@ -30,6 +30,7 @@ export async function uploadViaVM(files, vmUploadUrl, options = {}) {
onProgress(pct) {
if (options.onStatus) options.onStatus(k, '<span style="color:#2563eb">⏳ ' + pct + '%</span>');
},
onXHR: options.onXHR,
});
const elapsed = (performance.now() - t0) / 1000;
const speed = f.size / elapsed;