@absolutejs/absolute 0.20.0-beta.72 → 0.20.0-beta.73
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/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/cli/{dev-rbvkxpj7.js → dev-p7s1ej32.js} +224 -1
- package/dist/cli/index.js +1 -1
- package/dist/dev/importCostPreload.js +206 -0
- package/dist/dev/importCostReport.js +730 -0
- package/dist/dev/serverBootstrap.js +60 -11
- package/dist/index.js +19 -1
- package/dist/index.js.map +4 -4
- package/dist/src/dev/earlyListener.d.ts +32 -0
- package/dist/src/dev/importCost/deferability.d.ts +11 -0
- package/dist/src/dev/importCost/dominators.d.ts +37 -0
- package/dist/src/dev/importCost/format.d.ts +29 -0
- package/dist/src/dev/importCost/instrument.d.ts +5 -0
- package/dist/src/dev/importCost/moduleGraph.d.ts +13 -0
- package/dist/src/dev/importCost/recorder.d.ts +37 -0
- package/dist/src/dev/importCost/report.d.ts +3 -0
- package/dist/src/dev/importCost/scope.d.ts +10 -0
- package/dist/src/dev/importCost/selfTimes.d.ts +17 -0
- package/dist/src/dev/importCostPreload.d.ts +1 -0
- package/dist/src/dev/importCostReport.d.ts +1 -0
- package/dist/types/globals.d.ts +15 -0
- package/package.json +7 -7
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
var __require = import.meta.require;
|
|
3
3
|
|
|
4
|
-
// .angular-partial-tmp-
|
|
4
|
+
// .angular-partial-tmp-GauEbM/src/core/streamingSlotRegistrar.ts
|
|
5
5
|
var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
|
|
6
6
|
var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
|
|
7
7
|
var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
var __require = import.meta.require;
|
|
3
3
|
|
|
4
|
-
// .angular-partial-tmp-
|
|
4
|
+
// .angular-partial-tmp-GauEbM/src/core/streamingSlotRegistrar.ts
|
|
5
5
|
var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
|
|
6
6
|
var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
|
|
7
7
|
var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
|
|
@@ -48,7 +48,7 @@ var warnMissingStreamingSlotCollector = (primitiveName) => {
|
|
|
48
48
|
getWarningController()?.maybeWarn(primitiveName);
|
|
49
49
|
};
|
|
50
50
|
|
|
51
|
-
// .angular-partial-tmp-
|
|
51
|
+
// .angular-partial-tmp-GauEbM/src/core/streamingSlotRegistry.ts
|
|
52
52
|
var STREAMING_SLOT_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotAsyncLocalStorage");
|
|
53
53
|
var isObjectRecord2 = (value) => Boolean(value) && typeof value === "object";
|
|
54
54
|
var isAsyncLocalStorage = (value) => isObjectRecord2(value) && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function";
|
|
@@ -786,6 +786,160 @@ var createDevPrescan = (config, projectRoot = process.cwd()) => {
|
|
|
786
786
|
};
|
|
787
787
|
};
|
|
788
788
|
|
|
789
|
+
// src/dev/importCost/recorder.ts
|
|
790
|
+
var IMPORT_COST_ENV = "ABSOLUTE_DEV_IMPORT_COST";
|
|
791
|
+
var importCostEnabled = () => process.env[IMPORT_COST_ENV] === "1";
|
|
792
|
+
|
|
793
|
+
// src/dev/bootLifecycle.ts
|
|
794
|
+
var getBootPhase = () => globalThis.__absoluteBootPhase;
|
|
795
|
+
|
|
796
|
+
// src/dev/earlyListener.ts
|
|
797
|
+
var HTTP_SERVICE_UNAVAILABLE = 503;
|
|
798
|
+
var RETRY_AFTER_SECONDS = 2;
|
|
799
|
+
var BIND_RETRY_INTERVAL_MS = 250;
|
|
800
|
+
var BIND_RETRY_LIMIT = 40;
|
|
801
|
+
var POLL_INTERVAL_MS = RETRY_AFTER_SECONDS * MILLISECONDS_IN_A_SECOND;
|
|
802
|
+
var NOSCRIPT_REFRESH_SECONDS = 10;
|
|
803
|
+
var BOOT_STATUS_HEADER = "X-Absolute-Boot";
|
|
804
|
+
var PARENT_HANDOFF_MARKER = "absolute:listening";
|
|
805
|
+
var PARENT_LISTENER_ENV = "ABSOLUTE_PARENT_LISTENER";
|
|
806
|
+
var bindingPlaceholder = false;
|
|
807
|
+
var escapeHtml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """);
|
|
808
|
+
var bootStatusSnapshot = (startedAt) => {
|
|
809
|
+
const elapsedMs = Math.max(0, Date.now() - startedAt);
|
|
810
|
+
return {
|
|
811
|
+
elapsedMs,
|
|
812
|
+
elapsedSeconds: Math.floor(elapsedMs / MILLISECONDS_IN_A_SECOND),
|
|
813
|
+
phase: getBootPhase() ?? "starting",
|
|
814
|
+
status: "building"
|
|
815
|
+
};
|
|
816
|
+
};
|
|
817
|
+
var buildingPage = (snapshot) => `<!doctype html>
|
|
818
|
+
<html lang="en">
|
|
819
|
+
<head>
|
|
820
|
+
<meta charset="utf-8">
|
|
821
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
822
|
+
<meta http-equiv="refresh" content="${NOSCRIPT_REFRESH_SECONDS}">
|
|
823
|
+
<title>Building\u2026</title>
|
|
824
|
+
<style>
|
|
825
|
+
:root{color-scheme:light dark}
|
|
826
|
+
body{margin:0;min-height:100vh;display:grid;place-items:center;font:15px/1.5 system-ui,-apple-system,"Segoe UI",sans-serif;background:#0f1115;color:#e6e8ee}
|
|
827
|
+
main{text-align:center;padding:2rem}
|
|
828
|
+
.spin{width:36px;height:36px;margin:0 auto 1rem;border:3px solid rgba(255,255,255,.15);border-top-color:#8ab4ff;border-radius:50%;animation:s 1s linear infinite}
|
|
829
|
+
@keyframes s{to{transform:rotate(360deg)}}
|
|
830
|
+
h1{font-size:1.15rem;font-weight:600;margin:0 0 .25rem}
|
|
831
|
+
p{margin:0;opacity:.6;font-size:.85rem}
|
|
832
|
+
code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
|
|
833
|
+
</style>
|
|
834
|
+
</head>
|
|
835
|
+
<body>
|
|
836
|
+
<main>
|
|
837
|
+
<div class="spin" aria-hidden="true"></div>
|
|
838
|
+
<h1>Building\u2026 <span id="t">${snapshot.elapsedSeconds}</span>s</h1>
|
|
839
|
+
<p>AbsoluteJS dev server \xB7 <code id="p">${escapeHtml(snapshot.phase)}</code></p>
|
|
840
|
+
</main>
|
|
841
|
+
<script>
|
|
842
|
+
(function(){
|
|
843
|
+
var started=Date.now()-${snapshot.elapsedMs};
|
|
844
|
+
var t=document.getElementById('t');
|
|
845
|
+
setInterval(function(){t.textContent=String(Math.floor((Date.now()-started)/1000));},1000);
|
|
846
|
+
function poll(){
|
|
847
|
+
fetch(location.href,{cache:'no-store',headers:{accept:'application/json'}}).then(function(r){
|
|
848
|
+
if(r.headers.get('${BOOT_STATUS_HEADER.toLowerCase()}')!=='building'){location.reload();return;}
|
|
849
|
+
return r.json().then(function(j){if(j&&j.phase){document.getElementById('p').textContent=j.phase;}});
|
|
850
|
+
}).catch(function(){}).then(function(){setTimeout(poll,${POLL_INTERVAL_MS});});
|
|
851
|
+
}
|
|
852
|
+
setTimeout(poll,${POLL_INTERVAL_MS});
|
|
853
|
+
})();
|
|
854
|
+
</script>
|
|
855
|
+
</body>
|
|
856
|
+
</html>
|
|
857
|
+
`;
|
|
858
|
+
var buildingResponse = (request, startedAt) => {
|
|
859
|
+
const snapshot = bootStatusSnapshot(startedAt);
|
|
860
|
+
const headers = {
|
|
861
|
+
"Cache-Control": "no-store",
|
|
862
|
+
"Retry-After": String(RETRY_AFTER_SECONDS),
|
|
863
|
+
"X-Absolute-Boot": "building"
|
|
864
|
+
};
|
|
865
|
+
const isUpgrade = request.headers.get("upgrade")?.toLowerCase() === "websocket";
|
|
866
|
+
const accept = request.headers.get("accept") ?? "";
|
|
867
|
+
if (!isUpgrade && accept.includes("text/html")) {
|
|
868
|
+
headers["Content-Type"] = "text/html; charset=utf-8";
|
|
869
|
+
return new Response(buildingPage(snapshot), {
|
|
870
|
+
headers,
|
|
871
|
+
status: HTTP_SERVICE_UNAVAILABLE
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
if (!isUpgrade && accept.includes("application/json")) {
|
|
875
|
+
headers["Content-Type"] = "application/json; charset=utf-8";
|
|
876
|
+
return new Response(JSON.stringify(snapshot), {
|
|
877
|
+
headers,
|
|
878
|
+
status: HTTP_SERVICE_UNAVAILABLE
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
headers["Content-Type"] = "text/plain; charset=utf-8";
|
|
882
|
+
return new Response(`AbsoluteJS dev server is building (${snapshot.elapsedSeconds}s, ${snapshot.phase}). Retry shortly.
|
|
883
|
+
`, { headers, status: HTTP_SERVICE_UNAVAILABLE });
|
|
884
|
+
};
|
|
885
|
+
var parentListenerSupported = () => process.platform !== "win32";
|
|
886
|
+
var startEarlyListener = (options) => {
|
|
887
|
+
const startedAt = Date.now();
|
|
888
|
+
let server = null;
|
|
889
|
+
let released = false;
|
|
890
|
+
let attempts = 0;
|
|
891
|
+
let retryTimer;
|
|
892
|
+
const tryBind = () => {
|
|
893
|
+
if (released)
|
|
894
|
+
return;
|
|
895
|
+
attempts += 1;
|
|
896
|
+
bindingPlaceholder = true;
|
|
897
|
+
try {
|
|
898
|
+
server = Bun.serve({
|
|
899
|
+
hostname: options.host,
|
|
900
|
+
port: options.port,
|
|
901
|
+
fetch: (request) => buildingResponse(request, startedAt),
|
|
902
|
+
...options.reusePort ? { reusePort: true } : {},
|
|
903
|
+
...options.tls ? { tls: options.tls } : {}
|
|
904
|
+
});
|
|
905
|
+
} catch {
|
|
906
|
+
if (attempts >= BIND_RETRY_LIMIT)
|
|
907
|
+
return;
|
|
908
|
+
retryTimer = setTimeout(tryBind, BIND_RETRY_INTERVAL_MS);
|
|
909
|
+
retryTimer.unref();
|
|
910
|
+
} finally {
|
|
911
|
+
bindingPlaceholder = false;
|
|
912
|
+
}
|
|
913
|
+
};
|
|
914
|
+
const release = () => {
|
|
915
|
+
if (released)
|
|
916
|
+
return;
|
|
917
|
+
released = true;
|
|
918
|
+
if (retryTimer)
|
|
919
|
+
clearTimeout(retryTimer);
|
|
920
|
+
const active = server;
|
|
921
|
+
server = null;
|
|
922
|
+
if (!active)
|
|
923
|
+
return;
|
|
924
|
+
try {
|
|
925
|
+
active.stop(true);
|
|
926
|
+
} catch {}
|
|
927
|
+
};
|
|
928
|
+
tryBind();
|
|
929
|
+
const listener = {
|
|
930
|
+
release,
|
|
931
|
+
startedAt,
|
|
932
|
+
get released() {
|
|
933
|
+
return released;
|
|
934
|
+
},
|
|
935
|
+
get server() {
|
|
936
|
+
return server;
|
|
937
|
+
}
|
|
938
|
+
};
|
|
939
|
+
globalThis.__absoluteEarlyListener = listener;
|
|
940
|
+
return listener;
|
|
941
|
+
};
|
|
942
|
+
|
|
789
943
|
// src/cli/interactive.ts
|
|
790
944
|
import { openSync } from "fs";
|
|
791
945
|
import { ReadStream } from "tty";
|
|
@@ -1198,6 +1352,8 @@ var RESTART_PARK_POLL_MS = 20;
|
|
|
1198
1352
|
var NODE_API_IMPORT_ERROR = "To load Node-API modules, use require() or process.dlopen instead of import.";
|
|
1199
1353
|
var sourceServerBootstrap = resolvePath(import.meta.dir, "../../dev/serverBootstrap.ts");
|
|
1200
1354
|
var serverBootstrap = existsSync4(sourceServerBootstrap) ? sourceServerBootstrap : resolvePath(import.meta.dir, "../dev/serverBootstrap.js");
|
|
1355
|
+
var sourceImportCostPreload = resolvePath(import.meta.dir, "../../dev/importCostPreload.ts");
|
|
1356
|
+
var importCostPreload = existsSync4(sourceImportCostPreload) ? sourceImportCostPreload : resolvePath(import.meta.dir, "../dev/importCostPreload.js");
|
|
1201
1357
|
var formatServerBootDiagnostic = (output, serverEntry) => {
|
|
1202
1358
|
if (!output.includes(NODE_API_IMPORT_ERROR))
|
|
1203
1359
|
return null;
|
|
@@ -1565,6 +1721,54 @@ var dev = async (serverEntry, configPath, options = {}) => {
|
|
|
1565
1721
|
}
|
|
1566
1722
|
markBoot("dev port resolved");
|
|
1567
1723
|
updateLockMetadata(buildDirectory, { port });
|
|
1724
|
+
const parentListenerAllowed = env.ABSOLUTE_EARLY_LISTEN !== "0" && parentListenerSupported();
|
|
1725
|
+
let parentListener = null;
|
|
1726
|
+
let parentListenerPort = null;
|
|
1727
|
+
let parentListenerTls;
|
|
1728
|
+
const releaseParentListener = () => {
|
|
1729
|
+
const listener = parentListener;
|
|
1730
|
+
parentListener = null;
|
|
1731
|
+
parentListenerPort = null;
|
|
1732
|
+
if (!listener)
|
|
1733
|
+
return;
|
|
1734
|
+
listener.release();
|
|
1735
|
+
if (globalThis.__absoluteEarlyListener === listener) {
|
|
1736
|
+
globalThis.__absoluteEarlyListener = undefined;
|
|
1737
|
+
}
|
|
1738
|
+
};
|
|
1739
|
+
const loadParentListenerTls = async () => {
|
|
1740
|
+
if (!httpsEnabled)
|
|
1741
|
+
return null;
|
|
1742
|
+
try {
|
|
1743
|
+
const { loadDevCert } = await import("./devCert-avr89zf3.js");
|
|
1744
|
+
return loadDevCert();
|
|
1745
|
+
} catch {
|
|
1746
|
+
return null;
|
|
1747
|
+
}
|
|
1748
|
+
};
|
|
1749
|
+
const ensureParentListener = async () => {
|
|
1750
|
+
if (!parentListenerAllowed)
|
|
1751
|
+
return;
|
|
1752
|
+
if (parentListener && parentListenerPort === port)
|
|
1753
|
+
return;
|
|
1754
|
+
releaseParentListener();
|
|
1755
|
+
parentListenerTls ??= await loadParentListenerTls();
|
|
1756
|
+
const listener = startEarlyListener({
|
|
1757
|
+
host: resolvedDev.host,
|
|
1758
|
+
port,
|
|
1759
|
+
reusePort: true,
|
|
1760
|
+
tls: parentListenerTls
|
|
1761
|
+
});
|
|
1762
|
+
if (!listener.server) {
|
|
1763
|
+
listener.release();
|
|
1764
|
+
globalThis.__absoluteEarlyListener = undefined;
|
|
1765
|
+
return;
|
|
1766
|
+
}
|
|
1767
|
+
parentListener = listener;
|
|
1768
|
+
parentListenerPort = port;
|
|
1769
|
+
markBoot("parent listener bound");
|
|
1770
|
+
};
|
|
1771
|
+
await ensureParentListener();
|
|
1568
1772
|
const instancePid = process.pid;
|
|
1569
1773
|
const instanceLogFile = instanceLogPath(instancePid);
|
|
1570
1774
|
const relaunchCommand = [
|
|
@@ -2080,6 +2284,7 @@ var dev = async (serverEntry, configPath, options = {}) => {
|
|
|
2080
2284
|
if (!chunk.includes("Local:"))
|
|
2081
2285
|
return;
|
|
2082
2286
|
serverReady = true;
|
|
2287
|
+
releaseParentListener();
|
|
2083
2288
|
startTunnelIfConfigured();
|
|
2084
2289
|
startAndroidDev();
|
|
2085
2290
|
startIosDev();
|
|
@@ -2200,8 +2405,12 @@ var dev = async (serverEntry, configPath, options = {}) => {
|
|
|
2200
2405
|
} catch {}
|
|
2201
2406
|
};
|
|
2202
2407
|
let prescan = prescanConfig ? createDevPrescan(prescanConfig) : null;
|
|
2408
|
+
let spawnGeneration = 0;
|
|
2203
2409
|
const spawnServer = async () => {
|
|
2410
|
+
spawnGeneration += 1;
|
|
2411
|
+
const generation = spawnGeneration;
|
|
2204
2412
|
await refreshDevConfigForSpawn();
|
|
2413
|
+
await ensureParentListener();
|
|
2205
2414
|
markBoot("dev child spawn requested");
|
|
2206
2415
|
const prescanForSpawn = prescan;
|
|
2207
2416
|
prescan = null;
|
|
@@ -2209,6 +2418,7 @@ var dev = async (serverEntry, configPath, options = {}) => {
|
|
|
2209
2418
|
"--hot",
|
|
2210
2419
|
"--no-clear-screen",
|
|
2211
2420
|
...heapSnapshotEnabled ? ["--preload", heapPreloadPath] : [],
|
|
2421
|
+
...importCostEnabled() ? ["--preload", importCostPreload] : [],
|
|
2212
2422
|
serverBootstrap
|
|
2213
2423
|
], {
|
|
2214
2424
|
cwd: process.cwd(),
|
|
@@ -2220,6 +2430,7 @@ var dev = async (serverEntry, configPath, options = {}) => {
|
|
|
2220
2430
|
ABSOLUTE_INSTANCE_MANAGED: "1",
|
|
2221
2431
|
ABSOLUTE_PORT: String(port),
|
|
2222
2432
|
ABSOLUTE_SERVER_ENTRY: resolvePath(serverEntry),
|
|
2433
|
+
...parentListener ? { [PARENT_LISTENER_ENV]: "1" } : {},
|
|
2223
2434
|
...bootTimelineChildEnv(),
|
|
2224
2435
|
...prescanForSpawn ? { ABSOLUTE_DEV_PRESCAN: prescanForSpawn.path } : {},
|
|
2225
2436
|
...options.eager ? { ABSOLUTE_DEV_EAGER: "1" } : {},
|
|
@@ -2230,9 +2441,20 @@ var dev = async (serverEntry, configPath, options = {}) => {
|
|
|
2230
2441
|
...configPath ? { ABSOLUTE_CONFIG: configPath } : {},
|
|
2231
2442
|
...httpsEnabled ? { ABSOLUTE_HTTPS: "true" } : {}
|
|
2232
2443
|
},
|
|
2233
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
2444
|
+
stdio: ["ignore", "pipe", "pipe", "pipe"]
|
|
2234
2445
|
});
|
|
2235
2446
|
prescanForSpawn?.start();
|
|
2447
|
+
const [, , , handoffPipe] = proc.stdio;
|
|
2448
|
+
if (handoffPipe && "on" in handoffPipe) {
|
|
2449
|
+
handoffPipe.on("data", (chunk) => {
|
|
2450
|
+
if (generation !== spawnGeneration)
|
|
2451
|
+
return;
|
|
2452
|
+
if (!chunk.toString().includes(PARENT_HANDOFF_MARKER))
|
|
2453
|
+
return;
|
|
2454
|
+
releaseParentListener();
|
|
2455
|
+
});
|
|
2456
|
+
handoffPipe.on("error", () => {});
|
|
2457
|
+
}
|
|
2236
2458
|
let printedBootDiagnostic = false;
|
|
2237
2459
|
const forward = (source, dest, sourceName) => {
|
|
2238
2460
|
if (!source)
|
|
@@ -2443,6 +2665,7 @@ var dev = async (serverEntry, configPath, options = {}) => {
|
|
|
2443
2665
|
});
|
|
2444
2666
|
if (interactive)
|
|
2445
2667
|
interactive.dispose();
|
|
2668
|
+
releaseParentListener();
|
|
2446
2669
|
tunnelClient?.close();
|
|
2447
2670
|
androidDevAbort.abort();
|
|
2448
2671
|
androidNativeWatcher?.close();
|
package/dist/cli/index.js
CHANGED
|
@@ -58,7 +58,7 @@ if (command === "dev") {
|
|
|
58
58
|
}
|
|
59
59
|
const positionalArgs = stripNamedArgs("--config", "--android-device", "--ios-device").filter((arg) => arg !== "--no-mobile" && arg !== "--eager");
|
|
60
60
|
const serverEntry = positionalArgs[0] ?? DEFAULT_SERVER_ENTRY;
|
|
61
|
-
const { dev } = await import("./dev-
|
|
61
|
+
const { dev } = await import("./dev-p7s1ej32.js");
|
|
62
62
|
await dev(serverEntry, configPath, {
|
|
63
63
|
androidDevice,
|
|
64
64
|
eager: args.includes("--eager"),
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/dev/importCostPreload.ts
|
|
3
|
+
import { existsSync, readFileSync as readFileSync2 } from "fs";
|
|
4
|
+
import { join as join2 } from "path";
|
|
5
|
+
var {plugin } = globalThis.Bun;
|
|
6
|
+
|
|
7
|
+
// src/dev/importCost/instrument.ts
|
|
8
|
+
var BYTE_ORDER_MARK = 65279;
|
|
9
|
+
var NOT_FOUND = -1;
|
|
10
|
+
var PROLOGUE_TOKEN = /\s+|\/\/[^\n]*|\/\*[\s\S]*?\*\/|(['"])use [^'"\n]*\1[ \t]*;?/y;
|
|
11
|
+
var prologueEnd = (source) => {
|
|
12
|
+
let index = source.charCodeAt(0) === BYTE_ORDER_MARK ? 1 : 0;
|
|
13
|
+
if (source.startsWith("#!", index)) {
|
|
14
|
+
const newline = source.indexOf(`
|
|
15
|
+
`, index);
|
|
16
|
+
index = newline === NOT_FOUND ? source.length : newline + 1;
|
|
17
|
+
}
|
|
18
|
+
for (;; ) {
|
|
19
|
+
PROLOGUE_TOKEN.lastIndex = index;
|
|
20
|
+
if (PROLOGUE_TOKEN.exec(source) === null)
|
|
21
|
+
return index;
|
|
22
|
+
index = PROLOGUE_TOKEN.lastIndex;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
var TYPESCRIPT_EXTENSION = /\.[cm]?ts$/;
|
|
26
|
+
var JS_LOADER = "js";
|
|
27
|
+
var JSX_LOADER = "jsx";
|
|
28
|
+
var TS_LOADER = "ts";
|
|
29
|
+
var TSX_LOADER = "tsx";
|
|
30
|
+
var importCostLoader = (path) => {
|
|
31
|
+
if (path.endsWith(".tsx"))
|
|
32
|
+
return TSX_LOADER;
|
|
33
|
+
if (path.endsWith(".jsx"))
|
|
34
|
+
return JSX_LOADER;
|
|
35
|
+
if (TYPESCRIPT_EXTENSION.test(path))
|
|
36
|
+
return TS_LOADER;
|
|
37
|
+
return JS_LOADER;
|
|
38
|
+
};
|
|
39
|
+
var instrumentModuleSource = (source, moduleIndex) => {
|
|
40
|
+
const insertAt = prologueEnd(source);
|
|
41
|
+
const enter = `globalThis.__absoluteImportCostEnter?.(${moduleIndex});`;
|
|
42
|
+
const exit = `
|
|
43
|
+
;globalThis.__absoluteImportCostExit?.(${moduleIndex});`;
|
|
44
|
+
return `${source.slice(0, insertAt)}${enter}${source.slice(insertAt)}${exit}`;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// src/dev/importCost/recorder.ts
|
|
48
|
+
var IMPORT_COST_EVENT = {
|
|
49
|
+
enter: 2,
|
|
50
|
+
exit: 3,
|
|
51
|
+
loadEnd: 1,
|
|
52
|
+
loadStart: 0
|
|
53
|
+
};
|
|
54
|
+
var IMPORT_COST_EVENT_KINDS = 4;
|
|
55
|
+
var ensureImportCostRecorder = () => {
|
|
56
|
+
const existing = globalThis.__absoluteImportCost;
|
|
57
|
+
if (existing !== undefined)
|
|
58
|
+
return existing;
|
|
59
|
+
const created = {
|
|
60
|
+
entryModule: null,
|
|
61
|
+
entryOriginalModule: null,
|
|
62
|
+
events: [],
|
|
63
|
+
moduleIds: [],
|
|
64
|
+
moduleIndexes: new Map,
|
|
65
|
+
recording: true,
|
|
66
|
+
rootModule: null
|
|
67
|
+
};
|
|
68
|
+
globalThis.__absoluteImportCost = created;
|
|
69
|
+
return created;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// src/dev/importCost/scope.ts
|
|
73
|
+
import { readdirSync, readFileSync, realpathSync, statSync } from "fs";
|
|
74
|
+
import { join } from "path";
|
|
75
|
+
var NESTED_SCAN_DEPTH = 6;
|
|
76
|
+
var REGEX_SPECIAL = /[.*+?^${}()|[\]\\]/g;
|
|
77
|
+
var SEPARATOR = "[\\\\/]";
|
|
78
|
+
var OUTSIDE_MODULES = `(?!.*${SEPARATOR}node_modules${SEPARATOR}).*`;
|
|
79
|
+
var SOURCE_EXTENSION = "\\.m?[jt]sx?$";
|
|
80
|
+
var ANY_MJS = "\\.mjs$";
|
|
81
|
+
var manifestType = (directory) => {
|
|
82
|
+
try {
|
|
83
|
+
const manifest = JSON.parse(readFileSync(join(directory, "package.json"), "utf8"));
|
|
84
|
+
return Reflect.get(Object(manifest), "type") === "module" ? "module" : "commonjs";
|
|
85
|
+
} catch {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
var subdirectories = (directory) => {
|
|
90
|
+
try {
|
|
91
|
+
return readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isDirectory() || entry.isSymbolicLink()).map((entry) => entry.name);
|
|
92
|
+
} catch {
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
var findCommonJsIslands = (directory, found, depth) => {
|
|
97
|
+
if (depth > NESTED_SCAN_DEPTH)
|
|
98
|
+
return;
|
|
99
|
+
for (const name of subdirectories(directory)) {
|
|
100
|
+
visitIsland(join(directory, name), name, found, depth);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
var visitIsland = (directory, name, found, depth) => {
|
|
104
|
+
if (name === "node_modules" || manifestType(directory) === "commonjs") {
|
|
105
|
+
found.push(directory);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
findCommonJsIslands(directory, found, depth + 1);
|
|
109
|
+
};
|
|
110
|
+
var recordPackage = (directory, regions) => {
|
|
111
|
+
if (manifestType(directory) !== "module")
|
|
112
|
+
return;
|
|
113
|
+
regions.esmPrefixes.push(directory);
|
|
114
|
+
findCommonJsIslands(directory, regions.cjsPrefixes, 0);
|
|
115
|
+
};
|
|
116
|
+
var scanEntry = (modulesRoot, name, regions) => {
|
|
117
|
+
if (name.startsWith("."))
|
|
118
|
+
return;
|
|
119
|
+
if (!name.startsWith("@")) {
|
|
120
|
+
recordPackage(join(modulesRoot, name), regions);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
for (const scoped of subdirectories(join(modulesRoot, name))) {
|
|
124
|
+
recordPackage(join(modulesRoot, name, scoped), regions);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
var scanPackages = (modulesRoot, regions) => {
|
|
128
|
+
for (const name of subdirectories(modulesRoot)) {
|
|
129
|
+
scanEntry(modulesRoot, name, regions);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
var esmRegions = (root) => {
|
|
133
|
+
const regions = { cjsPrefixes: [], esmPrefixes: [] };
|
|
134
|
+
const modulesRoot = join(root, "node_modules");
|
|
135
|
+
try {
|
|
136
|
+
statSync(modulesRoot);
|
|
137
|
+
} catch {
|
|
138
|
+
return regions;
|
|
139
|
+
}
|
|
140
|
+
scanPackages(realpathSync(modulesRoot), regions);
|
|
141
|
+
return regions;
|
|
142
|
+
};
|
|
143
|
+
var alternation = (prefixes) => prefixes.map((prefix) => prefix.replace(REGEX_SPECIAL, "\\$&")).join("|");
|
|
144
|
+
var instrumentableFilter = (regions) => {
|
|
145
|
+
const inEsmRegion = regions.esmPrefixes.length === 0 ? "" : `|(?:${alternation(regions.esmPrefixes)}).*`;
|
|
146
|
+
const notCommonJs = regions.cjsPrefixes.length === 0 ? "" : `(?!(?:${alternation(regions.cjsPrefixes)}))`;
|
|
147
|
+
return new RegExp(`^${notCommonJs}(?:${OUTSIDE_MODULES}${inEsmRegion})${SOURCE_EXTENSION}|${ANY_MJS}`);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// src/dev/importCostPreload.ts
|
|
151
|
+
var recorder = ensureImportCostRecorder();
|
|
152
|
+
var { events, moduleIds, moduleIndexes } = recorder;
|
|
153
|
+
var record = (moduleIndex, kind) => {
|
|
154
|
+
events.push(moduleIndex * IMPORT_COST_EVENT_KINDS + kind, performance.now());
|
|
155
|
+
};
|
|
156
|
+
globalThis.__absoluteImportCostEnter = (moduleIndex) => {
|
|
157
|
+
if (!recorder.recording)
|
|
158
|
+
return;
|
|
159
|
+
record(moduleIndex, IMPORT_COST_EVENT.enter);
|
|
160
|
+
};
|
|
161
|
+
globalThis.__absoluteImportCostExit = (moduleIndex) => {
|
|
162
|
+
if (!recorder.recording)
|
|
163
|
+
return;
|
|
164
|
+
record(moduleIndex, IMPORT_COST_EVENT.exit);
|
|
165
|
+
};
|
|
166
|
+
var reportModulePath = () => {
|
|
167
|
+
const compiled = join2(import.meta.dir, "importCostReport.js");
|
|
168
|
+
return existsSync(compiled) ? compiled : join2(import.meta.dir, "importCost", "report.ts");
|
|
169
|
+
};
|
|
170
|
+
globalThis.__absoluteImportCostReport = async () => {
|
|
171
|
+
recorder.recording = false;
|
|
172
|
+
try {
|
|
173
|
+
const loaded = await import(reportModulePath());
|
|
174
|
+
loaded.reportImportCost?.();
|
|
175
|
+
} catch (error) {
|
|
176
|
+
console.error(`[absolute] import-cost report failed to load: ${error instanceof Error ? error.message : String(error)}`);
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
var moduleIndexOf = (path) => {
|
|
180
|
+
const existing = moduleIndexes.get(path);
|
|
181
|
+
if (existing !== undefined)
|
|
182
|
+
return existing;
|
|
183
|
+
const created = moduleIds.length;
|
|
184
|
+
moduleIds.push(path);
|
|
185
|
+
moduleIndexes.set(path, created);
|
|
186
|
+
return created;
|
|
187
|
+
};
|
|
188
|
+
plugin({
|
|
189
|
+
name: "absolute-import-cost",
|
|
190
|
+
setup(build) {
|
|
191
|
+
build.onLoad({ filter: instrumentableFilter(esmRegions(process.cwd())) }, (args) => {
|
|
192
|
+
const loader = importCostLoader(args.path);
|
|
193
|
+
if (!recorder.recording) {
|
|
194
|
+
return {
|
|
195
|
+
contents: readFileSync2(args.path, "utf8"),
|
|
196
|
+
loader
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
const moduleIndex = moduleIndexOf(args.path);
|
|
200
|
+
record(moduleIndex, IMPORT_COST_EVENT.loadStart);
|
|
201
|
+
const contents = instrumentModuleSource(readFileSync2(args.path, "utf8"), moduleIndex);
|
|
202
|
+
record(moduleIndex, IMPORT_COST_EVENT.loadEnd);
|
|
203
|
+
return { contents, loader };
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
});
|