@@ -0,0 +1,6 @@
|
||||
stderr (last 2000 chars):
|
||||
|
||||
|
||||
Host reported ready: false
|
||||
tt-native available (no disable msg): true
|
||||
PASS: false
|
||||
Generated
+1
@@ -7,6 +7,7 @@
|
||||
"": {
|
||||
"name": "holesail-browser-host",
|
||||
"version": "1.0.0",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"assert": "npm:bare-node-assert@^1.0.0",
|
||||
"b4a": "^1.6.7",
|
||||
|
||||
Generated
+1
@@ -7,6 +7,7 @@
|
||||
"": {
|
||||
"name": "holesail-browser",
|
||||
"version": "1.0.0",
|
||||
"license": "AGPL-3.0",
|
||||
"devDependencies": {
|
||||
"archiver": "^7.0.1",
|
||||
"bare-build": "^0.4.3",
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIID6TCCAtGgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBhjEcMBoGA1UEAxMTSG9s
|
||||
ZXNhaWwgQnJvd3NlciBDQTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYD
|
||||
VQQHEw1TYW4gRnJhbmNpc2NvMRkwFwYDVQQKExBIb2xlc2FpbCBCcm93c2VyMRkw
|
||||
FwYDVQQLExBIb2xlc2FpbCBSb290IENBMB4XDTI2MDMwNzAxMDg1MloXDTM2MDMw
|
||||
NzAxMDg1MlowgYYxHDAaBgNVBAMTE0hvbGVzYWlsIEJyb3dzZXIgQ0ExCzAJBgNV
|
||||
BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcG
|
||||
A1UEChMQSG9sZXNhaWwgQnJvd3NlcjEZMBcGA1UECxMQSG9sZXNhaWwgUm9vdCBD
|
||||
QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMRA66qMT8eI9ur+CmCr
|
||||
3+jnlTe9pCZ9cJ4glEH9eab4VQ/6u95PBkZMWx+JsIwd1TTuXZ4UExI3ESh3bN0k
|
||||
4l3H1dBV6ipvcghUajxMuVuhpjp6k9DMtE+newfcS2Rf871LSnUndu/RetGDeL1b
|
||||
wBaVowYuxTyiA/l4BBWxppJ0HZ/W/1u0YBolHlnsH7ZCVngSu/JHxU5jZkHtfYL7
|
||||
ePmkPhSuTj7wtNmNR2Ckaxt4lmHCprFsjuGFneG8BIqZRIgeB21kVtkeKMFSj4Ab
|
||||
oR8IWFS6sPiTfEUB/7Ixs7XnfaQRKFlW0TR1e9F7scavUVeU1uGCcd8tE+wHTfct
|
||||
rlECAwEAAaNgMF4wDwYDVR0TBAgwBgEB/wIBADALBgNVHQ8EBAMCAQYwHQYDVR0O
|
||||
BBYEFCBY+xanOwexpYFp4lTeWwpNbO29MB8GA1UdIwQYMBaAFCBY+xanOwexpYFp
|
||||
4lTeWwpNbO29MA0GCSqGSIb3DQEBCwUAA4IBAQCbMD1+7sdx4FE75Iz0jaY0ij2N
|
||||
PHxfzZ/1uwIXt0xpq1ajwphvMJ+9nDZKYQKnAQsMhUTy+vU4d3muCC3GFraMWpcS
|
||||
gNH0L17zpv155TqLWeUYBkXaTygBkslpNyJUsRdrevzLp6U3fRYyDedEt8civyBW
|
||||
vR0Q4+V4GdWDzzYqo45umX52PK//cyExKWa5t/9QBC3qfsKZUbh5pt+TqoXQN5ph
|
||||
AdcJMZ5JnDO1pKASo3odgBlfEAWG/QxqbZQ4ggjSLB4SxIlRFLLp6EIVn2VlPwPc
|
||||
op5QfQy3JCrXNcOctkbwAHbOsJUuFnVJWZSZguQcbz8IKVm1TSQ9G5cHaCNu
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAxEDrqoxPx4j26v4KYKvf6OeVN72kJn1wniCUQf15pvhVD/q7
|
||||
3k8GRkxbH4mwjB3VNO5dnhQTEjcRKHds3STiXcfV0FXqKm9yCFRqPEy5W6GmOnqT
|
||||
0My0T6d7B9xLZF/zvUtKdSd279F60YN4vVvAFpWjBi7FPKID+XgEFbGmknQdn9b/
|
||||
W7RgGiUeWewftkJWeBK78kfFTmNmQe19gvt4+aQ+FK5OPvC02Y1HYKRrG3iWYcKm
|
||||
sWyO4YWd4bwEiplEiB4HbWRW2R4owVKPgBuhHwhYVLqw+JN8RQH/sjGzted9pBEo
|
||||
WVbRNHV70Xuxxq9RV5TW4YJx3y0T7AdN9y2uUQIDAQABAoIBAEGC/mhXIEaWZP56
|
||||
wRIWLc98huYtiv9CPna6n2ML7zEakqKb61zBenG7CWwUtXeAeeyKaXvcbaVV9odQ
|
||||
nmmP53SwwaIjG+EAhMtdCn2IixOYeXnp8y/vNX2lhb9Q/WXLVfzphjhnbR+PCPWp
|
||||
coObfhrL5rioojSkTLlZI9vuCpG2VW8GZoWIJ7T316TiETnhYKy4ms1bRnjsTlcN
|
||||
M8kIPfesrIUMkIKiRBrKzYbU3V14wI7dZJQzkh4bjG3VMww+smiFgkME2c+KJwJA
|
||||
OWHd1vZOzN/WtzSri3Y6ftcntm+r/uLkr3IXnqAVDRVgFldXtFarlq1jDy6DLmCg
|
||||
gBzqoDECgYEA6P9USl0Nn+yO+fbpiylPo+XCmVxe7XEm8x7OKXCtlHPlPhGMq9Aj
|
||||
DeargOoqJa+gyG8sASiM2DneeAvsKrr2fg1GF5elkB1enYhOmABMXQTLY4p7th9v
|
||||
KcizbI12lr04rGCgdigFxgMjZ1g1WCv1aFFkD55EOY388h1GUqBWCkUCgYEA16Dy
|
||||
CwnsiZB7y1PiD0qOhhSG+ao2E7duJOgUnIm1gBNFjn8WYe4lEUs+Qy9Kg43G3CV3
|
||||
6ZvUOvWFQM2o/ZcGjH60wIq2SGV1rP1Gb+7YZTqAshsTNvSt2g2twZ2In+7uJBcJ
|
||||
dXyC8YW9uQft5kc7wcufuwvZkPaTqzNYBRH6+p0CgYAYSgXPesPg2BhPlp3iE/xp
|
||||
aZpPwoFi31jgH2X+i/CMeUh8n/e6MYh1+oYGemLKavSn8G717/Q+1kmK2jNUgQkR
|
||||
OvEDpJtt2qHyajNHRUCwsb9CMT2UTtKX2IRb3KNwM2mlDq2ro6B2c/1M2LU26945
|
||||
ccKsniMenN6xnrumAXD2wQKBgQClyE0vpYKhxV8YVbbhUM5BUfjwbShEgmwBnhly
|
||||
vQG5pZd91kIMKv9+y13kY7CjclapHXmTN0a1ydyYlUZPKlVToXsw6bT59l/CD7yf
|
||||
BICFW7RkuyJLx1T+6DNmP8syQ43+W2PfW0qFjPDwGKOUv8G23upA8fxlUt736nLK
|
||||
+yb+lQKBgGQDmKZwtjFtC46Y04G/lL9BeGMnu8sOahRsEsAZ5tps8cl4dPofBkcW
|
||||
oHMuYENz5qBGx1DCKYfGS5mv3t6Kifye+1K1MjyM7b+JLJ6cIVS80n2RvBOK1qQY
|
||||
RWJhL2HIT7+nkpRcOKlih2yxTbeToNvNLO8FBFZn/qWI8xY2yY7E
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -146,27 +146,54 @@ module.exports = async function sign() {}
|
||||
* can be called as a plain constructor function via util.inherits.
|
||||
*/
|
||||
function patchBundle(bundle, hosts) {
|
||||
// ── Fix 1: tt-native addon ──────────────────────────────────────────────────
|
||||
const ttNativeBindingKey = '/node_modules/tt-native/binding.js'
|
||||
const ttNativePkgKey = '/node_modules/tt-native/package.json'
|
||||
// After unmount, keys may be relative (no leading slash) or with slash depending on bare-pack.
|
||||
// Resolve the actual key used in the bundle for a given path suffix.
|
||||
const bundleKeys = typeof bundle.keys === 'function' ? [...bundle.keys()] : Object.keys(bundle.files || {})
|
||||
function resolveKey(pathSuffix) {
|
||||
const normalized = pathSuffix.replace(/^\/+/, '').replace(/\\/g, '/')
|
||||
const withSlash = '/' + normalized
|
||||
if (bundleKeys.includes(withSlash)) return withSlash
|
||||
if (bundleKeys.includes(normalized)) return normalized
|
||||
return withSlash // default to slash form for writes
|
||||
}
|
||||
function readKey(k) {
|
||||
let b = bundle.read(k)
|
||||
if (b !== null) return b
|
||||
const alt = k.startsWith('/') ? k.slice(1) : '/' + k.replace(/^\/+/, '')
|
||||
return bundle.read(alt)
|
||||
}
|
||||
|
||||
if (bundle.read(ttNativeBindingKey) !== null) {
|
||||
// ── Fix 1: tt-native addon ──────────────────────────────────────────────────
|
||||
const ttNativeBindingKey = resolveKey('node_modules/tt-native/binding.js')
|
||||
const ttNativePkgKey = resolveKey('node_modules/tt-native/package.json')
|
||||
|
||||
if (readKey(ttNativeBindingKey) !== null) {
|
||||
// Build host-specific resolution map so the runtime picks the correct prebuild
|
||||
// per platform (addon → bare → node → platform → arch). Same format as
|
||||
// bare-pack/bare-module-traverse so require.addon() resolves on Linux, etc.
|
||||
const addonResolutions = { addon: { bare: { node: {} } } }
|
||||
|
||||
for (const host of hosts) {
|
||||
const prebuiltKey = `/node_modules/tt-native/prebuilds/${host}/tt-native.bare`
|
||||
const diskPath = path.join(NATIVE_HOST_DIR, prebuiltKey.slice(1))
|
||||
const prebuiltKey = resolveKey(`node_modules/tt-native/prebuilds/${host}/tt-native.bare`)
|
||||
const diskPath = path.join(NATIVE_HOST_DIR, prebuiltKey.replace(/^\/+/, '').replace(/\//g, path.sep))
|
||||
|
||||
if (!fs.existsSync(diskPath)) continue
|
||||
|
||||
bundle.write(prebuiltKey, fs.readFileSync(diskPath), { addon: true })
|
||||
const prebuildData = fs.readFileSync(diskPath)
|
||||
bundle.write(prebuiltKey, prebuildData, { addon: true })
|
||||
// On Windows the runtime may look up addon paths with backslashes; write the same
|
||||
// addon under the backslash key so require.addon() can find it.
|
||||
if (host.startsWith('win32')) {
|
||||
const winKey = prebuiltKey.replace(/\//g, '\\')
|
||||
if (winKey !== prebuiltKey) bundle.write(winKey, prebuildData, { addon: true })
|
||||
}
|
||||
|
||||
const [platform, arch] = host.split('-')
|
||||
if (!addonResolutions.addon.bare.node[platform]) addonResolutions.addon.bare.node[platform] = {}
|
||||
addonResolutions.addon.bare.node[platform][arch] = prebuiltKey
|
||||
// On Windows the runtime looks up addon paths with backslashes; store the key
|
||||
// we wrote so the runtime finds the addon.
|
||||
const resolutionKey = host.startsWith('win32') ? prebuiltKey.replace(/\//g, '\\') : prebuiltKey
|
||||
addonResolutions.addon.bare.node[platform][arch] = resolutionKey
|
||||
}
|
||||
|
||||
if (Object.keys(addonResolutions.addon.bare.node).length > 0) {
|
||||
@@ -183,24 +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.
|
||||
// Write to both key shapes (with and without leading slash) so the runtime finds
|
||||
// it regardless of how the bundle protocol normalizes keys after unmount.
|
||||
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.slice(1), pkgContent)
|
||||
bundle.write(ttNativePkgKey.startsWith('/') ? ttNativePkgKey.slice(1) : '/' + ttNativePkgKey, pkgContent)
|
||||
}
|
||||
console.log(' Patched tt-native binding (host-specific resolutions)')
|
||||
}
|
||||
}
|
||||
|
||||
// ── Fix 2b: bunyan runtime detection ────────────────────────────────────────
|
||||
// bunyan checks process.versions.node to detect Node.js. Bare doesn't set
|
||||
// this, so bunyan falls through to the browser branch and tries window.location.
|
||||
// Fix: patch bunyan.js to treat Bare as a node-like environment.
|
||||
const bunyanKey = '/node_modules/bunyan/lib/bunyan.js'
|
||||
const bunyanSrc = bundle.read(bunyanKey)
|
||||
const bunyanKey = resolveKey('node_modules/bunyan/lib/bunyan.js')
|
||||
const bunyanSrc = readKey(bunyanKey)
|
||||
if (bunyanSrc !== null) {
|
||||
let src = bunyanSrc.toString()
|
||||
// Insert a Bare-compatibility shim right before the runtimeEnv detection block.
|
||||
@@ -213,9 +235,9 @@ function patchBundle(bundle, hosts) {
|
||||
|
||||
// ── Fix 2: node-rdpjs-2 EventEmitter compatibility ──────────────────────────
|
||||
// Find the events module key in the bundle (it's the bare-node-events wrapper)
|
||||
const eventsKey = '/node_modules/events/index.js'
|
||||
const eventsKey = resolveKey('node_modules/events/index.js')
|
||||
|
||||
if (bundle.read(eventsKey) !== null) {
|
||||
if (readKey(eventsKey) !== null) {
|
||||
// Replace with a shim that makes EventEmitter callable as a plain function.
|
||||
// util.inherits does: SuperCtor.call(this) — which fails on ES6 classes.
|
||||
// The shim wraps the class in a function so both `new EventEmitter()` and
|
||||
@@ -258,6 +280,33 @@ module.exports = EventEmitter;
|
||||
console.log(' Patched events module for node-rdpjs-2 compatibility')
|
||||
}
|
||||
|
||||
// ── 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.
|
||||
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)
|
||||
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) {
|
||||
const diskPath = path.join(NATIVE_HOST_DIR, key.replace(/^\/+/, '').replace(/\//g, path.sep))
|
||||
if (fs.existsSync(diskPath)) {
|
||||
content = fs.readFileSync(diskPath)
|
||||
bundle.write(key, content)
|
||||
jsonFixed++
|
||||
}
|
||||
}
|
||||
if (hasWin32 && content && content.length > 0) {
|
||||
const winKey = key.replace(/\//g, '\\')
|
||||
if (winKey !== key) bundle.write(winKey, content)
|
||||
}
|
||||
}
|
||||
if (jsonFixed > 0) console.log(` Patched ${jsonFixed} empty/invalid .json entries`)
|
||||
if (hasWin32 && keysToProcess.some((k) => k.endsWith('.json'))) console.log(' Added Windows backslash path variants for .json entries')
|
||||
}
|
||||
|
||||
async function build(hosts, doPackage) {
|
||||
|
||||
Reference in New Issue
Block a user