fix(build,denoise): gate node leak, postMessage origin, fail-hard patch, CDN dedup (N124/N125/N128/N120)
- N124: denoise shim cleanup() now disconnects the noise gate AudioWorkletNode (var-scoped, guarded), releasing the gate processor thread instead of leaking it on every getUserMedia within a session. - N125: denoise-status postMessage now targets the parent origin (derived from the parentUrl widget param via new URL(...).origin, falling back to this frame's origin) instead of broadcasting with '*'. - N128: patch-folds.mjs fails hard (process.exit(1)) when the patch target is missing, so an unpatched folds can't silently ship. The idempotent "already applied" path still exits 0 (verified by re-run). - N120: the avatar-decoration CDN URL is now single-sourced in avatarDecorations.ts (DECORATION_CDN); syncDecorations.mjs extracts it by regex (can't import across the build/app boundary) and fails hard if renamed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+19
-2
@@ -30,6 +30,17 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Derive the parent origin for postMessage targetOrigin from the parentUrl
|
||||||
|
// widget param (a full URL) so denoise-status messages aren't broadcast with
|
||||||
|
// '*'. Fall back to this frame's own origin if parentUrl is missing/malformed.
|
||||||
|
var targetOrigin;
|
||||||
|
try {
|
||||||
|
var parentUrl = params.get('parentUrl');
|
||||||
|
targetOrigin = parentUrl ? new URL(parentUrl).origin : window.location.origin;
|
||||||
|
} catch (e) {
|
||||||
|
targetOrigin = window.location.origin;
|
||||||
|
}
|
||||||
|
|
||||||
var md = navigator.mediaDevices;
|
var md = navigator.mediaDevices;
|
||||||
if (!md || typeof md.getUserMedia !== 'function') return;
|
if (!md || typeof md.getUserMedia !== 'function') return;
|
||||||
if (typeof AudioWorkletNode === 'undefined' || typeof AudioContext === 'undefined') return;
|
if (typeof AudioWorkletNode === 'undefined' || typeof AudioContext === 'undefined') return;
|
||||||
@@ -274,6 +285,9 @@
|
|||||||
source.disconnect();
|
source.disconnect();
|
||||||
mlNode.disconnect();
|
mlNode.disconnect();
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
try {
|
||||||
|
if (gateNode) gateNode.disconnect();
|
||||||
|
} catch (e) {}
|
||||||
try {
|
try {
|
||||||
origTrack.stop();
|
origTrack.stop();
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
@@ -301,7 +315,7 @@
|
|||||||
nativeNS: USE_NATIVE_NS,
|
nativeNS: USE_NATIVE_NS,
|
||||||
gate: USE_GATE,
|
gate: USE_GATE,
|
||||||
},
|
},
|
||||||
'*',
|
targetOrigin,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,7 +330,10 @@
|
|||||||
.catch(function (e) {
|
.catch(function (e) {
|
||||||
var msg = e instanceof Error ? e.message : String(e);
|
var msg = e instanceof Error ? e.message : String(e);
|
||||||
console.error('[lotus-denoise] Setup failed:', msg);
|
console.error('[lotus-denoise] Setup failed:', msg);
|
||||||
window.parent.postMessage({ type: 'lotus-denoise-status', active: false, error: msg }, '*');
|
window.parent.postMessage(
|
||||||
|
{ type: 'lotus-denoise-status', active: false, error: msg },
|
||||||
|
targetOrigin,
|
||||||
|
);
|
||||||
return stream;
|
return stream;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-2
@@ -19,8 +19,17 @@ try {
|
|||||||
writeFileSync(foldsPath, content, 'utf8');
|
writeFileSync(foldsPath, content, 'utf8');
|
||||||
console.log('Applied defensive Icon src guard to folds.');
|
console.log('Applied defensive Icon src guard to folds.');
|
||||||
} else {
|
} else {
|
||||||
console.warn('Warning: folds Icon patch target not found - may need updating.');
|
// Genuine "patch could not be applied" case: the target string is gone
|
||||||
|
// (folds renamed/restructured it) AND it isn't already patched. Fail hard
|
||||||
|
// so the postinstall hook / CI breaks loudly instead of silently shipping
|
||||||
|
// an unpatched folds (which crashes at render with "src is not a function").
|
||||||
|
console.error(
|
||||||
|
'ERROR: folds Icon patch target not found - folds may have updated. ' +
|
||||||
|
'Update the patch target string in scripts/patch-folds.mjs before building.',
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn('Warning: Could not patch folds:', e.message);
|
console.error('ERROR: Could not patch folds:', e.message);
|
||||||
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,25 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|||||||
const root = join(__dirname, '..');
|
const root = join(__dirname, '..');
|
||||||
const catalogPath = join(root, 'src', 'app', 'features', 'lotus', 'avatarDecorations.ts');
|
const catalogPath = join(root, 'src', 'app', 'features', 'lotus', 'avatarDecorations.ts');
|
||||||
|
|
||||||
const CDN = 'https://drive.lotusguild.org/public.php/dav/files/bHswJ9pNKp2t26N/cinny-decorations';
|
// Single source of truth: the CDN base URL lives in avatarDecorations.ts as
|
||||||
|
// `export const DECORATION_CDN`. We extract it from there at runtime rather than
|
||||||
|
// re-declaring it here, so the build script and the app can never drift. This
|
||||||
|
// .mjs script can't cleanly import the browser-side .ts module (it's outside the
|
||||||
|
// Vite/TS app graph), so we parse the constant out of the file text instead.
|
||||||
|
// If you migrate the CDN, change it ONLY in avatarDecorations.ts.
|
||||||
|
const catalog = readFileSync(catalogPath, 'utf8');
|
||||||
|
|
||||||
|
const cdnMatch = catalog.match(/export const DECORATION_CDN\s*=\s*['"]([^'"]+)['"]/);
|
||||||
|
if (!cdnMatch) {
|
||||||
|
console.error(
|
||||||
|
'Could not find `export const DECORATION_CDN` in avatarDecorations.ts — ' +
|
||||||
|
'the constant may have been renamed. Update scripts/syncDecorations.mjs.',
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
const CDN = cdnMatch[1];
|
||||||
|
|
||||||
// Extract all slugs from the catalog file
|
// Extract all slugs from the catalog file
|
||||||
const catalog = readFileSync(catalogPath, 'utf8');
|
|
||||||
const slugMatches = [...catalog.matchAll(/slug: '([^']+)'/g)].map((m) => m[1]);
|
const slugMatches = [...catalog.matchAll(/slug: '([^']+)'/g)].map((m) => m[1]);
|
||||||
|
|
||||||
if (slugMatches.length === 0) {
|
if (slugMatches.length === 0) {
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
// Single source of truth for the avatar-decoration CDN base URL.
|
||||||
|
// scripts/syncDecorations.mjs reads this exact `DECORATION_CDN` declaration out
|
||||||
|
// of this file at runtime (by regex) instead of re-declaring it, so the two can
|
||||||
|
// never drift. If you migrate the CDN, change it here ONLY — keep the
|
||||||
|
// `export const DECORATION_CDN = '...'` shape so the sync script can still parse it.
|
||||||
export const DECORATION_CDN =
|
export const DECORATION_CDN =
|
||||||
'https://drive.lotusguild.org/public.php/dav/files/bHswJ9pNKp2t26N/cinny-decorations';
|
'https://drive.lotusguild.org/public.php/dav/files/bHswJ9pNKp2t26N/cinny-decorations';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user