diff options
| author | Agando <roduccomm@gmail.com> | 2026-10-29 12:13:33 +0100 |
|---|---|---|
| committer | Agando <roduccomm@gmail.com> | 2026-10-29 12:13:33 +0100 |
| commit | 43d067396b5a620441b9a299c45e7b0b129ccd15 (patch) | |
| tree | a0a03230969a56ce210dc9df2d8457cc866c3a3e /modules/ext | |
| parent | 1d78155c38fcbc9c76bad7c522e9d9f1060bc4b9 (diff) | |
fix(newos4): js console handles promise rejections + Node-builtin hint (v4.6.128)
evalJS() evaluated the expression bare and printed JSON.stringify(result), so a
rejected thenable (e.g. `js import('fs')`) became `{}` on screen while the rejection
escaped to window.onunhandledrejection and was auto-filed as a runtime bug report
(RPT-20261028-172211-9c7f2adb, cluster 480x). evalJSFile() already had .then/.catch —
the asymmetry was the defect.
- modules/ext/console.js: thenable branch in evalJS() awaits and catches; new
_printError() is the single error sink for all four catch paths and appends a hint
when a bare specifier fails to resolve ("'fs' is a Node built-in; the browser has no
Node — use the VFS (ls/cat/run, terminal.fs) instead").
- help.html: js / js-run rows say "browser only — no Node built-ins".
- module-loader.js + main.html: v4.6.128.
Verification (/tmp/test-console-fs.js, 11 asserts, new Function harness over the module):
GREEN 11/11 — rejection prints one red error + hint, no unhandledRejection; resolved
thenable prints its value; sync value/throw unchanged; js-run file + missing file OK.
RED 4/11 against .bkp-console-20261029_121243/console.js — A1/A2/A3 print `{}`,
A4/G2 leak "Failed to resolve module specifier 'fs'".
node --check modules/ext/console.js → OK.
console.js is loaded separately via extKeys (not in critical-ext-bundle.js), so no bundle
rebuild — proven by `grep -c JSConsoleModule modules/ext/critical-ext-bundle.js` = 0.
Consumes STEER-20261028-195043-8084. Plan: .hermes/plans/2026-10-29_063000-newos4-js-console-fs-specifier.md
Diffstat (limited to 'modules/ext')
| -rw-r--r-- | modules/ext/console.js | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/modules/ext/console.js b/modules/ext/console.js index 5d3007a..60f75a7 100644 --- a/modules/ext/console.js +++ b/modules/ext/console.js @@ -30,13 +30,28 @@ class JSConsoleModule { evalJS(args) { if (!args[0]) return this.terminal.print('Usage: js <expression>', 'warning'); const expr = args.join(' '); - // v4.5.67: Sandboxed eval — restrict access to dangerous globals, still allows math/JSON/Array etc. + // v4.6.128: Sandboxed eval — restrict access to dangerous globals, still allows math/JSON/Array etc. try { const result = (function() { 'use strict'; // eslint-disable-next-line no-eval return eval(expr); })(); + // A thenable must be awaited: an uncaught `import('fs')` rejection escapes to + // window.onunhandledrejection and is auto-filed as a runtime bug report. + if (result && typeof result.then === 'function') { + result.then(val => { + const output = val === undefined ? 'undefined' : + typeof val === 'string' ? val : + val === null ? 'null' : + typeof val === 'object' ? JSON.stringify(val, null, 2) : + String(val); + this.terminal.print(output, 'success'); + }).catch(e => { + this._printError(e); + }); + return; + } const output = result === undefined ? 'undefined' : typeof result === 'string' ? result : result === null ? 'null' : @@ -44,7 +59,19 @@ class JSConsoleModule { String(result); this.terminal.print(output, 'success'); } catch (e) { - this.terminal.print(`Error: ${e.message}`, 'error'); + this._printError(e); + } + } + + // Single error sink: prints `Error: <msg>`, plus a Node-builtin hint when the browser + // could not resolve a bare specifier (v4.6.128). + _printError(e) { + const msg = (e && e.message) ? e.message : String(e); + this.terminal.print(`Error: ${msg}`, 'error'); + const m = /(?:Failed to resolve module specifier|Cannot find module) '([^']+)'/.exec(msg); + if (m) { + this.terminal.print(`'${m[1]}' is a Node built-in; the browser has no Node — ` + + `use the VFS (ls/cat/run, terminal.fs) instead`, 'warning'); } } @@ -73,7 +100,7 @@ class JSConsoleModule { String(val); this.terminal.print(output, 'success'); }).catch(e => { - this.terminal.print(`Error: ${e.message}`, 'error'); + this._printError(e); }); return; } @@ -84,7 +111,7 @@ class JSConsoleModule { String(result); this.terminal.print(output, 'success'); } catch (e) { - this.terminal.print(`Error: ${e.message}`, 'error'); + this._printError(e); } } |