catalyst-core 0.2.0-beta.3 → 0.3.0-beta.1
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/babel.native.config.cjs +8 -0
- package/bin/catalyst.js +49 -105
- package/changelog.md +8 -0
- package/dist/caching.js +1 -1
- package/dist/index.jsx +8 -0
- package/dist/logger.js +74 -3
- package/dist/native/androidSetup.js +300 -8
- package/dist/native/bridge/WebBridge.js +481 -59
- package/dist/native/bridge/constants/NativeInterfaces.js +290 -45
- package/dist/native/bridge/errors.js +250 -26
- package/dist/native/bridge/hooks/index.js +125 -1
- package/dist/native/bridge/hooks/useCamera.js +347 -9
- package/dist/native/bridge/hooks/useDataProtection.js +200 -2
- package/dist/native/bridge/hooks/useDeviceInfo.js +71 -2
- package/dist/native/bridge/hooks/useFilePicker.js +429 -2
- package/dist/native/bridge/hooks/useGoogleSignIn.js +81 -1
- package/dist/native/bridge/hooks/useHapticFeedback.js +196 -1
- package/dist/native/bridge/hooks/useIntent.js +95 -1
- package/dist/native/bridge/hooks/useNativeTransition.js +202 -27
- package/dist/native/bridge/hooks/useNetworkStatus.js +84 -3
- package/dist/native/bridge/hooks/useNotification.js +318 -2
- package/dist/native/bridge/hooks/useSafeArea.js +84 -2
- package/dist/native/bridge/hooks/useVideoStream.js +434 -6
- package/dist/native/bridge/hooks/utils.js +27 -1
- package/dist/native/bridge/hooks.js +16 -1
- package/dist/native/bridge/perf/collectors/ApiCollector.js +66 -3
- package/dist/native/bridge/perf/collectors/CacheCollector.js +186 -11
- package/dist/native/bridge/perf/collectors/HookCollector.js +141 -19
- package/dist/native/bridge/perf/collectors/InsightsCollector.js +481 -23
- package/dist/native/bridge/perf/collectors/InteractionCollector.js +245 -10
- package/dist/native/bridge/perf/collectors/KeyboardCollector.js +107 -8
- package/dist/native/bridge/perf/collectors/NavigationCollector.js +273 -32
- package/dist/native/bridge/perf/collectors/NetworkTimingCollector.js +178 -2
- package/dist/native/bridge/perf/collectors/RenderCollector.js +258 -14
- package/dist/native/bridge/perf/collectors/ScrollCollector.js +95 -9
- package/dist/native/bridge/perf/collectors/ThreadCollector.js +90 -6
- package/dist/native/bridge/perf/core/constants.js +103 -20
- package/dist/native/bridge/perf/core/measure.js +179 -30
- package/dist/native/bridge/perf/core/session.js +89 -23
- package/dist/native/bridge/perf/core/store.js +554 -1
- package/dist/native/bridge/perf/core/summary.js +174 -1
- package/dist/native/bridge/perf/core/traceExport.js +240 -1
- package/dist/native/bridge/perf/core/waterfalls.js +146 -1
- package/dist/native/bridge/perf/index.js +359 -38
- package/dist/native/bridge/safeArea.js +53 -5
- package/dist/native/bridge/standardizedHooks.js +595 -82
- package/dist/native/bridge/useBaseHook.js +274 -38
- package/dist/native/bridge/utils/CameraUtils.js +201 -56
- package/dist/native/bridge/utils/FileObjectConverter.js +129 -18
- package/dist/native/bridge/utils/NativeBridge.js +425 -141
- package/dist/native/buildAndroid/assets.js +510 -13
- package/dist/native/buildAndroid/build.js +296 -19
- package/dist/native/buildAndroid/config.js +87 -1
- package/dist/native/buildAndroid/index.js +374 -1
- package/dist/native/buildAppAndroid.js +34 -2
- package/dist/native/buildAppIos.js +62 -2
- package/dist/native/buildIos/assets.js +609 -8
- package/dist/native/buildIos/build.js +639 -20
- package/dist/native/buildIos/config.js +294 -12
- package/dist/native/buildIos/index.js +343 -6
- package/dist/native/buildIos/plugins.js +343 -16
- package/dist/native/internal-plugins/device-info-plugin/android/DeviceInfoPlugin.kt +43 -0
- package/dist/native/internal-plugins/device-info-plugin/ios/DeviceInfoPlugin.swift +28 -0
- package/dist/native/internal-plugins/device-info-plugin/manifest.json +19 -0
- package/dist/native/internalPluginUtils.js +232 -7
- package/dist/native/package.json +3 -0
- package/dist/native/plugin-bridge/PluginBridge.js +227 -1
- package/dist/native/pluginComposerAndroid.js +407 -23
- package/dist/native/pluginComposerIos.js +435 -11
- package/dist/native/renameAndroidProject.js +1094 -88
- package/dist/native/setupEmulatorIos.js +289 -22
- package/dist/native/setupServer.js +160 -19
- package/dist/native/terminalProgress.js +199 -11
- package/dist/native/utils.js +193 -15
- package/dist/offline/catalyst-sw.js +145 -1
- package/dist/offline/registerServiceWorker.js +33 -1
- package/dist/otel.js +375 -46
- package/dist/router/ClientRouter.js +14 -2
- package/dist/router/ServerRouter.js +9 -1
- package/dist/router.js +1 -1
- package/dist/scripts/build.js +112 -3
- package/dist/scripts/checkVersion.js +3 -1
- package/dist/scripts/cleanCache.js +30 -1
- package/dist/scripts/generateOfflineManifest.js +116 -1
- package/dist/scripts/loadEnvironmentVariables.js +32 -6
- package/dist/scripts/plugins.js +309 -1
- package/dist/scripts/preServerInit.js +13 -0
- package/dist/scripts/scriptUtils.js +54 -3
- package/dist/scripts/serve.js +51 -4
- package/dist/scripts/start.js +47 -10
- package/dist/scripts/validator.js +149 -1
- package/dist/sentry.cjs +127 -0
- package/dist/sentry.js +125 -5
- package/dist/server/expressServer.js +250 -5
- package/dist/server/manifestCache.js +36 -0
- package/dist/server/renderer/ChunkExtractor.js +144 -0
- package/dist/server/renderer/document/Body.jsx +59 -0
- package/dist/server/renderer/document/FastRefresh.jsx +20 -0
- package/dist/server/renderer/document/Head.jsx +60 -0
- package/dist/server/renderer/document/index.jsx +2 -0
- package/dist/server/renderer/extract.js +149 -31
- package/dist/server/renderer/handler.jsx +433 -0
- package/dist/server/renderer/index.js +8 -1
- package/dist/server/renderer/render.js +47 -0
- package/dist/server/utils/botDetectionMiddleware.js +29 -0
- package/dist/server/utils/cjsRequire.js +10 -0
- package/dist/server/utils/userAgentUtil.js +87 -9
- package/dist/server/utils/validator.js +164 -1
- package/dist/vite/FastRefresh.jsx +20 -0
- package/dist/vite/inject-cache-key-plugin.js +276 -0
- package/dist/vite/loadCustomViteConfig.js +22 -0
- package/dist/vite/manifest-categorization-plugin.js +455 -0
- package/dist/vite/node-loader.mjs +458 -0
- package/dist/vite/scssParams.js +21 -0
- package/dist/vite/vite.config.client.js +130 -0
- package/dist/vite/vite.config.js +422 -0
- package/dist/vite/vite.config.server.js +84 -0
- package/dist/web-router/components/MetaTag.jsx +34 -0
- package/dist/web-router/components/RouterDataProvider.jsx +332 -0
- package/dist/web-router/components/Split.jsx +200 -0
- package/dist/web-router/components/SplitInview.jsx +106 -0
- package/dist/web-router/components/SsrRequestContext.jsx +14 -0
- package/dist/web-router/context.jsx +12 -0
- package/dist/web-router/hooks.jsx +72 -0
- package/dist/web-router/types/components/MetaTag.d.ts +2 -0
- package/dist/web-router/types/components/RouterDataProvider.d.ts +95 -0
- package/dist/web-router/types/context.d.ts +14 -0
- package/dist/web-router/types/hooks.d.ts +1 -0
- package/dist/web-router/types/index.d.ts +3 -0
- package/dist/web-router/types/utils/metaDataUtils.d.ts +24 -0
- package/dist/web-router/utils/metaDataUtils.jsx +119 -0
- package/mcp_v2/conversion-tasks.json +35 -17
- package/mcp_v2/knowledge-base.json +124 -13
- package/mcp_v2/lib/helpers.js +10 -0
- package/mcp_v2/mcp.js +4 -4
- package/mcp_v2/package.json +1 -0
- package/mcp_v2/tools/build.js +116 -20
- package/mcp_v2/tools/conversion.js +106 -5
- package/mcp_v2/tools/tasks.js +18 -14
- package/package.json +35 -68
- package/babel.config.js +0 -32
- package/dist/index.js +0 -1
- package/dist/scripts/devBuild.js +0 -3
- package/dist/scripts/devServe.js +0 -3
- package/dist/scripts/loadScriptsBeforeServerStarts.js +0 -4
- package/dist/scripts/registerAliases.js +0 -6
- package/dist/server/renderer/document/Body.js +0 -11
- package/dist/server/renderer/document/Head.js +0 -9
- package/dist/server/renderer/document/index.js +0 -1
- package/dist/server/renderer/handler.js +0 -47
- package/dist/server/startServer.js +0 -57
- package/dist/webpack/babel-plugins/remove-client.plugin.js +0 -5
- package/dist/webpack/babel-plugins/remove-ssr.plugin.js +0 -5
- package/dist/webpack/babel.config.client.js +0 -1
- package/dist/webpack/babel.config.ssr.js +0 -1
- package/dist/webpack/base.babel.js +0 -7
- package/dist/webpack/development.client.babel.js +0 -10
- package/dist/webpack/production.client.babel.js +0 -4
- package/dist/webpack/production.ssr.babel.js +0 -8
- package/dist/webpack/scssParams.js +0 -9
|
@@ -1,4 +1,23 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _measure = require("./core/measure.js");
|
|
8
|
+
var _store = require("./core/store.js");
|
|
9
|
+
var _NavigationCollector = require("./collectors/NavigationCollector.js");
|
|
10
|
+
var _ScrollCollector = require("./collectors/ScrollCollector.js");
|
|
11
|
+
var _KeyboardCollector = require("./collectors/KeyboardCollector.js");
|
|
12
|
+
var _RenderCollector = require("./collectors/RenderCollector.js");
|
|
13
|
+
var _CacheCollector = require("./collectors/CacheCollector.js");
|
|
14
|
+
var _HookCollector = require("./collectors/HookCollector.js");
|
|
15
|
+
var _InteractionCollector = require("./collectors/InteractionCollector.js");
|
|
16
|
+
var _InsightsCollector = require("./collectors/InsightsCollector.js");
|
|
17
|
+
var _ThreadCollector = require("./collectors/ThreadCollector.js");
|
|
18
|
+
var _ApiCollector = require("./collectors/ApiCollector.js");
|
|
19
|
+
var _NetworkTimingCollector = require("./collectors/NetworkTimingCollector.js");
|
|
20
|
+
/**
|
|
2
21
|
* perf/index.js — WebPerfCollector
|
|
3
22
|
*
|
|
4
23
|
* Thin orchestrator. Responsibilities:
|
|
@@ -42,40 +61,342 @@
|
|
|
42
61
|
* CacheCollector.cache-summary → InsightsCollector.notifyCacheSummary
|
|
43
62
|
* All collectors → InsightsCollector (reactive warnings + session summary)
|
|
44
63
|
* All high-level collector outputs → PerfStore for waterfalls/tables/export
|
|
45
|
-
*/
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
this.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
this.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
this.
|
|
61
|
-
this.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
this.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
//
|
|
75
|
-
this.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
class WebPerfCollector {
|
|
67
|
+
constructor() {
|
|
68
|
+
// Align native timestamps (SystemClock.elapsedRealtime) to performance.now() space.
|
|
69
|
+
// Read lazily on each call — __NATIVE_TIME_OFFSET is injected via evaluateJavascript
|
|
70
|
+
// in onPageStarted which may not have executed yet when this constructor runs.
|
|
71
|
+
const nativeToWeb = nativeMs => nativeMs - (window.__NATIVE_TIME_OFFSET ?? 0);
|
|
72
|
+
this._nativeToWeb = nativeToWeb;
|
|
73
|
+
|
|
74
|
+
// ── Shared core ────────────────────────────────────────────────────────
|
|
75
|
+
const measure = new _measure.Measure();
|
|
76
|
+
this._store = new _store.PerfStore(nativeToWeb);
|
|
77
|
+
|
|
78
|
+
// ── Collectors ─────────────────────────────────────────────────────────
|
|
79
|
+
this._nav = new _NavigationCollector.NavigationCollector(measure, nativeToWeb);
|
|
80
|
+
this._scroll = new _ScrollCollector.ScrollCollector(measure, nativeToWeb);
|
|
81
|
+
this._keyboard = new _KeyboardCollector.KeyboardCollector(measure, nativeToWeb);
|
|
82
|
+
this._render = new _RenderCollector.RenderCollector(measure, () => this._sessionContext(), nativeToWeb);
|
|
83
|
+
this._cache = new _CacheCollector.CacheCollector(measure, nativeToWeb);
|
|
84
|
+
this._hook = new _HookCollector.HookCollector(measure);
|
|
85
|
+
this._interaction = new _InteractionCollector.InteractionCollector(measure);
|
|
86
|
+
this._insights = new _InsightsCollector.InsightsCollector(measure);
|
|
87
|
+
this._thread = new _ThreadCollector.ThreadCollector(measure, nativeToWeb);
|
|
88
|
+
this._api = new _ApiCollector.ApiCollector(measure, nativeToWeb);
|
|
89
|
+
this._networkTiming = new _NetworkTimingCollector.NetworkTimingCollector(measure);
|
|
90
|
+
|
|
91
|
+
// ── Cross-collector wiring ─────────────────────────────────────────────
|
|
92
|
+
|
|
93
|
+
// LoAF → ScrollCollector + HookCollector
|
|
94
|
+
this._render.addLoafListener((start, end) => this._scroll.onLoaf(start, end));
|
|
95
|
+
this._render.addLoafListener((start, end) => this._hook.onLoaf(start, end));
|
|
96
|
+
|
|
97
|
+
// LoAF during navigation → Insights
|
|
98
|
+
this._render.addLoafListener((start, end) => {
|
|
99
|
+
if (this._nav.isLoading) {
|
|
100
|
+
this._insights.notifyLoafDuringNav({
|
|
101
|
+
durationMs: end - start,
|
|
102
|
+
startTime: start,
|
|
103
|
+
endTime: end
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Interaction session → RenderCollector
|
|
109
|
+
this._render.setInteractionSource(() => this._interaction);
|
|
110
|
+
this._networkTiming.setInteractionSource(() => this._interaction);
|
|
111
|
+
this._api.setInteractionSource(() => this._interaction);
|
|
112
|
+
|
|
113
|
+
// Normalized store feed for waterfalls, tables, export, and future DevTools UI.
|
|
114
|
+
this._nav.setWaterfallSource(data => this._store.recordNavigation(data));
|
|
115
|
+
this._interaction.setWaterfallSource(data => this._store.recordInteraction(data));
|
|
116
|
+
this._networkTiming.setWaterfallSource(data => this._store.recordNetwork(data));
|
|
117
|
+
this._api.setWaterfallSource(data => this._store.recordNativeApi(data));
|
|
118
|
+
this._render.setWaterfallSource(data => this._store.recordRender(data));
|
|
119
|
+
this._hook.setWaterfallSource(data => this._store.recordHook(data));
|
|
120
|
+
this._scroll.setWaterfallSource(data => this._store.recordScroll(data));
|
|
121
|
+
this._keyboard.setWaterfallSource(data => this._store.recordKeyboard(data));
|
|
122
|
+
|
|
123
|
+
// Interaction → Insights (slow tap-to-paint)
|
|
124
|
+
this._interaction.setInsightsSource(data => this._insights.notifySlowInteraction(data));
|
|
125
|
+
|
|
126
|
+
// Render → Insights (layout shift + memory)
|
|
127
|
+
this._render.setInsightsSource(data => {
|
|
128
|
+
if (data.currentMb != null) this._insights.notifyHighMemory(data);else this._insights.notifyLayoutShift(data);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Thread → Insights (hw-accel disabled during dropped frame)
|
|
132
|
+
this._thread.setInsightsSource(data => this._insights.notifyHwAccelDuringFrame(data));
|
|
133
|
+
|
|
134
|
+
// Cache summary → Insights (low hit rate)
|
|
135
|
+
this._cache.setInsightsSource(data => this._insights.notifyCacheSummary(data));
|
|
136
|
+
|
|
137
|
+
// Scroll jank → Insights
|
|
138
|
+
this._scroll.setInsightsSource(data => this._insights.notifyScrollJank(data));
|
|
139
|
+
|
|
140
|
+
// Insights → normalized store
|
|
141
|
+
this._insights.setStoreSource(data => {
|
|
142
|
+
this._store.recordInsight(data);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
static init(bridge) {
|
|
146
|
+
if (window.__catalystPerfCollector) return;
|
|
147
|
+
const collector = new WebPerfCollector();
|
|
148
|
+
window.__catalystPerfCollector = collector;
|
|
149
|
+
collector._setup(bridge);
|
|
150
|
+
console.log("[CatalystPerf] active — nativeOffset:", window.__NATIVE_TIME_OFFSET ?? 0, "ms");
|
|
151
|
+
}
|
|
152
|
+
_setup(bridge) {
|
|
153
|
+
this._store.expose();
|
|
154
|
+
|
|
155
|
+
// Native → web event receiver (called directly by Kotlin via evaluateJavascript)
|
|
156
|
+
window.__catalystPerfEvent = jsonOrString => {
|
|
157
|
+
try {
|
|
158
|
+
const event = typeof jsonOrString === "string" ? JSON.parse(jsonOrString) : jsonOrString;
|
|
159
|
+
this._routeNativeEvent(event);
|
|
160
|
+
} catch (e) {
|
|
161
|
+
console.warn("[CatalystPerf] Bad native event payload:", jsonOrString, e);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// Native batch flush receiver — called by Kotlin after onPageFinished + 250ms delay.
|
|
166
|
+
// Drains via requestIdleCallback so web render is not blocked.
|
|
167
|
+
window.__catalystPerfBatch = (batchId, jsonArrayString) => {
|
|
168
|
+
if (jsonArrayString == null) {
|
|
169
|
+
jsonArrayString = batchId;
|
|
170
|
+
batchId = null;
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
console.log("[CatalystPerf] __catalystPerfBatch received, length=", typeof jsonArrayString === "string" ? jsonArrayString.length : "?");
|
|
174
|
+
const events = typeof jsonArrayString === "string" ? JSON.parse(jsonArrayString) : jsonArrayString;
|
|
175
|
+
if (!Array.isArray(events) || events.length === 0) {
|
|
176
|
+
console.warn("[CatalystPerf] __catalystPerfBatch — empty or invalid array");
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
if (batchId) {
|
|
180
|
+
this._acceptedBatchIds ??= new Set();
|
|
181
|
+
if (this._acceptedBatchIds.has(batchId)) return true;
|
|
182
|
+
this._acceptedBatchIds.add(batchId);
|
|
183
|
+
if (this._acceptedBatchIds.size > 100) {
|
|
184
|
+
this._acceptedBatchIds.delete(this._acceptedBatchIds.values().next().value);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const typeSummary = events.reduce((acc, e) => {
|
|
188
|
+
acc[e.type] = (acc[e.type] || 0) + 1;
|
|
189
|
+
return acc;
|
|
190
|
+
}, {});
|
|
191
|
+
console.log("[CatalystPerf] __catalystPerfBatch events:", events.length, JSON.stringify(typeSummary));
|
|
192
|
+
this._drainBatch(events);
|
|
193
|
+
return true;
|
|
194
|
+
} catch (e) {
|
|
195
|
+
console.warn("[CatalystPerf] Bad batch payload:", e);
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
// WebBridge fallback registration (for frameworks that route via bridge callbacks)
|
|
201
|
+
if (bridge) {
|
|
202
|
+
bridge.register("CATALYST_PERF_EVENT", data => {
|
|
203
|
+
window.__catalystPerfEvent(data);
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Initialise all collectors
|
|
208
|
+
this._nav.init();
|
|
209
|
+
this._scroll.init();
|
|
210
|
+
this._keyboard.init();
|
|
211
|
+
this._render.init();
|
|
212
|
+
this._cache.init();
|
|
213
|
+
this._hook.init();
|
|
214
|
+
this._interaction.init();
|
|
215
|
+
this._insights.init();
|
|
216
|
+
this._thread.init();
|
|
217
|
+
this._api.init();
|
|
218
|
+
this._networkTiming.init();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ─── Native batch drain ───────────────────────────────────────────────────
|
|
222
|
+
// Processes buffered native events (boot timing, cache, api-call) via
|
|
223
|
+
// requestIdleCallback so the web thread stays free for rendering.
|
|
224
|
+
|
|
225
|
+
_drainBatch(events) {
|
|
226
|
+
let index = 0;
|
|
227
|
+
const CHUNK = 20; // process up to 20 events per idle slice
|
|
228
|
+
|
|
229
|
+
const processChunk = deadline => {
|
|
230
|
+
let processed = 0;
|
|
231
|
+
while (index < events.length && processed < CHUNK) {
|
|
232
|
+
if (deadline && deadline.timeRemaining() < 1) break;
|
|
233
|
+
this._routeBatchEvent(events[index++]);
|
|
234
|
+
processed++;
|
|
235
|
+
}
|
|
236
|
+
if (index < events.length) {
|
|
237
|
+
if (typeof requestIdleCallback === "function") {
|
|
238
|
+
requestIdleCallback(processChunk, {
|
|
239
|
+
timeout: 2000
|
|
240
|
+
});
|
|
241
|
+
} else {
|
|
242
|
+
// Fallback: setTimeout for environments without rIC
|
|
243
|
+
setTimeout(() => processChunk(null), 0);
|
|
244
|
+
}
|
|
245
|
+
} else {
|
|
246
|
+
console.log(`[CatalystPerf] batch drained — ${events.length} events`);
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
if (typeof requestIdleCallback === "function") {
|
|
250
|
+
requestIdleCallback(processChunk, {
|
|
251
|
+
timeout: 2000
|
|
252
|
+
});
|
|
253
|
+
} else {
|
|
254
|
+
setTimeout(() => processChunk(null), 0);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
_routeBatchEvent(event) {
|
|
258
|
+
const {
|
|
259
|
+
type
|
|
260
|
+
} = event;
|
|
261
|
+
this._store.recordNativeEvent(event, "native-batch");
|
|
262
|
+
if (type === "page-load-start" || type === "page-load-error") {
|
|
263
|
+
this._nav.onNativeEvent(event);
|
|
264
|
+
} else if (type === "page-load-end") {
|
|
265
|
+
this._nav.onNativeEvent(event);
|
|
266
|
+
if (event.durationMs != null) {
|
|
267
|
+
this._insights.notifySlowLoad({
|
|
268
|
+
url: event.url,
|
|
269
|
+
durationMs: event.durationMs,
|
|
270
|
+
...this._nativeRange(event)
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
} else if (type?.startsWith("boot-")) {
|
|
274
|
+
this._nav.onBatchEvent(event);
|
|
275
|
+
} else if (type?.startsWith("cache-") || type === "network-fetch-complete") {
|
|
276
|
+
console.log("[CatalystPerf] routing cache event:", type, event.url?.slice(-40));
|
|
277
|
+
this._cache.onBatchEvent(event);
|
|
278
|
+
} else if (type === "cache-summary") {
|
|
279
|
+
console.log("[CatalystPerf] routing cache-summary:", JSON.stringify(event));
|
|
280
|
+
this._cache.onBatchEvent(event);
|
|
281
|
+
} else if (type === "api-call") {
|
|
282
|
+
this._api.onBatchEvent(event);
|
|
283
|
+
} else if (type === "cold-start") {
|
|
284
|
+
this._nav.onNativeEvent(event);
|
|
285
|
+
this._insights.notifyColdStart({
|
|
286
|
+
durationMs: event.durationMs,
|
|
287
|
+
...this._nativeRange(event)
|
|
288
|
+
});
|
|
289
|
+
} else {
|
|
290
|
+
// Unknown batch event — silently ignore (may be from future native additions)
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// ─── Native event router ──────────────────────────────────────────────────
|
|
295
|
+
|
|
296
|
+
_routeNativeEvent(event) {
|
|
297
|
+
this._store.recordNativeEvent(event, "native-live");
|
|
298
|
+
switch (event.type) {
|
|
299
|
+
case "keyboard-show":
|
|
300
|
+
this._keyboard.onKeyboardShow(event);
|
|
301
|
+
break;
|
|
302
|
+
case "keyboard-hide":
|
|
303
|
+
this._keyboard.onKeyboardHide(event);
|
|
304
|
+
break;
|
|
305
|
+
case "cache-hit-memory":
|
|
306
|
+
case "cache-hit-disk":
|
|
307
|
+
case "cache-miss-fetch":
|
|
308
|
+
case "network-fetch-complete":
|
|
309
|
+
// Legacy live path — only reached if buffer flush is disabled.
|
|
310
|
+
// In normal operation, cache events go via __catalystPerfBatch.
|
|
311
|
+
this._cache.onNativeEvent(event);
|
|
312
|
+
break;
|
|
313
|
+
case "page-load-start":
|
|
314
|
+
case "page-load-error":
|
|
315
|
+
this._nav.onNativeEvent(event);
|
|
316
|
+
break;
|
|
317
|
+
case "page-load-end":
|
|
318
|
+
{
|
|
319
|
+
this._nav.onNativeEvent(event);
|
|
320
|
+
if (event.durationMs != null) {
|
|
321
|
+
this._insights.notifySlowLoad({
|
|
322
|
+
url: event.url,
|
|
323
|
+
durationMs: event.durationMs,
|
|
324
|
+
...this._nativeRange(event)
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
case "cold-start":
|
|
330
|
+
this._nav.onNativeEvent(event);
|
|
331
|
+
this._insights.notifyColdStart({
|
|
332
|
+
durationMs: event.durationMs,
|
|
333
|
+
...this._nativeRange(event)
|
|
334
|
+
});
|
|
335
|
+
break;
|
|
336
|
+
case "fps-drop-episode":
|
|
337
|
+
{
|
|
338
|
+
const source = this._render.onNativeEvent(event);
|
|
339
|
+
// Option B: feed fps-drop into scroll session if one is open
|
|
340
|
+
if (this._scroll._session.isOpen) {
|
|
341
|
+
this._scroll.onFpsDrop(event);
|
|
342
|
+
}
|
|
343
|
+
this._insights.notifyFpsDrop({
|
|
344
|
+
minFps: event.minFps,
|
|
345
|
+
avgFps: event.avgFps,
|
|
346
|
+
durationMs: event.durationMs,
|
|
347
|
+
duringInteraction: source?.interactionId != null,
|
|
348
|
+
deltaFps: event.deltaFps ?? null,
|
|
349
|
+
baselineFps: event.baselineFps ?? null,
|
|
350
|
+
interactionId: source?.interactionId ?? null,
|
|
351
|
+
startTime: source?.startTime,
|
|
352
|
+
endTime: source?.endTime
|
|
353
|
+
});
|
|
354
|
+
break;
|
|
355
|
+
}
|
|
356
|
+
case "long-task":
|
|
357
|
+
this._render.onNativeEvent(event);
|
|
358
|
+
break;
|
|
359
|
+
case "memory-snapshot":
|
|
360
|
+
this._render.onNativeEvent(event);
|
|
361
|
+
// Insights notified from RenderCollector via setInsightsSource (uses nativeMb)
|
|
362
|
+
break;
|
|
363
|
+
case "scroll-start":
|
|
364
|
+
this._scroll.onScrollStart(event);
|
|
365
|
+
break;
|
|
366
|
+
case "scroll-end":
|
|
367
|
+
this._scroll.onScrollEnd(event);
|
|
368
|
+
break;
|
|
369
|
+
case "hw-accel-change":
|
|
370
|
+
this._thread.onNativeEvent(event);
|
|
371
|
+
break;
|
|
372
|
+
case "navigation-back":
|
|
373
|
+
// Emit via NavigationCollector as a point-in-time batch-style event
|
|
374
|
+
this._nav.onBatchEvent(event);
|
|
375
|
+
break;
|
|
376
|
+
default:
|
|
377
|
+
console.warn("[CatalystPerf] Unknown native event type:", event.type);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
_nativeRange(event) {
|
|
381
|
+
const nativeEnd = event.nativeTime ?? event.nativeEndMs ?? event.endNativeTime;
|
|
382
|
+
if (!Number.isFinite(nativeEnd)) return {};
|
|
383
|
+
const endTime = this._nativeToWeb(nativeEnd);
|
|
384
|
+
const durationMs = Number.isFinite(event.durationMs) ? event.durationMs : 1;
|
|
385
|
+
return {
|
|
386
|
+
startTime: Math.max(0, endTime - durationMs),
|
|
387
|
+
endTime
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// ─── Session context helper ───────────────────────────────────────────────
|
|
392
|
+
// Used by RenderCollector to tag LoAF and layout-shift entries with the
|
|
393
|
+
// active session so you can see in DevTools which phase a bad frame belongs to.
|
|
394
|
+
|
|
395
|
+
_sessionContext() {
|
|
396
|
+
if (this._nav.isLoading) return "navigation";
|
|
397
|
+
if (this._scroll._session.isOpen) return "scroll";
|
|
398
|
+
if (this._keyboard._session.isOpen) return "keyboard";
|
|
399
|
+
return "none";
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
var _default = exports.default = WebPerfCollector;
|
|
@@ -1,5 +1,53 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.setSafeAreaGlobal = exports.getSafeAreaFromGlobal = exports.getSafeArea = exports.DEFAULT_INSETS = void 0;
|
|
7
|
+
const DEFAULT_INSETS = exports.DEFAULT_INSETS = {
|
|
8
|
+
top: 0,
|
|
9
|
+
right: 0,
|
|
10
|
+
bottom: 0,
|
|
11
|
+
left: 0
|
|
12
|
+
};
|
|
13
|
+
const coerceNumber = value => {
|
|
14
|
+
const numeric = Number(value);
|
|
15
|
+
// Ensure non-negative values
|
|
16
|
+
return Number.isFinite(numeric) && numeric >= 0 ? numeric : 0;
|
|
17
|
+
};
|
|
18
|
+
const normalizeInsets = input => {
|
|
19
|
+
if (!input || typeof input !== "object") {
|
|
20
|
+
return {
|
|
21
|
+
...DEFAULT_INSETS
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
top: coerceNumber(input.top),
|
|
26
|
+
right: coerceNumber(input.right),
|
|
27
|
+
bottom: coerceNumber(input.bottom),
|
|
28
|
+
left: coerceNumber(input.left)
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
const getSafeAreaFromGlobal = () => {
|
|
32
|
+
// Use window on client, globalThis on server (SSR)
|
|
33
|
+
// eslint-disable-next-line no-undef
|
|
34
|
+
const global = typeof window !== "undefined" ? window : globalThis;
|
|
35
|
+
const value = global.__SAFE_AREA_INITIAL__;
|
|
36
|
+
if (!value) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
return normalizeInsets(value);
|
|
40
|
+
};
|
|
41
|
+
exports.getSafeAreaFromGlobal = getSafeAreaFromGlobal;
|
|
42
|
+
const setSafeAreaGlobal = insets => {
|
|
43
|
+
// eslint-disable-next-line no-undef
|
|
44
|
+
const global = typeof window !== "undefined" ? window : globalThis;
|
|
45
|
+
const normalized = normalizeInsets(insets);
|
|
46
|
+
global.__SAFE_AREA_INITIAL__ = normalized;
|
|
47
|
+
return normalized;
|
|
48
|
+
};
|
|
49
|
+
exports.setSafeAreaGlobal = setSafeAreaGlobal;
|
|
50
|
+
const getSafeArea = () => getSafeAreaFromGlobal() || {
|
|
51
|
+
...DEFAULT_INSETS
|
|
52
|
+
};
|
|
53
|
+
exports.getSafeArea = getSafeArea;
|