fix(native-host): resolve "Unexpected end of JSON input" on Windows
CI / Build & Test (push) Successful in 4m6s
CI / Build & Test (push) Successful in 4m6s
Write all path variants for every .json in the bundle when building for win32 (backslash, with/without leading slash) so bundle.read() returns content regardless of runtime key normalization. Refill empty or invalid JSON from alternate key or disk before writing variants. Explicitly write tt-native package.json under Windows path variants in Fix 1. Document in CHANGELOG.
This commit is contained in:
@@ -24,6 +24,7 @@ All notable changes to Holesail Browser are documented here.
|
||||
**Bug fixes and stability (36 issues resolved)**
|
||||
- Fixed tt-native not available on Linux (SSH PTY disabled): build script now sets a host-specific addon resolution map so each platform binary loads the correct tt-native prebuild instead of the first host’s (darwin-arm64).
|
||||
- Fixed tt-native not available on Windows (SSH PTY disabled): use forward-slash addon resolution key for all platforms (including win32) so the runtime finds the addon when the bundle normalizes paths; Windows prebuild is still written under both forward and backslash keys for compatibility.
|
||||
- Fixed "Unexpected end of JSON input" on Windows when running the native host exe: write all path variants for every .json in the bundle (forward slash, backslash, with/without leading slash) so bundle.read() returns content regardless of how the runtime normalizes keys; refill empty or invalid JSON from disk or alternate key before writing variants.
|
||||
- Fixed `ReferenceError` for undeclared `regenerated` variable in `certificate-authority.js` on Windows
|
||||
- Added `hs.removeAllListeners()` in error paths of `setVirtualHost` and `startServiceTunnel` to prevent stale listener leaks
|
||||
- Cleared `reconnectTimer` when replacing an existing virtual host or service tunnel entry
|
||||
|
||||
@@ -210,12 +210,19 @@ function patchBundle(bundle, hosts) {
|
||||
)
|
||||
// Ensure tt-native package.json has content in the bundle. On Windows the runtime
|
||||
// can end up reading empty content for this key (path/bundle handling), causing
|
||||
// "Unexpected end of JSON input" when the .json loader runs. Explicitly write it.
|
||||
// "Unexpected end of JSON input" when the .json loader runs. Explicitly write it
|
||||
// under all key variants (with/without leading slash, and backslash for win32).
|
||||
const pkgPath = path.join(NATIVE_HOST_DIR, 'node_modules', 'tt-native', 'package.json')
|
||||
if (fs.existsSync(pkgPath)) {
|
||||
const pkgContent = fs.readFileSync(pkgPath)
|
||||
bundle.write(ttNativePkgKey, pkgContent)
|
||||
bundle.write(ttNativePkgKey.startsWith('/') ? ttNativePkgKey.slice(1) : '/' + ttNativePkgKey, pkgContent)
|
||||
if (hosts.some((h) => h.startsWith('win32'))) {
|
||||
const winPkgKey = ttNativePkgKey.replace(/\//g, '\\')
|
||||
bundle.write(winPkgKey, pkgContent)
|
||||
bundle.write(winPkgKey.replace(/^\\+/, ''), pkgContent)
|
||||
if (!winPkgKey.startsWith('\\')) bundle.write('\\' + winPkgKey, pkgContent)
|
||||
}
|
||||
}
|
||||
console.log(' Patched tt-native binding (host-specific resolutions)')
|
||||
}
|
||||
@@ -284,13 +291,20 @@ module.exports = EventEmitter;
|
||||
// ── Fix 3: Windows JSON empty-content and path normalization ──────────────────
|
||||
// On Windows the runtime can request .json keys with backslashes or get empty
|
||||
// content for some keys. Ensure every .json entry has valid content and add
|
||||
// backslash variants for win32 so the runtime finds them.
|
||||
// all backslash path variants for win32 so bundle.read() finds content
|
||||
// regardless of how the runtime normalizes the key.
|
||||
const hasWin32 = hosts.some((h) => h.startsWith('win32'))
|
||||
let jsonFixed = 0
|
||||
const keysToProcess = typeof bundle.keys === 'function' ? [...bundle.keys()] : Object.keys(bundle.files || {})
|
||||
for (const key of keysToProcess) {
|
||||
if (!key.endsWith('.json')) continue
|
||||
let content = bundle.read(key)
|
||||
// Try alternate key (with/without leading slash) in case empty due to key mismatch
|
||||
if (!content || content.length === 0) {
|
||||
const altKey = key.startsWith('/') ? key.slice(1) : '/' + key.replace(/^\/+/, '')
|
||||
content = bundle.read(altKey)
|
||||
if (content && content.length > 0) bundle.write(key, content)
|
||||
}
|
||||
const isEmpty = !content || content.length === 0
|
||||
const invalidJson = content && content.length > 0 && (() => { try { JSON.parse(content.toString()); return false } catch (_) { return true } })()
|
||||
if (isEmpty || invalidJson) {
|
||||
@@ -303,7 +317,15 @@ module.exports = EventEmitter;
|
||||
}
|
||||
if (hasWin32 && content && content.length > 0) {
|
||||
const winKey = key.replace(/\//g, '\\')
|
||||
if (winKey !== key) bundle.write(winKey, content)
|
||||
if (winKey !== key) {
|
||||
bundle.write(winKey, content)
|
||||
// Also write no-leading-backslash and leading-backslash variants so lookup
|
||||
// finds content whether the runtime uses "node_modules\..." or "\node_modules\..."
|
||||
const winKeyNoLead = winKey.replace(/^\\+/, '')
|
||||
if (winKeyNoLead !== winKey) bundle.write(winKeyNoLead, content)
|
||||
const winKeyWithLead = winKey.startsWith('\\') ? winKey : '\\' + winKey
|
||||
if (winKeyWithLead !== winKey) bundle.write(winKeyWithLead, content)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (jsonFixed > 0) console.log(` Patched ${jsonFixed} empty/invalid .json entries`)
|
||||
|
||||
Reference in New Issue
Block a user