modelstage 0.0.0-stage → 0.5.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +274 -2
- package/THIRD_PARTY_NOTICES.md +90 -0
- package/bin/modelstage.mjs +137 -0
- package/config/diag-upload.example.json +7 -0
- package/config/models/live2d.assetbundls.json +1 -0
- package/config/models/live2d.azurlane.json +1 -0
- package/config/models/live2d.azurlane_bundle.json +1 -0
- package/config/models/live2d.azurlane_spine.json +1 -0
- package/config/models/live2d.bd2.json +1 -0
- package/config/models/live2d.bluearchive.json +1 -0
- package/config/models/live2d.live2d.json +1 -0
- package/config/models/live2d.nikke.json +1 -0
- package/config/models/live2d.nikke_2.json +1 -0
- package/config/models/live2d.npc.json +1 -0
- package/config/models/spine.assetbundls.json +1 -0
- package/config/models/spine.azurlane.json +1 -0
- package/config/models/spine.azurlane_bundle.json +1 -0
- package/config/models/spine.azurlane_spine.json +1 -0
- package/config/models/spine.bd2.json +1 -0
- package/config/models/spine.bluearchive.json +1 -0
- package/config/models/spine.live2d.json +1 -0
- package/config/models/spine.nikke.json +1 -0
- package/config/models/spine.nikke_2.json +1 -0
- package/config/models/spine.npc.json +1 -0
- package/config/names/NIKKE.json +1058 -0
- package/config/names/README.md +47 -0
- package/config/names//345/244/251/345/221/275/344/271/213/345/255/220.json +42897 -0
- package/config/names//346/243/225/350/211/262/345/260/230/345/237/2032.json +4016 -0
- package/config/names//347/242/247/350/223/235/350/210/252/347/272/277.json +38342 -0
- package/config/plugins.json +13 -0
- package/config/resources.example.json +40 -0
- package/package.json +63 -4
- package/plugins/unity-live2d-bundle/README.md +98 -0
- package/plugins/unity-live2d-bundle/index.js +891 -0
- package/plugins/unity-live2d-bundle/lib/anim-to-motion.js +402 -0
- package/plugins/unity-live2d-bundle/lib/bundle-probe.js +244 -0
- package/plugins/unity-live2d-bundle/lib/bytes.js +189 -0
- package/plugins/unity-live2d-bundle/lib/common-strings.js +46 -0
- package/plugins/unity-live2d-bundle/lib/dxt.js +197 -0
- package/plugins/unity-live2d-bundle/lib/errors.js +71 -0
- package/plugins/unity-live2d-bundle/lib/etc2.js +371 -0
- package/plugins/unity-live2d-bundle/lib/extract.js +242 -0
- package/plugins/unity-live2d-bundle/lib/lzma-d-min.LICENSE.txt +21 -0
- package/plugins/unity-live2d-bundle/lib/lzma-d-min.js +34 -0
- package/plugins/unity-live2d-bundle/lib/model3.js +137 -0
- package/plugins/unity-live2d-bundle/lib/png.js +424 -0
- package/plugins/unity-live2d-bundle/lib/serialized.js +233 -0
- package/plugins/unity-live2d-bundle/lib/texdecode.js +190 -0
- package/plugins/unity-live2d-bundle/lib/typetree.js +215 -0
- package/plugins/unity-live2d-bundle/lib/unityfs.js +396 -0
- package/plugins/unity-live2d-bundle/plugin.json +81 -0
- package/plugins/unity-live2d-bundle/profiles/unityfs-live2d.json +26 -0
- package/plugins/unity-spine-bundle/index.js +535 -0
- package/plugins/unity-spine-bundle/lib/bytes.js +189 -0
- package/plugins/unity-spine-bundle/lib/common-strings.js +46 -0
- package/plugins/unity-spine-bundle/lib/dxt.js +197 -0
- package/plugins/unity-spine-bundle/lib/errors.js +79 -0
- package/plugins/unity-spine-bundle/lib/etc2.js +371 -0
- package/plugins/unity-spine-bundle/lib/extract.js +242 -0
- package/plugins/unity-spine-bundle/lib/lzma-d-min.LICENSE.txt +21 -0
- package/plugins/unity-spine-bundle/lib/lzma-d-min.js +34 -0
- package/plugins/unity-spine-bundle/lib/png.js +424 -0
- package/plugins/unity-spine-bundle/lib/serialized.js +233 -0
- package/plugins/unity-spine-bundle/lib/texdecode.js +190 -0
- package/plugins/unity-spine-bundle/lib/typetree.js +215 -0
- package/plugins/unity-spine-bundle/lib/unityfs.js +396 -0
- package/plugins/unity-spine-bundle/plugin.json +75 -0
- package/src/server/README.md +69 -0
- package/src/server/assets/browse.mjs +56 -0
- package/src/server/assets/bundle-probe.mjs +94 -0
- package/src/server/assets/probe.mjs +184 -0
- package/src/server/core/config.mjs +173 -0
- package/src/server/core/env-num.mjs +60 -0
- package/src/server/core/env.mjs +49 -0
- package/src/server/core/fs-portable.mjs +37 -0
- package/src/server/core/log.mjs +107 -0
- package/src/server/core/paths.mjs +44 -0
- package/src/server/data/catalog.mjs +1091 -0
- package/src/server/data/entry-states.mjs +499 -0
- package/src/server/data/live2d.mjs +272 -0
- package/src/server/data/manifest-cache.mjs +58 -0
- package/src/server/data/manifest-stamp.mjs +135 -0
- package/src/server/data/model-meta.mjs +114 -0
- package/src/server/data/names.mjs +106 -0
- package/src/server/data/shape-probe-worker.mjs +33 -0
- package/src/server/data/shape-probe.mjs +626 -0
- package/src/server/data/spine.mjs +336 -0
- package/src/server/data/tree.mjs +126 -0
- package/src/server/http/atomic-json.mjs +145 -0
- package/src/server/http/background-solids.mjs +270 -0
- package/src/server/http/backgrounds.mjs +388 -0
- package/src/server/http/diag-upload.mjs +264 -0
- package/src/server/http/diag.mjs +173 -0
- package/src/server/http/ready.mjs +167 -0
- package/src/server/http/static.mjs +312 -0
- package/src/server/http/write.mjs +654 -0
- package/src/server/index.mjs +114 -0
- package/src/server/plugins/builtin-providers.json +30 -0
- package/src/server/plugins/registry.mjs +650 -0
- package/src/server/plugins/slot-catalog.mjs +286 -0
- package/src/server/routes/background-solids.mjs +56 -0
- package/src/server/routes/backgrounds.mjs +77 -0
- package/src/server/routes/config.mjs +38 -0
- package/src/server/routes/data.mjs +313 -0
- package/src/server/routes/diag.mjs +37 -0
- package/src/server/routes/entries.mjs +170 -0
- package/src/server/routes/ready.mjs +122 -0
- package/src/server/serve.mjs +396 -0
- package/src/server/unpack/capacity.mjs +217 -0
- package/src/server/unpack/mem-probe.mjs +27 -0
- package/src/server/unpack/plugin-runner.mjs +529 -0
- package/src/server/unpack/plugin-store.mjs +736 -0
- package/src/server/unpack/probe-store.mjs +73 -0
- package/src/server/unpack/routes.mjs +359 -0
- package/src/server/unpack/runtime/exec.mjs +558 -0
- package/src/server/unpack/runtime/index.mjs +141 -0
- package/src/server/unpack/runtime/node-vm.mjs +111 -0
- package/src/server/unpack/unpack-worker.mjs +105 -0
- package/src/server/unpack/worker-client.mjs +184 -0
- package/src/server/unpack/write-result.mjs +84 -0
- package/src/shared/bundle-shape.mjs +83 -0
- package/src/shared/entry-reasons.mjs +119 -0
- package/src/shared/names.mjs +45 -0
- package/src/shared/type-labels.mjs +31 -0
- package/src/web/README.md +193 -0
- package/src/web/app/anim-list.js +222 -0
- package/src/web/app/background-solids.js +150 -0
- package/src/web/app/backgrounds.js +152 -0
- package/src/web/app/camera-log.js +28 -0
- package/src/web/app/context.js +72 -0
- package/src/web/app/dir-picker.js +242 -0
- package/src/web/app/entry-report.js +71 -0
- package/src/web/app/memory-bars.js +91 -0
- package/src/web/app/memory-budget.js +228 -0
- package/src/web/app/memory-guard.js +204 -0
- package/src/web/app/model-actions.js +682 -0
- package/src/web/app/renderer-setting.js +70 -0
- package/src/web/app/root-manager.js +254 -0
- package/src/web/app/status.js +138 -0
- package/src/web/app/topbar-actions.js +357 -0
- package/src/web/app/transport-actions.js +297 -0
- package/src/web/app/ui-state.js +559 -0
- package/src/web/app/url-params.js +171 -0
- package/src/web/app/view-settings.js +186 -0
- package/src/web/components.css +524 -0
- package/src/web/debug/diag-hud.js +95 -0
- package/src/web/debug/drag.js +369 -0
- package/src/web/debug/log.js +320 -0
- package/src/web/debug/model-cmp.js +292 -0
- package/src/web/debug/panel.css +474 -0
- package/src/web/debug/panel.js +712 -0
- package/src/web/debug/race-probe.js +82 -0
- package/src/web/debug/upload.js +130 -0
- package/src/web/engine/adapters/atlas.js +47 -0
- package/src/web/engine/adapters/index.js +22 -0
- package/src/web/engine/adapters/renderer.js +223 -0
- package/src/web/engine/adapters/skeleton.js +105 -0
- package/src/web/engine/adapters/texture.js +64 -0
- package/src/web/engine/animation.js +181 -0
- package/src/web/engine/appearance.js +136 -0
- package/src/web/engine/camera-adapter.js +212 -0
- package/src/web/engine/effect-chain.js +138 -0
- package/src/web/engine/engine-state.js +120 -0
- package/src/web/engine/filters.js +224 -0
- package/src/web/engine/fit.js +197 -0
- package/src/web/engine/frame-gate.js +33 -0
- package/src/web/engine/gl-driver.js +56 -0
- package/src/web/engine/gl.js +77 -0
- package/src/web/engine/index.js +20 -0
- package/src/web/engine/loader.js +55 -0
- package/src/web/engine/model-info.js +26 -0
- package/src/web/engine/pipeline.js +200 -0
- package/src/web/engine/player.js +427 -0
- package/src/web/engine/pma/blend.js +76 -0
- package/src/web/engine/pma/detect.js +118 -0
- package/src/web/engine/pma/index.js +8 -0
- package/src/web/engine/pma/resolve.js +112 -0
- package/src/web/engine/pma/upload.js +127 -0
- package/src/web/engine/pma.js +5 -0
- package/src/web/engine/render-frame.js +93 -0
- package/src/web/engine/runtime-capabilities.js +209 -0
- package/src/web/engine/runtime.js +37 -0
- package/src/web/engine/skins.js +165 -0
- package/src/web/engine/textures.js +174 -0
- package/src/web/index.html +117 -0
- package/src/web/infra/api.js +531 -0
- package/src/web/infra/diag.js +509 -0
- package/src/web/infra/document.js +269 -0
- package/src/web/infra/dom.js +31 -0
- package/src/web/infra/events.mjs +27 -0
- package/src/web/infra/log.js +153 -0
- package/src/web/infra/mem-stats.js +112 -0
- package/src/web/infra/plugin-host-registration.mjs +285 -0
- package/src/web/infra/plugin-host-report.mjs +32 -0
- package/src/web/infra/plugin-host-unload.mjs +79 -0
- package/src/web/infra/plugin-host-unpack.mjs +899 -0
- package/src/web/infra/plugin-host-warmup.mjs +180 -0
- package/src/web/infra/plugin-host.js +628 -0
- package/src/web/infra/ready.js +461 -0
- package/src/web/infra/schedule.js +51 -0
- package/src/web/infra/shortcuts.js +129 -0
- package/src/web/infra/slot-registry.js +402 -0
- package/src/web/infra/vfs.js +247 -0
- package/src/web/live2d/bridge.js +400 -0
- package/src/web/live2d/model.js +321 -0
- package/src/web/live2d/overlay.js +142 -0
- package/src/web/live2d/pixi-app.js +111 -0
- package/src/web/live2d/playback-probe.js +92 -0
- package/src/web/live2d/probe-geometry.js +329 -0
- package/src/web/live2d/probe.js +119 -0
- package/src/web/live2d/release.js +66 -0
- package/src/web/live2d/runtime-adapter.js +289 -0
- package/src/web/live2d/stage-ctx.js +152 -0
- package/src/web/live2d/stage.js +204 -0
- package/src/web/live2d/vfs-settings.js +174 -0
- package/src/web/live2d/view.js +89 -0
- package/src/web/main.js +629 -0
- package/src/web/panel/background-list.js +373 -0
- package/src/web/panel/bg-source.js +291 -0
- package/src/web/panel/color-picker.css +199 -0
- package/src/web/panel/color-picker.js +278 -0
- package/src/web/panel/dialog.css +116 -0
- package/src/web/panel/dialog.js +173 -0
- package/src/web/panel/dom.js +35 -0
- package/src/web/panel/icons.js +58 -0
- package/src/web/panel/memory-bar.js +195 -0
- package/src/web/panel/panel-settings.js +1263 -0
- package/src/web/panel/panel.css +1304 -0
- package/src/web/panel/render-choice.js +104 -0
- package/src/web/panel/schema.js +784 -0
- package/src/web/panel/settings-io.js +291 -0
- package/src/web/panel/shell-controls.js +274 -0
- package/src/web/panel/slider.js +210 -0
- package/src/web/panel/toolbar-schema.js +111 -0
- package/src/web/panel/toolbar.js +195 -0
- package/src/web/panel/transport-picker.js +375 -0
- package/src/web/panel/transport.js +321 -0
- package/src/web/panel/view.js +553 -0
- package/src/web/plugin/unpack-worker.js +185 -0
- package/src/web/render/camera/constants.js +60 -0
- package/src/web/render/camera/index.js +123 -0
- package/src/web/render/camera/spine.js +124 -0
- package/src/web/render/capture.js +30 -0
- package/src/web/render/interaction.js +527 -0
- package/src/web/render/live2d.js +627 -0
- package/src/web/render/playback.js +47 -0
- package/src/web/render/reset-view.js +29 -0
- package/src/web/render/spine.js +386 -0
- package/src/web/render/surface-switch.js +176 -0
- package/src/web/render/surface.js +571 -0
- package/src/web/render/surfaces.js +70 -0
- package/src/web/roster/filter.js +31 -0
- package/src/web/roster/list.js +276 -0
- package/src/web/roster/persist.js +92 -0
- package/src/web/roster/reveal.js +77 -0
- package/src/web/roster/rows.js +248 -0
- package/src/web/roster/snapshot.js +39 -0
- package/src/web/roster/type-filter.js +97 -0
- package/src/web/roster/view.js +761 -0
- package/src/web/spine/canvas-api-groups.js +267 -0
- package/src/web/spine/canvas-api.js +97 -0
- package/src/web/spine/canvas-document.js +80 -0
- package/src/web/spine/canvas-engine.js +193 -0
- package/src/web/spine/canvas-entry.js +28 -0
- package/src/web/spine/canvas-pixels.js +36 -0
- package/src/web/spine/canvas-runtime.js +127 -0
- package/src/web/spine/canvas-view.js +108 -0
- package/src/web/spine/canvas.js +7 -0
- package/src/web/spine/runtime-hint.js +73 -0
- package/src/web/spine/runtimes.js +212 -0
- package/src/web/style.css +493 -0
- package/tool/lib/bundle-probe-node.mjs +121 -0
- package/tool/lib/paths.mjs +20 -0
- package/tool/lib/runtime-guides.mjs +65 -0
- package/tool/lib/runtime-package.mjs +403 -0
- package/tool/lib/spine-meta.mjs +227 -0
- package/tool/lib/spine-motions.mjs +104 -0
- package/tool/parse-jsonc.mjs +86 -0
- package/tool/resolve-live2d-runtimes.mjs +276 -0
- package/tool/spine-motion-rules.json +101 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// app/memory-guard.js —— 内存保护(一个开关管三条路径)
|
|
2
|
+
//
|
|
3
|
+
// 与 ctl-hang-guard 的区别(别混):
|
|
4
|
+
// memoryGuard(本文件) = **内存容量**保护 → 防 OOM / 页面崩溃
|
|
5
|
+
// ctl-hang-guard = **帧停滞**看门狗 → 画面停住时尝试自愈
|
|
6
|
+
// 两者并列、互不替代。
|
|
7
|
+
//
|
|
8
|
+
// 三条路径:
|
|
9
|
+
// A 服务端解包准入:开关开=超预算拒绝(既有行为);关=请求带 allowOverLimit 强行解包。
|
|
10
|
+
// 判断全在服务端(capacity.mjs 读系统内存),前端不自己算阈值。
|
|
11
|
+
// B 前端加载前预检:jsHeap 占上限比例 > HEAP_RATIO 就拒绝并给出真实数字。
|
|
12
|
+
// C 长操作中监控:解包/批量加载期间按帧采样 jsHeap,超限即中止(已完成的文件保留)。
|
|
13
|
+
//
|
|
14
|
+
// 为什么数值必须取真值:只说"内存不足"用户无法判断该拆包还是该关标签页 ——
|
|
15
|
+
// 所以所有提示都带「当前 / 上限 / 百分比 / MB」。
|
|
16
|
+
|
|
17
|
+
import { memStats } from '../infra/mem-stats.js';
|
|
18
|
+
import { HEAP_RATIO, assess, buildMessage, setBudgetGuardEnabled } from './memory-budget.js';
|
|
19
|
+
|
|
20
|
+
export { HEAP_RATIO };
|
|
21
|
+
|
|
22
|
+
/** 操作中监控的采样间隔(帧)—— 每 20 帧约 1/3 秒,够快且不干扰渲染 */
|
|
23
|
+
export const MONITOR_FRAME_STRIDE = 20;
|
|
24
|
+
|
|
25
|
+
/** 开关状态(默认开:保持"服务端永远准入判断"的现状,关才放行) */
|
|
26
|
+
let enabled = true;
|
|
27
|
+
|
|
28
|
+
/** 最近一次判据读数(面板显示 + 断言都用它,避免各处各取一次导致数字对不上) */
|
|
29
|
+
let readout = { availMb: null, totalMb: null, peakEstMb: null, budgetMb: null, at: 0, error: '' };
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 设置开关(面板 ctl-memory-guard 变化时调用)。
|
|
33
|
+
* @param {boolean} on
|
|
34
|
+
* @returns {boolean} 生效后的值
|
|
35
|
+
*/
|
|
36
|
+
export function setMemoryGuard(on) {
|
|
37
|
+
enabled = on !== false;
|
|
38
|
+
setBudgetGuardEnabled(enabled); // 判据层与开关状态保持同步(它不 import 本文件,避免成环)
|
|
39
|
+
try { document.documentElement.dataset.memoryGuard = enabled ? 'on' : 'off'; } catch { /* 忽略 */ }
|
|
40
|
+
return enabled;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** @returns {boolean} 内存保护是否开启 */
|
|
44
|
+
export function isMemoryGuardOn() {
|
|
45
|
+
return enabled;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 读前端堆占用(真值来自 performance.memory,不可用时返回 null 而不是瞎估)。
|
|
50
|
+
* @returns {{usedMB:number|null, limitMB:number|null, pct:number|null}}
|
|
51
|
+
*/
|
|
52
|
+
export function heapSnapshot() {
|
|
53
|
+
const s = memStats();
|
|
54
|
+
return { usedMB: s.jsHeapMB, limitMB: s.jsHeapLimitMB, pct: s.jsHeapPct };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 路径 B:加载大模型前的预检。
|
|
59
|
+
*
|
|
60
|
+
* 判不了(浏览器不暴露 performance.memory,如 Firefox/Safari)就**放行** ——
|
|
61
|
+
* 拿不到真值时不假装保护,否则会变成"在部分浏览器上永远加载不了"。
|
|
62
|
+
* @param {string} what 要加载的东西(写进提示,便于用户知道是哪一步被拦)
|
|
63
|
+
* @returns {{ok: boolean, message?: string, usedMB?: number|null, limitMB?: number|null, pct?: number|null}}
|
|
64
|
+
*/
|
|
65
|
+
export async function preflightLoad(what) {
|
|
66
|
+
// 判断口径全部交给 memory-budget.assess(服务端容量 + 前端堆两路取更严格),
|
|
67
|
+
// 这里只负责把结果翻成调用方要的形状,不自己算任何阈值。
|
|
68
|
+
if (!enabled) return { ok: true };
|
|
69
|
+
const r = await assess({ where: 'web-load', label: what });
|
|
70
|
+
return { ok: r.ok, message: r.message, reason: r.reason, ...r.numbers };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 解包判据(供 plugin-host 在装载容器包前调用):包字节 → 预估峰值 vs 可用预算。
|
|
75
|
+
* 内部就是 assess({ where:'web-unpack' }),前端不算任何倍数。
|
|
76
|
+
* @param {string} label 对象名
|
|
77
|
+
* @param {number} bytes 包字节数
|
|
78
|
+
* @returns {Promise<{ok:boolean, reason:string, numbers:object, message:string}>}
|
|
79
|
+
*/
|
|
80
|
+
export function assessUnpack(label, bytes) {
|
|
81
|
+
if (!enabled) return Promise.resolve({ ok: true, reason: 'guard-off', numbers: {}, message: '' });
|
|
82
|
+
return assess({ where: 'web-unpack', label, bytesHint: bytes });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* 路径 C:长操作中的内存监控。
|
|
87
|
+
*
|
|
88
|
+
* 用法:
|
|
89
|
+
* const mon = startMemoryMonitor('解包');
|
|
90
|
+
* for (...) { await one(); if (mon.aborted()) break; } // 中止但保留已完成的部分
|
|
91
|
+
* mon.stop();
|
|
92
|
+
*
|
|
93
|
+
* 为什么按帧采样而不是 setInterval:跟着渲染循环走,页面不可见时自然降频,
|
|
94
|
+
* 不会在后台标签页里空转(符合《事件驱动优先》)。
|
|
95
|
+
* @param {string} label 操作名(写进日志与提示)
|
|
96
|
+
* @returns {{stop: () => void, aborted: () => boolean, reason: () => string, samples: () => number}}
|
|
97
|
+
*/
|
|
98
|
+
export function startMemoryMonitor(label) {
|
|
99
|
+
const state = { hit: false, why: '', n: 0, frames: 0 };
|
|
100
|
+
let raf = 0;
|
|
101
|
+
let cancelled = false;
|
|
102
|
+
|
|
103
|
+
/** 采一次样并判定(帧回调与同步检查共用这一处,避免两套判定漂移) */
|
|
104
|
+
const sample = () => {
|
|
105
|
+
if (state.hit || cancelled) return;
|
|
106
|
+
state.n += 1;
|
|
107
|
+
const h = heapSnapshot();
|
|
108
|
+
if (!enabled || h.pct === null || h.pct <= HEAP_RATIO) return;
|
|
109
|
+
state.hit = true;
|
|
110
|
+
// 文案走统一模板(三处同一套格式),不再各处手拼
|
|
111
|
+
state.why = buildMessage({
|
|
112
|
+
where: 'web-long-op',
|
|
113
|
+
label: String(label).trim(),
|
|
114
|
+
serverFails: false,
|
|
115
|
+
heapFails: true,
|
|
116
|
+
serverDetail: '',
|
|
117
|
+
numbers: { heapPct: h.pct, usedMB: h.usedMB, limitMB: h.limitMB },
|
|
118
|
+
});
|
|
119
|
+
try { document.documentElement.dataset.memGuardAbort = label; } catch { /* 忽略 */ }
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const tick = () => {
|
|
123
|
+
if (cancelled || state.hit) return;
|
|
124
|
+
state.frames += 1;
|
|
125
|
+
// 首帧就采一次,之后每 MONITOR_FRAME_STRIDE 帧一次。
|
|
126
|
+
// 原来只在 %STRIDE===0 时采 ⇒ "几帧内跑完"的短操作等于没有监控
|
|
127
|
+
// (实测:取 19 个小文件一帧都没跨过,监控从未触发)。
|
|
128
|
+
if (state.frames === 1 || state.frames % MONITOR_FRAME_STRIDE === 0) sample();
|
|
129
|
+
if (state.hit) return;
|
|
130
|
+
raf = requestAnimationFrame(tick);
|
|
131
|
+
};
|
|
132
|
+
if (typeof requestAnimationFrame === 'function') raf = requestAnimationFrame(tick);
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
stop: () => { cancelled = true; try { cancelAnimationFrame(raf); } catch { /* 忽略 */ } },
|
|
136
|
+
aborted: () => state.hit,
|
|
137
|
+
reason: () => state.why,
|
|
138
|
+
samples: () => state.n,
|
|
139
|
+
/**
|
|
140
|
+
* 同步采样一次,返回是否已越线。
|
|
141
|
+
*
|
|
142
|
+
* 为什么需要:按帧采样对"密集但总时长短"的循环无能为力 —— 取 19 个小文件可能一帧都没跨过,
|
|
143
|
+
* 那时监控等于不存在。调用方在每步开始前调它,就能在"还没排到下一帧"时也发现越线。
|
|
144
|
+
*/
|
|
145
|
+
checkNow: () => { sample(); return state.hit; },
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* 刷新判据读数(面板「内存判据」那行显示的真实值)。
|
|
151
|
+
*
|
|
152
|
+
* 数值来源必须是服务端的 /api/unpack/capacity(由它读系统内存),
|
|
153
|
+
* 前端不许自己拍脑袋算"大概够不够"。
|
|
154
|
+
* @param {{rootId?: string, rel?: string}} [target] 给了就带上该包的需求估算
|
|
155
|
+
* @returns {Promise<object>} 服务端返回的判据(失败时返回 {error})
|
|
156
|
+
*/
|
|
157
|
+
export async function refreshMemoryReadout(target) {
|
|
158
|
+
const qs = target && target.rootId && target.rel
|
|
159
|
+
? `?rootId=${encodeURIComponent(target.rootId)}&rel=${encodeURIComponent(target.rel)}`
|
|
160
|
+
: '';
|
|
161
|
+
try {
|
|
162
|
+
const res = await fetch(`/api/unpack/capacity${qs}`, {
|
|
163
|
+
headers: { Accept: 'application/json' },
|
|
164
|
+
signal: AbortSignal.timeout(2000),
|
|
165
|
+
});
|
|
166
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
167
|
+
const j = await res.json();
|
|
168
|
+
readout = {
|
|
169
|
+
availMb: Number.isFinite(j.memAvailableMb) ? j.memAvailableMb : null,
|
|
170
|
+
totalMb: Number.isFinite(j.memTotalMb) ? j.memTotalMb : null,
|
|
171
|
+
peakEstMb: Number.isFinite(j.peakEstMb) ? j.peakEstMb : null,
|
|
172
|
+
budgetMb: Number.isFinite(j.budgetMb) ? j.budgetMb : null,
|
|
173
|
+
at: Date.now(),
|
|
174
|
+
error: '',
|
|
175
|
+
};
|
|
176
|
+
return { ...j, readout };
|
|
177
|
+
} catch (err) {
|
|
178
|
+
readout = { ...readout, at: Date.now(), error: String((err && err.message) || err) };
|
|
179
|
+
return { error: readout.error, readout };
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** 最近一次读数(断言用) */
|
|
184
|
+
export function memoryReadout() {
|
|
185
|
+
return { ...readout };
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/** 供测试/断言的整体快照 */
|
|
189
|
+
export function memGuardSnapshot() {
|
|
190
|
+
return {
|
|
191
|
+
enabled,
|
|
192
|
+
heapRatio: HEAP_RATIO,
|
|
193
|
+
heap: heapSnapshot(),
|
|
194
|
+
readout: memoryReadout(),
|
|
195
|
+
abortedLabel: (() => { try { return document.documentElement.dataset.memGuardAbort || ''; } catch { return ''; } })(),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** 供测试重置(仅测试用) */
|
|
200
|
+
export function __resetMemoryGuardForTest() {
|
|
201
|
+
enabled = true;
|
|
202
|
+
readout = { availMb: null, totalMb: null, peakEstMb: null, budgetMb: null, at: 0, error: '' };
|
|
203
|
+
try { delete document.documentElement.dataset.memGuardAbort; } catch { /* 忽略 */ }
|
|
204
|
+
}
|