aboutsummaryrefslogtreecommitdiff
path: root/modules/core
diff options
context:
space:
mode:
authorAgando <roduccomm@gmail.com>2026-10-23 15:28:57 +0200
committerAgando <roduccomm@gmail.com>2026-10-23 15:28:57 +0200
commit2aa908775e2660223115f62dde83549370d4cd84 (patch)
treeeb55ed7e4f708f2086b27003d12d654dcb30b7ef /modules/core
parent7c48b16cb59a514217e275b0a32cece3c74d2a24 (diff)
fix(newos4): define VirtualFS.emptyTrash() — empty-trash threw since 2026-10-18
Report RPT-20261018-164646-89352963 ("this.fs.emptyTrash is not a function") was filed by the auto-filer and never fixed: terminal.js:1777 called a method VirtualFS never defined, so 'empty-trash --confirm' threw instead of emptying. Added emptyTrash() returning true only when it removed something. Verified live on v4.6.54: put -> rm -> empty-trash --confirm => 'Trash emptied.'; second run => 'Trash is already empty.'; .trash entries 0.
Diffstat (limited to 'modules/core')
-rw-r--r--modules/core/core-bundle.js13
-rw-r--r--modules/core/module-loader.js2
-rw-r--r--modules/core/virtual-fs.js27
3 files changed, 41 insertions, 1 deletions
diff --git a/modules/core/core-bundle.js b/modules/core/core-bundle.js
index 331e090..212573d 100644
--- a/modules/core/core-bundle.js
+++ b/modules/core/core-bundle.js
@@ -632,6 +632,19 @@ class VirtualFileSystem {
}
return false;
}
+ // Reported 2026-10-18 ("this.fs.emptyTrash is not a function") and verified 2026-10-23:
+ // terminal.js:1777 called this method but nothing ever defined it, so `empty-trash --confirm`
+ // threw instead of emptying. Returns true only when something was actually removed.
+ emptyTrash() {
+ const trash = this.root.content && this.root.content['.trash'];
+ if (!trash || !trash.content) return false;
+ const names = Object.keys(trash.content);
+ if (!names.length) return false;
+ names.forEach(n => { delete trash.content[n]; });
+ this.saveToStorage();
+ this._emitChange('/.trash');
+ return true;
+ }
_pruneTrash(maxEntries = 50) {
// Bounded trash: deletions are moves-to-trash, so without a cap / .trash/ was an
// unbounded second accumulator. Names start with a millis timestamp → sort = oldest first.
diff --git a/modules/core/module-loader.js b/modules/core/module-loader.js
index f22576a..a3b3a6f 100644
--- a/modules/core/module-loader.js
+++ b/modules/core/module-loader.js
@@ -4,7 +4,7 @@
// Core module bundle loaded synchronously in main.html.
// This loader only handles version cache-busting, splash, terminal init, and optional ext modules.
- const LATEST_VER = 'v4.6.53';
+ const LATEST_VER = 'v4.6.54';
const CACHE = '?v=' + LATEST_VER;
const stored = localStorage.getItem('webx11_cache_ver');
if (stored !== LATEST_VER) {
diff --git a/modules/core/virtual-fs.js b/modules/core/virtual-fs.js
index 8f11d25..c9eb7a3 100644
--- a/modules/core/virtual-fs.js
+++ b/modules/core/virtual-fs.js
@@ -595,6 +595,7 @@ class VirtualFileSystem {
const trash = this.root.content['.trash'];
const trashName = ts + '-' + name;
trash.content[trashName] = JSON.parse(JSON.stringify(node));
+ this._pruneTrash();
const resolved = this._resolvePath(path);
if (resolved) delete resolved.dir.content[resolved.name];
this.saveToStorage();
@@ -620,6 +621,7 @@ class VirtualFileSystem {
let ctr = 0;
while (trash.content[unique]) { unique = baseName + '-' + (++ctr); }
trash.content[unique] = JSON.parse(JSON.stringify(node));
+ this._pruneTrash();
delete resolved.dir.content[resolved.name];
this.saveToStorage();
this._emitChange(path);
@@ -628,6 +630,31 @@ class VirtualFileSystem {
}
return false;
}
+ // Reported 2026-10-18 ("this.fs.emptyTrash is not a function") and verified 2026-10-23:
+ // terminal.js:1777 called this method but nothing ever defined it, so `empty-trash --confirm`
+ // threw instead of emptying. Returns true only when something was actually removed.
+ emptyTrash() {
+ const trash = this.root.content && this.root.content['.trash'];
+ if (!trash || !trash.content) return false;
+ const names = Object.keys(trash.content);
+ if (!names.length) return false;
+ names.forEach(n => { delete trash.content[n]; });
+ this.saveToStorage();
+ this._emitChange('/.trash');
+ return true;
+ }
+ _pruneTrash(maxEntries = 50) {
+ // Bounded trash: deletions are moves-to-trash, so without a cap / .trash/ was an
+ // unbounded second accumulator. Names start with a millis timestamp → sort = oldest first.
+ const trash = this.root.content['.trash'];
+ if (!trash) return 0;
+ const keys = Object.keys(trash.content);
+ if (keys.length <= maxEntries) return 0;
+ keys.sort();
+ const drop = keys.slice(0, keys.length - maxEntries);
+ drop.forEach(k => { delete trash.content[k]; });
+ return drop.length;
+ }
deleteDirRecursive(path) {
return this.trashDir(path);
}