@scriptc/compiler 0.0.33 → 0.0.35
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/backend/cc-cache.test.js +1091 -7
- package/dist/backend/cc-cache.test.js.map +1 -1
- package/dist/backend/cc.d.ts +109 -18
- package/dist/backend/cc.js +1057 -289
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emit-exprs.js +26 -1
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-shapes.js +37 -4
- package/dist/backend/emission/emit-shapes.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +11 -2
- package/dist/backend/emission/emitter.js +11 -5
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/library-identity.d.ts +22 -0
- package/dist/backend/library-identity.js +103 -0
- package/dist/backend/library-identity.js.map +1 -0
- package/dist/backend/llvm/emitter.d.ts +3 -0
- package/dist/backend/llvm/emitter.js +35 -5
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/shapes.d.ts +1 -0
- package/dist/backend/llvm/shapes.js +25 -1
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/split.d.ts +43 -0
- package/dist/backend/llvm/split.js +227 -0
- package/dist/backend/llvm/split.js.map +1 -0
- package/dist/backend/llvm/split.test.d.ts +1 -0
- package/dist/backend/llvm/split.test.js +102 -0
- package/dist/backend/llvm/split.test.js.map +1 -0
- package/dist/backend/mangle.d.ts +1 -0
- package/dist/backend/mangle.js +3 -0
- package/dist/backend/mangle.js.map +1 -1
- package/dist/backend/object-localize.d.ts +5 -5
- package/dist/backend/object-localize.js +19 -16
- package/dist/backend/object-localize.js.map +1 -1
- package/dist/backend/object-localize.test.js +57 -13
- package/dist/backend/object-localize.test.js.map +1 -1
- package/dist/executable/early-cache.d.ts +86 -0
- package/dist/executable/early-cache.js +460 -0
- package/dist/executable/early-cache.js.map +1 -0
- package/dist/executable/early-cache.test.d.ts +1 -0
- package/dist/executable/early-cache.test.js +300 -0
- package/dist/executable/early-cache.test.js.map +1 -0
- package/dist/ffi/profile.d.ts +7 -2
- package/dist/ffi/profile.js +1 -0
- package/dist/ffi/profile.js.map +1 -1
- package/dist/frontend/input-tracker.d.ts +82 -0
- package/dist/frontend/input-tracker.js +380 -0
- package/dist/frontend/input-tracker.js.map +1 -0
- package/dist/frontend/input-tracker.test.d.ts +1 -0
- package/dist/frontend/input-tracker.test.js +137 -0
- package/dist/frontend/input-tracker.test.js.map +1 -0
- package/dist/frontend/lowering/lower-builtins.js +4 -10
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +169 -144
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.js +3 -0
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.js +66 -32
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.js +89 -11
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +45 -26
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.js +3 -3
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.js +1 -1
- package/dist/frontend/lowering/lower-mixins.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +1 -1
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +49 -4
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +73 -29
- package/dist/frontend/lowering/lowerer.js +588 -116
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.js +1 -1
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/npm-static-rewrite.js +25 -26
- package/dist/frontend/npm-static-rewrite.js.map +1 -1
- package/dist/frontend/npm-static.js +29 -30
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm-static.test.d.ts +1 -0
- package/dist/frontend/npm-static.test.js +15 -0
- package/dist/frontend/npm-static.test.js.map +1 -0
- package/dist/frontend/npm.js +5 -17
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/program.js +44 -19
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/resolve.js +8 -29
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/ts7/checker.d.ts +40 -2
- package/dist/frontend/ts7/checker.js +194 -32
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/program.js +17 -18
- package/dist/frontend/ts7/program.js.map +1 -1
- package/dist/frontend/types.d.ts +33 -0
- package/dist/frontend/types.js +134 -45
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.js +458 -141
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +27 -4
- package/dist/ir/nodes.js +28 -0
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/serialize.d.ts +1 -1
- package/dist/ir/serialize.js +1 -1
- package/dist/ir/validate.js +37 -1
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/early-cache.d.ts +65 -0
- package/dist/library/early-cache.js +361 -0
- package/dist/library/early-cache.js.map +1 -0
- package/dist/library/early-cache.test.d.ts +1 -0
- package/dist/library/early-cache.test.js +528 -0
- package/dist/library/early-cache.test.js.map +1 -0
- package/dist/library/implementation-identity.d.ts +23 -0
- package/dist/library/implementation-identity.js +84 -0
- package/dist/library/implementation-identity.js.map +1 -0
- package/dist/library/int-infer.js +14 -0
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +21 -4
- package/dist/library/int-infer.test.js.map +1 -1
- package/dist/library/semantic-source.d.ts +13 -0
- package/dist/library/semantic-source.js +257 -0
- package/dist/library/semantic-source.js.map +1 -0
- package/dist/library/semantic-source.test.d.ts +1 -0
- package/dist/library/semantic-source.test.js +113 -0
- package/dist/library/semantic-source.test.js.map +1 -0
- package/dist/library/sidecar.d.ts +6 -0
- package/dist/library/sidecar.js +11 -0
- package/dist/library/sidecar.js.map +1 -1
- package/dist/startup-cache.d.ts +6 -0
- package/dist/startup-cache.js +6 -0
- package/dist/startup-cache.js.map +1 -0
- package/package.json +3 -2
- package/surface-manifest.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
1
|
+
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
2
|
import { basename, dirname, join, resolve } from "node:path";
|
|
3
|
-
import { CcCompileError, compileC, compileLibArchive, mobileLibraryTarget, mobileTargetRefusal, resolveCc, targetPlatform } from "./backend/cc.js";
|
|
3
|
+
import { buildCacheRoot, CcCompileError, compileC, compileLibArchive, executableNativeEnvironmentFingerprint, mobileLibraryTarget, mobileTargetRefusal, prepareBuildCacheRoot, pruneBuildCache, resolveCc, targetPlatform } from "./backend/cc.js";
|
|
4
4
|
import { emitModule } from "./backend/emission/emitter.js";
|
|
5
5
|
import { emitLlvmModule, LlvmUnsupportedError } from "./backend/llvm/emitter.js";
|
|
6
|
+
import { splitLlvmLibraryProgram, splitLlvmProgram } from "./backend/llvm/split.js";
|
|
7
|
+
import { rebaseLibrarySourceComments, replaceLibraryIdentity, stripLibraryIdentity, stripLibrarySourceComments } from "./backend/library-identity.js";
|
|
6
8
|
import { checkerPanicDiag, ffiNativeBuildDiag, libAsyncExportDiag, libAsyncSurfaceDiag, libExportUnresolvedDiag, libGenericExportDiag, libIntBoundaryDiag, libNpmIneligibleDiag, libSidecarDiag, libUnmappableSignatureDiag, iceDiag, isCheckerPanic, LIB_INBOUND_BYTES_TRAP_CODE, LIB_RUNTIME_TRAP_CODES } from "./diagnostics/diagnostic.js";
|
|
7
9
|
import { checkLibraryIntegerSlots, classSeed, hasIntSlots, numberCarrierKind } from "./library/int-infer.js";
|
|
8
10
|
import { loadLibraryProfile, profileRemediation, profileTeaching } from "./library/profile.js";
|
|
9
11
|
import { decorateLibraryRefusals, evaluateLibraryFences } from "./library/fence-eval.js";
|
|
10
12
|
import { assembleTrapTeaching } from "./library/trap-teaching.js";
|
|
11
|
-
import { buildSidecar, canonicalModuleGraph, canonicalPath, compilerReleaseVersion, libraryIdentityHashes, } from "./library/sidecar.js";
|
|
13
|
+
import { buildSidecar, canonicalModuleGraph, canonicalPath, compilerReleaseVersion, libraryIdentityHashes, updateSidecarIdentity, } from "./library/sidecar.js";
|
|
12
14
|
import { validateSidecar } from "./library/sidecar-validate.js";
|
|
13
15
|
import { entryFunctionExports } from "./frontend/lib-exports.js";
|
|
14
16
|
import { entryContractFacts } from "./frontend/lib-contract.js";
|
|
@@ -18,13 +20,18 @@ import { validateModule } from "./ir/validate.js";
|
|
|
18
20
|
import { canonicalBuiltinModule, checkPreflight, isNodeTypesPath, loadProgram, locOf, requiresOf, resolveNpmImport } from "./frontend/program.js";
|
|
19
21
|
import { npmStaticIneligibleReason, npmStaticOffenders, npmStaticPackageOfPath } from "./frontend/npm-static.js";
|
|
20
22
|
import { provenanceSources } from "./frontend/provenance-registry.js";
|
|
21
|
-
import { resolveBareModule } from "./frontend/resolve.js";
|
|
23
|
+
import { clearResolveCaches, resolveBareModule } from "./frontend/resolve.js";
|
|
22
24
|
import { isJsSourceFileName, isRelativeSpecifier } from "./frontend/shared.js";
|
|
23
25
|
import { lowerToIr } from "./frontend/lowering/lowerer.js";
|
|
24
26
|
import { loadFfiProfile } from "./ffi/profile.js";
|
|
25
27
|
import { hasForeignFfiCallback } from "./backend/ffi-callbacks.js";
|
|
28
|
+
import { FrontendInputTracker, trackedReadFile } from "./frontend/input-tracker.js";
|
|
29
|
+
import { libraryFrontendImplementationFingerprint, publishEarlyLibraryCache, readEarlyLibraryCache, readSemanticLibraryCache } from "./library/early-cache.js";
|
|
30
|
+
import { createSourceLineRebaser } from "./library/semantic-source.js";
|
|
31
|
+
import { publishEarlyExecutableCache, publishEarlyExecutableRoute, readEarlyExecutableCache } from "./executable/early-cache.js";
|
|
32
|
+
import { compilerImplementationIdentity } from "./library/implementation-identity.js";
|
|
26
33
|
export const VERSION = "0.0.1";
|
|
27
|
-
export { compileC, runtimeSrcDir } from "./backend/cc.js";
|
|
34
|
+
export { compileC, runtimeSrcDir, warmNativeCaches, } from "./backend/cc.js";
|
|
28
35
|
export { ANDROID_MIN_API, IPHONEOS_MIN_VERSION, isAndroidTarget, isIosTarget, isMobileTarget, mobileLibraryTarget, mobileTargetRefusal } from "./backend/cc.js";
|
|
29
36
|
export { emitModule } from "./backend/emission/emitter.js";
|
|
30
37
|
export { renderAll, renderDiagnostic } from "./diagnostics/render.js";
|
|
@@ -317,6 +324,11 @@ function packageNameOfBareSpecifier(specifier) {
|
|
|
317
324
|
* static-or-refuse teaching, and the detection closes over the opted-in
|
|
318
325
|
* packages' own bare edges (no island exists to serve a dep from). */
|
|
319
326
|
function runFrontend(entryPath, npmStatic, externalTypes) {
|
|
327
|
+
// Resolver package/workspace metadata is intentionally shared across the
|
|
328
|
+
// several load attempts of ONE auto-detection fixpoint, but never across
|
|
329
|
+
// separate compiles in a long-lived process. A cache miss must observe
|
|
330
|
+
// package.json edits before it can publish a new early-library entry.
|
|
331
|
+
clearResolveCaches();
|
|
320
332
|
const statuses = [];
|
|
321
333
|
const npmSites = new Map();
|
|
322
334
|
const judged = new Set();
|
|
@@ -620,13 +632,112 @@ export function analyze(entryPath, opts = {}) {
|
|
|
620
632
|
}
|
|
621
633
|
/** The whole pipeline: load → preflight → lower → validate → emit C → clang. */
|
|
622
634
|
export async function compile(entryPath, opts) {
|
|
635
|
+
const frontendInputs = new FrontendInputTracker();
|
|
636
|
+
return frontendInputs.run(() => compileTracked(entryPath, opts, frontendInputs));
|
|
637
|
+
}
|
|
638
|
+
function executableNativeFeatures(mod, backend, dynamic, optimization, llvmRefusal) {
|
|
639
|
+
return {
|
|
640
|
+
backend,
|
|
641
|
+
...(optimization === "dev" ? { optimization: "dev" } : {}),
|
|
642
|
+
...(llvmRefusal === undefined ? {} : { llvmRefusal }),
|
|
643
|
+
dynamic,
|
|
644
|
+
regex: moduleUsesRegex(mod),
|
|
645
|
+
copying: moduleUsesCopying(mod),
|
|
646
|
+
textDecoderLegacy: moduleUsesLegacyTextDecoder(mod),
|
|
647
|
+
fileHandle: moduleUsesFileHandle(mod),
|
|
648
|
+
fetch: moduleUsesFetch(mod),
|
|
649
|
+
netIsland: moduleEmbedsBuiltin(mod, "node:http") ||
|
|
650
|
+
moduleEmbedsBuiltin(mod, "node:https") ||
|
|
651
|
+
moduleEmbedsBuiltin(mod, "node:net") ||
|
|
652
|
+
moduleEmbedsBuiltin(mod, "node:tls"),
|
|
653
|
+
zlib: moduleUsesZlib(mod) || moduleEmbedsCompressedNpm(mod),
|
|
654
|
+
assert: moduleUsesAssert(mod),
|
|
655
|
+
inspect: moduleUsesInspect(mod),
|
|
656
|
+
dynInvoke: moduleUsesDynInvoke(mod),
|
|
657
|
+
dc: moduleUsesDc(mod),
|
|
658
|
+
dynAsync: moduleUsesDynAsync(mod),
|
|
659
|
+
events: moduleUsesProcessEvents(mod),
|
|
660
|
+
emitter: moduleUsesEmitter(mod),
|
|
661
|
+
symbol: moduleUsesSymbol(mod),
|
|
662
|
+
searchParams: moduleUsesSearchParams(mod),
|
|
663
|
+
qs: moduleUsesQs(mod),
|
|
664
|
+
parseArgs: moduleUsesParseArgs(mod),
|
|
665
|
+
stream: moduleUsesStream(mod),
|
|
666
|
+
net: moduleUsesNet(mod),
|
|
667
|
+
http: moduleUsesHttpServer(mod),
|
|
668
|
+
http2: moduleUsesHttp2(mod),
|
|
669
|
+
dgram: moduleUsesDgram(mod),
|
|
670
|
+
watch: moduleUsesFsWatch(mod),
|
|
671
|
+
foreignFfi: hasForeignFfiCallback(mod.ffiImports ?? []),
|
|
672
|
+
nodeTest: moduleUsesNodeTest(mod),
|
|
673
|
+
tls: moduleUsesTls(mod),
|
|
674
|
+
tlsCa: moduleUsesTlsCa(mod),
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
async function compileExecutableNative(features, cPath, outPath, sanitize, ffi, programSplit = null, onArtifactReady) {
|
|
678
|
+
const effectiveProgramSplit = programSplit ??
|
|
679
|
+
(features.optimization === "dev" && features.backend === "llvm" && !sanitize
|
|
680
|
+
? splitLlvmProgram(await readFile(cPath, "utf8"))
|
|
681
|
+
: null);
|
|
682
|
+
await compileC({
|
|
683
|
+
cPath,
|
|
684
|
+
outPath,
|
|
685
|
+
cacheIdentity: "scriptc-generated-v1",
|
|
686
|
+
...(features.optimization === "dev" ? { optimization: "dev" } : {}),
|
|
687
|
+
...(effectiveProgramSplit === null
|
|
688
|
+
? {}
|
|
689
|
+
: {
|
|
690
|
+
programShards: effectiveProgramSplit.shards,
|
|
691
|
+
programPublicSymbols: effectiveProgramSplit.publicSymbols,
|
|
692
|
+
}),
|
|
693
|
+
sanitize,
|
|
694
|
+
dynamic: features.dynamic,
|
|
695
|
+
regex: features.regex,
|
|
696
|
+
copying: features.copying,
|
|
697
|
+
textDecoderLegacy: features.textDecoderLegacy,
|
|
698
|
+
fileHandle: features.fileHandle,
|
|
699
|
+
fetch: features.fetch,
|
|
700
|
+
netIsland: features.netIsland,
|
|
701
|
+
zlib: features.zlib,
|
|
702
|
+
assert: features.assert,
|
|
703
|
+
inspect: features.inspect,
|
|
704
|
+
dynInvoke: features.dynInvoke,
|
|
705
|
+
dc: features.dc,
|
|
706
|
+
dynAsync: features.dynAsync,
|
|
707
|
+
events: features.events,
|
|
708
|
+
emitter: features.emitter,
|
|
709
|
+
symbol: features.symbol,
|
|
710
|
+
searchParams: features.searchParams,
|
|
711
|
+
qs: features.qs,
|
|
712
|
+
parseArgs: features.parseArgs,
|
|
713
|
+
stream: features.stream,
|
|
714
|
+
net: features.net,
|
|
715
|
+
http: features.http,
|
|
716
|
+
http2: features.http2,
|
|
717
|
+
dgram: features.dgram,
|
|
718
|
+
watch: features.watch,
|
|
719
|
+
foreignFfi: features.foreignFfi,
|
|
720
|
+
nodeTest: features.nodeTest,
|
|
721
|
+
tls: features.tls,
|
|
722
|
+
tlsCa: features.tlsCa,
|
|
723
|
+
...(onArtifactReady === undefined ? {} : { onArtifactReady }),
|
|
724
|
+
...(ffi === null
|
|
725
|
+
? {}
|
|
726
|
+
: { linkInputs: ffi.libraries, systemLibraries: ffi.systemLibraries }),
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
async function compileTracked(entryPath, opts, frontendInputs) {
|
|
730
|
+
entryPath = resolve(entryPath);
|
|
623
731
|
let ffi = null;
|
|
732
|
+
let ffiProfileBytes = null;
|
|
624
733
|
if (opts.ffiProfilePath !== undefined) {
|
|
625
|
-
const
|
|
734
|
+
const ffiProfilePath = resolve(opts.ffiProfilePath);
|
|
735
|
+
const loaded = loadFfiProfile(ffiProfilePath);
|
|
626
736
|
if (!loaded.ok) {
|
|
627
737
|
return { ok: false, diagnostics: loaded.diagnostics, sourceTexts: new Map() };
|
|
628
738
|
}
|
|
629
739
|
ffi = loaded.profile;
|
|
740
|
+
ffiProfileBytes = loaded.profileBytes;
|
|
630
741
|
}
|
|
631
742
|
const buildPlatform = buildTargetPlatform();
|
|
632
743
|
// Mobile triples are library-mode targets: the archive an embedding app
|
|
@@ -655,6 +766,81 @@ export async function compile(entryPath, opts) {
|
|
|
655
766
|
};
|
|
656
767
|
}
|
|
657
768
|
}
|
|
769
|
+
const cacheRoot = provenanceSources() === null
|
|
770
|
+
? await prepareBuildCacheRoot(buildCacheRoot())
|
|
771
|
+
: null;
|
|
772
|
+
const implementation = await compilerImplementationIdentity();
|
|
773
|
+
const earlyCacheOptions = {
|
|
774
|
+
entryPath,
|
|
775
|
+
outDir: opts.outDir,
|
|
776
|
+
outPath: opts.outPath,
|
|
777
|
+
emitIr: opts.emitIr ?? false,
|
|
778
|
+
sanitize: opts.sanitize ?? false,
|
|
779
|
+
dynamic: opts.dynamic ?? false,
|
|
780
|
+
backend: opts.backend ?? "auto",
|
|
781
|
+
...(opts.optimization === "dev" ? { optimization: "dev" } : {}),
|
|
782
|
+
npmStatic: opts.npmStatic ?? null,
|
|
783
|
+
ffiProfile: opts.ffiProfilePath === undefined || ffiProfileBytes === null
|
|
784
|
+
? null
|
|
785
|
+
: { path: opts.ffiProfilePath, bytes: ffiProfileBytes },
|
|
786
|
+
target: `${process.env["SCRIPTC_TARGET"] ?? "native"}:${buildPlatform}:${process.arch}`,
|
|
787
|
+
compiler: [process.env["SCRIPTC_CC"] ?? "clang"],
|
|
788
|
+
nativeEnvironment: await executableNativeEnvironmentFingerprint(),
|
|
789
|
+
nodeVersion: process.version,
|
|
790
|
+
implementation: implementation.digest,
|
|
791
|
+
implementationDependencies: implementation.dependencies,
|
|
792
|
+
};
|
|
793
|
+
const earlyHit = await readEarlyExecutableCache(cacheRoot, earlyCacheOptions);
|
|
794
|
+
if (earlyHit !== null) {
|
|
795
|
+
// Route/proof metadata is independently evictable. A full-compiler
|
|
796
|
+
// fallback that still finds the validated payload repairs that lightweight
|
|
797
|
+
// index so the next identical CLI invocation can avoid this module graph.
|
|
798
|
+
await publishEarlyExecutableRoute(cacheRoot, earlyCacheOptions).catch(() => undefined);
|
|
799
|
+
if (earlyHit.executableRestored) {
|
|
800
|
+
await pruneBuildCache(cacheRoot);
|
|
801
|
+
return {
|
|
802
|
+
ok: true,
|
|
803
|
+
binaryPath: opts.outPath,
|
|
804
|
+
cPath: earlyHit.cPath,
|
|
805
|
+
backend: earlyHit.native.backend,
|
|
806
|
+
...(earlyHit.irPath === undefined ? {} : { irPath: earlyHit.irPath }),
|
|
807
|
+
...(earlyHit.native.llvmRefusal === undefined
|
|
808
|
+
? {}
|
|
809
|
+
: { llvmRefusal: earlyHit.native.llvmRefusal }),
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
try {
|
|
813
|
+
await compileExecutableNative(earlyHit.native, earlyHit.cPath, opts.outPath, opts.sanitize ?? false, ffi, null, async ({ dependencies }) => {
|
|
814
|
+
await publishEarlyExecutableCache(cacheRoot, earlyCacheOptions, {
|
|
815
|
+
...earlyHit,
|
|
816
|
+
executableRestored: true,
|
|
817
|
+
nativeDependencies: dependencies,
|
|
818
|
+
frontend: earlyHit.frontend,
|
|
819
|
+
});
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
catch (err) {
|
|
823
|
+
if (ffi !== null && err instanceof CcCompileError) {
|
|
824
|
+
return {
|
|
825
|
+
ok: false,
|
|
826
|
+
diagnostics: [ffiNativeBuildDiag(ffiNativeBuildDetail(err), opts.ffiProfilePath ?? entryPath)],
|
|
827
|
+
sourceTexts: new Map(),
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
throw err;
|
|
831
|
+
}
|
|
832
|
+
await pruneBuildCache(cacheRoot);
|
|
833
|
+
return {
|
|
834
|
+
ok: true,
|
|
835
|
+
binaryPath: opts.outPath,
|
|
836
|
+
cPath: earlyHit.cPath,
|
|
837
|
+
backend: earlyHit.native.backend,
|
|
838
|
+
...(earlyHit.irPath === undefined ? {} : { irPath: earlyHit.irPath }),
|
|
839
|
+
...(earlyHit.native.llvmRefusal === undefined
|
|
840
|
+
? {}
|
|
841
|
+
: { llvmRefusal: earlyHit.native.llvmRefusal }),
|
|
842
|
+
};
|
|
843
|
+
}
|
|
658
844
|
const fe = runFrontend(entryPath, opts.npmStatic);
|
|
659
845
|
let lowered;
|
|
660
846
|
let entryText;
|
|
@@ -728,6 +914,7 @@ export async function compile(entryPath, opts) {
|
|
|
728
914
|
// (the frontend ran once, the IR is backend-agnostic — nothing recompiles).
|
|
729
915
|
let cPath = join(opts.outDir, `${stem}.c`);
|
|
730
916
|
let backend = "c";
|
|
917
|
+
let llvmSource = null;
|
|
731
918
|
let llvmRefusal;
|
|
732
919
|
if (opts.backend !== "c") {
|
|
733
920
|
try {
|
|
@@ -737,6 +924,7 @@ export async function compile(entryPath, opts) {
|
|
|
737
924
|
});
|
|
738
925
|
cPath = join(opts.outDir, `${stem}.ll`);
|
|
739
926
|
await writeFile(cPath, ll);
|
|
927
|
+
llvmSource = ll;
|
|
740
928
|
backend = "llvm";
|
|
741
929
|
}
|
|
742
930
|
catch (err) {
|
|
@@ -763,105 +951,24 @@ export async function compile(entryPath, opts) {
|
|
|
763
951
|
irPath = join(opts.outDir, `${stem}.ir.json`);
|
|
764
952
|
await writeFile(irPath, serializeModule(lowered.module));
|
|
765
953
|
}
|
|
954
|
+
const nativeFeatures = executableNativeFeatures(lowered.module, backend, opts.dynamic ?? false, opts.optimization ?? "release", llvmRefusal);
|
|
955
|
+
const programSplit = backend === "llvm" && (opts.optimization ?? "release") === "dev" &&
|
|
956
|
+
!(opts.sanitize ?? false) && llvmSource !== null
|
|
957
|
+
? splitLlvmProgram(llvmSource)
|
|
958
|
+
: null;
|
|
766
959
|
await mkdir(dirname(opts.outPath), { recursive: true });
|
|
960
|
+
let publishedExecutable = false;
|
|
767
961
|
try {
|
|
768
|
-
await
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
// regex-free programs keep the historical (pinned) command line.
|
|
779
|
-
regex: moduleUsesRegex(lowered.module),
|
|
780
|
-
// Array copying methods and the typed-array bridges live in one
|
|
781
|
-
// optional TU, linked only when one of their IR intrinsics survives.
|
|
782
|
-
copying: moduleUsesCopying(lowered.module),
|
|
783
|
-
textDecoderLegacy: moduleUsesLegacyTextDecoder(lowered.module),
|
|
784
|
-
// FileHandle owns a native descriptor and its settled-promise adapters;
|
|
785
|
-
// keep that optional TU out of programs that never call fsp.open.
|
|
786
|
-
fileHandle: moduleUsesFileHandle(lowered.module),
|
|
787
|
-
// The link switch for scr_fetch.c (the native bridge over scr_net +
|
|
788
|
-
// scr_tls + scr_http's client parser + zlib — cc.ts implies those
|
|
789
|
-
// units into the link): embedded npm code that references fetch gets
|
|
790
|
-
// the bridge; everything else keeps its exact link line.
|
|
791
|
-
fetch: moduleUsesFetch(lowered.module),
|
|
792
|
-
// The island's node:http/https client bridge: embedded graphs that
|
|
793
|
-
// import those builtins pull scr_net_island.c + the socket units.
|
|
794
|
-
netIsland: moduleEmbedsBuiltin(lowered.module, "node:http") ||
|
|
795
|
-
moduleEmbedsBuiltin(lowered.module, "node:https") ||
|
|
796
|
-
moduleEmbedsBuiltin(lowered.module, "node:net") ||
|
|
797
|
-
moduleEmbedsBuiltin(lowered.module, "node:tls"),
|
|
798
|
-
// The link switch for scr_zlib.c + libz: zlib.* libCalls on the IR,
|
|
799
|
-
// node:zlib in the embedded graph, or COMPRESSED embedded module text
|
|
800
|
-
// (emit-island.ts stores big npm sources as raw DEFLATE; the emitted
|
|
801
|
-
// main installs scr_zlib_inflate_exact on the same predicate).
|
|
802
|
-
zlib: moduleUsesZlib(lowered.module) || moduleEmbedsCompressedNpm(lowered.module),
|
|
803
|
-
// The link switch for scr_assert.c: assert.* libCalls on the IR (the
|
|
804
|
-
// regex switch also pulls it — scr_regex.c calls the assert helpers).
|
|
805
|
-
assert: moduleUsesAssert(lowered.module),
|
|
806
|
-
// The link switch for scr_inspect.c: insp.* libCalls on the IR.
|
|
807
|
-
inspect: moduleUsesInspect(lowered.module),
|
|
808
|
-
// The link switch for scr_dyn_invoke.c: dynInvoke nodes or
|
|
809
|
-
// dyn.defineProps libCalls on the IR.
|
|
810
|
-
dynInvoke: moduleUsesDynInvoke(lowered.module),
|
|
811
|
-
// The link switch for scr_dc.c: dc.* libCalls on the IR (the
|
|
812
|
-
// diagnostics_channel registry and pub/sub).
|
|
813
|
-
dc: moduleUsesDc(lowered.module),
|
|
814
|
-
// The link switch for scr_async_dyn.c: the checked-dynamic async
|
|
815
|
-
// surfaces (cc.ts also pulls it under the dynInvoke/dc gates).
|
|
816
|
-
dynAsync: moduleUsesDynAsync(lowered.module),
|
|
817
|
-
// The link switch for scr_events.c: process signal/exit listeners and
|
|
818
|
-
// the stdin event surface on the IR.
|
|
819
|
-
events: moduleUsesProcessEvents(lowered.module),
|
|
820
|
-
// The link switch for scr_events_emitter.c: the node:events
|
|
821
|
-
// EventEmitter surface on the IR (emitter.* libCalls or the
|
|
822
|
-
// %EventEmitter class def).
|
|
823
|
-
emitter: moduleUsesEmitter(lowered.module),
|
|
824
|
-
// The link switch for scr_symbol.c: sym.* libCalls or a symbol-kind
|
|
825
|
-
// type anywhere on the IR.
|
|
826
|
-
symbol: moduleUsesSymbol(lowered.module),
|
|
827
|
-
// The link switch for scr_url_params.c: sp.* libCalls, the
|
|
828
|
-
// url.searchParams getter, or a searchParams-kind type on the IR.
|
|
829
|
-
searchParams: moduleUsesSearchParams(lowered.module),
|
|
830
|
-
// The link switch for scr_qs.c: the qs.* libCalls that live there
|
|
831
|
-
// (parse/stringify/unescape; escape rides the always-linked encoder).
|
|
832
|
-
qs: moduleUsesQs(lowered.module),
|
|
833
|
-
// The static node:util parseArgs implementation (scr_util.c).
|
|
834
|
-
parseArgs: moduleUsesParseArgs(lowered.module),
|
|
835
|
-
// The link switch for scr_stream.c: the node:stream class surface on
|
|
836
|
-
// the IR (stream libCalls or the %Readable-family class defs).
|
|
837
|
-
stream: moduleUsesStream(lowered.module),
|
|
838
|
-
// The link switch for scr_net.c: net.* (or http.* — http rides on
|
|
839
|
-
// net) libCalls on the IR.
|
|
840
|
-
net: moduleUsesNet(lowered.module),
|
|
841
|
-
// The link switch for scr_http.c: http.* libCalls on the IR.
|
|
842
|
-
http: moduleUsesHttpServer(lowered.module),
|
|
843
|
-
http2: moduleUsesHttp2(lowered.module),
|
|
844
|
-
// The link switch for scr_dgram.c: dgram.* or dns.* libCalls on the IR.
|
|
845
|
-
dgram: moduleUsesDgram(lowered.module),
|
|
846
|
-
// The link switch for scr_watch.c: fs.watch/watcher.* libCalls on the IR.
|
|
847
|
-
watch: moduleUsesFsWatch(lowered.module),
|
|
848
|
-
foreignFfi: hasForeignFfiCallback(lowered.module.ffiImports ?? []),
|
|
849
|
-
// The link switch for scr_test.c: test.* libCalls on the IR.
|
|
850
|
-
nodeTest: moduleUsesNodeTest(lowered.module),
|
|
851
|
-
// The link switch for scr_tls.c + the vendored mbedTLS archive:
|
|
852
|
-
// tls.* or https.* libCalls on the IR.
|
|
853
|
-
tls: moduleUsesTls(lowered.module),
|
|
854
|
-
// The link switch for scr_tls_ca.c (the CA-store introspection unit
|
|
855
|
-
// — plain PEM bookkeeping, no mbedTLS): tlsca.* libCalls on the IR.
|
|
856
|
-
// cc.ts also compiles it under the tls gate (scr_tls.c consults the
|
|
857
|
-
// unit's default-set override for its trust anchors).
|
|
858
|
-
tlsCa: moduleUsesTlsCa(lowered.module),
|
|
859
|
-
...(ffi !== null
|
|
860
|
-
? {
|
|
861
|
-
linkInputs: ffi.libraries,
|
|
862
|
-
systemLibraries: ffi.systemLibraries,
|
|
863
|
-
}
|
|
864
|
-
: {}),
|
|
962
|
+
await compileExecutableNative(nativeFeatures, cPath, opts.outPath, opts.sanitize ?? false, ffi, programSplit, async ({ dependencies }) => {
|
|
963
|
+
await publishEarlyExecutableCache(cacheRoot, earlyCacheOptions, {
|
|
964
|
+
cPath,
|
|
965
|
+
native: nativeFeatures,
|
|
966
|
+
executableRestored: true,
|
|
967
|
+
nativeDependencies: dependencies,
|
|
968
|
+
frontend: frontendInputs.snapshot(),
|
|
969
|
+
...(irPath === undefined ? {} : { irPath }),
|
|
970
|
+
});
|
|
971
|
+
publishedExecutable = true;
|
|
865
972
|
});
|
|
866
973
|
}
|
|
867
974
|
catch (err) {
|
|
@@ -876,6 +983,16 @@ export async function compile(entryPath, opts) {
|
|
|
876
983
|
}
|
|
877
984
|
throw err;
|
|
878
985
|
}
|
|
986
|
+
if (!publishedExecutable) {
|
|
987
|
+
await publishEarlyExecutableCache(cacheRoot, earlyCacheOptions, {
|
|
988
|
+
cPath,
|
|
989
|
+
native: nativeFeatures,
|
|
990
|
+
executableRestored: false,
|
|
991
|
+
frontend: frontendInputs.snapshot(),
|
|
992
|
+
...(irPath === undefined ? {} : { irPath }),
|
|
993
|
+
}).catch(() => undefined);
|
|
994
|
+
}
|
|
995
|
+
await pruneBuildCache(cacheRoot);
|
|
879
996
|
return {
|
|
880
997
|
ok: true,
|
|
881
998
|
binaryPath: opts.outPath,
|
|
@@ -1202,7 +1319,176 @@ function mergeSidecarIntSlots(cfg, facts, mod) {
|
|
|
1202
1319
|
}
|
|
1203
1320
|
return { ok: true, config: cfg };
|
|
1204
1321
|
}
|
|
1322
|
+
function libraryNativeFeatures(mod, backend) {
|
|
1323
|
+
return {
|
|
1324
|
+
backend,
|
|
1325
|
+
regex: moduleUsesRegex(mod),
|
|
1326
|
+
assert: moduleUsesAssert(mod),
|
|
1327
|
+
inspect: moduleUsesInspect(mod),
|
|
1328
|
+
symbol: moduleUsesSymbol(mod),
|
|
1329
|
+
searchParams: moduleUsesSearchParams(mod),
|
|
1330
|
+
emitter: moduleUsesEmitter(mod),
|
|
1331
|
+
zlib: moduleUsesZlib(mod),
|
|
1332
|
+
copying: moduleUsesCopying(mod),
|
|
1333
|
+
textDecoderLegacy: moduleUsesLegacyTextDecoder(mod),
|
|
1334
|
+
...(mod.lib?.identity !== undefined ? { buildId: mod.lib.identity.buildId } : {}),
|
|
1335
|
+
};
|
|
1336
|
+
}
|
|
1337
|
+
function libraryLocalizeSymbols(profile) {
|
|
1338
|
+
return profile.localizeRuntime
|
|
1339
|
+
? [
|
|
1340
|
+
profile.initSymbol,
|
|
1341
|
+
profile.sinkRegisterSymbol,
|
|
1342
|
+
...(profile.collectSymbol !== null ? [profile.collectSymbol] : []),
|
|
1343
|
+
...(profile.resultResetSymbol !== null ? [profile.resultResetSymbol] : []),
|
|
1344
|
+
...(profile.callbackRegisterSymbol !== null ? [profile.callbackRegisterSymbol] : []),
|
|
1345
|
+
...(profile.sidecar !== null
|
|
1346
|
+
? [profile.sidecar.buildIdSymbol, profile.sidecar.abiVersionSymbol]
|
|
1347
|
+
: []),
|
|
1348
|
+
...profile.exports.map((entry) => entry.symbol),
|
|
1349
|
+
]
|
|
1350
|
+
: undefined;
|
|
1351
|
+
}
|
|
1352
|
+
async function compileLibraryNative(profile, cPath, archivePath, sanitize, features) {
|
|
1353
|
+
const localizeSymbols = libraryLocalizeSymbols(profile);
|
|
1354
|
+
let identityCSource;
|
|
1355
|
+
let programSource;
|
|
1356
|
+
if (profile.sidecar !== null || profile.emission === "c" ||
|
|
1357
|
+
(profile.emission === "llvm" && profile.optimization === "dev" && !sanitize)) {
|
|
1358
|
+
const publicSource = await readFile(cPath, "utf8");
|
|
1359
|
+
programSource = publicSource;
|
|
1360
|
+
}
|
|
1361
|
+
if (profile.sidecar !== null) {
|
|
1362
|
+
if (features.buildId === undefined)
|
|
1363
|
+
throw new Error("library identity TU has no build id");
|
|
1364
|
+
const withoutIdentity = stripLibraryIdentity(programSource, profile.emission);
|
|
1365
|
+
if (withoutIdentity === programSource) {
|
|
1366
|
+
throw new Error("generated public library TU has no identity region");
|
|
1367
|
+
}
|
|
1368
|
+
programSource = withoutIdentity;
|
|
1369
|
+
identityCSource = [
|
|
1370
|
+
"#include <stdint.h>",
|
|
1371
|
+
"#include <inttypes.h>",
|
|
1372
|
+
`uint64_t ${profile.sidecar.buildIdSymbol}(void) { return UINT64_C(0x${features.buildId}); }`,
|
|
1373
|
+
`uint32_t ${profile.sidecar.abiVersionSymbol}(void) { return ${profile.sidecar.abiVersion}u; }`,
|
|
1374
|
+
"",
|
|
1375
|
+
].join("\n");
|
|
1376
|
+
}
|
|
1377
|
+
if (profile.emission === "c") {
|
|
1378
|
+
programSource = stripLibrarySourceComments(programSource, profile.entry);
|
|
1379
|
+
}
|
|
1380
|
+
const llvmSplit = profile.emission === "llvm" && profile.optimization === "dev" && !sanitize && programSource !== undefined
|
|
1381
|
+
? splitLlvmLibraryProgram(programSource)
|
|
1382
|
+
: null;
|
|
1383
|
+
await compileLibArchive({
|
|
1384
|
+
cPath,
|
|
1385
|
+
...(programSource !== undefined ? { programSource } : {}),
|
|
1386
|
+
...(identityCSource !== undefined ? { identityCSource } : {}),
|
|
1387
|
+
...(llvmSplit !== null
|
|
1388
|
+
? {
|
|
1389
|
+
programShards: llvmSplit.shards,
|
|
1390
|
+
programPublicSymbols: llvmSplit.publicSymbols,
|
|
1391
|
+
}
|
|
1392
|
+
: {}),
|
|
1393
|
+
outPath: archivePath,
|
|
1394
|
+
cacheIdentity: "scriptc-generated-library-v1",
|
|
1395
|
+
sanitize,
|
|
1396
|
+
optimization: profile.optimization,
|
|
1397
|
+
...(localizeSymbols !== undefined ? { localizeSymbols } : {}),
|
|
1398
|
+
...(profile.instancePerThread ? { threadInstances: true } : {}),
|
|
1399
|
+
regex: features.regex,
|
|
1400
|
+
assert: features.assert,
|
|
1401
|
+
inspect: features.inspect,
|
|
1402
|
+
symbol: features.symbol,
|
|
1403
|
+
searchParams: features.searchParams,
|
|
1404
|
+
emitter: features.emitter,
|
|
1405
|
+
zlib: features.zlib,
|
|
1406
|
+
copying: features.copying,
|
|
1407
|
+
textDecoderLegacy: features.textDecoderLegacy,
|
|
1408
|
+
});
|
|
1409
|
+
}
|
|
1410
|
+
async function emitSemanticLibraryHit(hit, profile, opts, archivePath, cacheRoot, cacheOptions, timing) {
|
|
1411
|
+
const mod = hit.mod;
|
|
1412
|
+
const rootDir = dirname(resolve(opts.profilePath));
|
|
1413
|
+
let sidecarJson = hit.sidecarJson;
|
|
1414
|
+
if (profile.sidecar !== null) {
|
|
1415
|
+
if (mod.lib?.identity === undefined || sidecarJson === null) {
|
|
1416
|
+
throw new Error("semantic library cache lost sidecar identity metadata");
|
|
1417
|
+
}
|
|
1418
|
+
const modules = canonicalModuleGraph(rootDir, hit.sourceTexts);
|
|
1419
|
+
const { buildId, sourceHash } = libraryIdentityHashes(compilerReleaseVersion(), profile.profileBytes, modules);
|
|
1420
|
+
mod.lib.identity.buildId = buildId;
|
|
1421
|
+
hit.native.buildId = buildId;
|
|
1422
|
+
sidecarJson = updateSidecarIdentity(sidecarJson, buildId, sourceHash);
|
|
1423
|
+
}
|
|
1424
|
+
const validation = validateModule(mod);
|
|
1425
|
+
if (validation.length > 0) {
|
|
1426
|
+
return {
|
|
1427
|
+
ok: false,
|
|
1428
|
+
diagnostics: validation.map((violation) => iceDiag(violation.message, violation.loc)),
|
|
1429
|
+
sourceTexts: hit.sourceTexts,
|
|
1430
|
+
};
|
|
1431
|
+
}
|
|
1432
|
+
await mkdir(opts.outDir, { recursive: true });
|
|
1433
|
+
const stem = basename(profile.entry).replace(/\.(ts|js|mjs|cjs)$/, "");
|
|
1434
|
+
const cPath = join(opts.outDir, `${stem}.lib.${profile.emission === "llvm" ? "ll" : "c"}`);
|
|
1435
|
+
let translationUnit = hit.translationUnit;
|
|
1436
|
+
if (profile.sidecar !== null) {
|
|
1437
|
+
translationUnit = replaceLibraryIdentity(translationUnit, profile.emission, mod.lib.identity);
|
|
1438
|
+
}
|
|
1439
|
+
if (profile.emission === "llvm") {
|
|
1440
|
+
await writeFile(cPath, translationUnit);
|
|
1441
|
+
}
|
|
1442
|
+
else {
|
|
1443
|
+
const previous = hit.previousSources.get(mod.sourceFile);
|
|
1444
|
+
const current = hit.sourceTexts.get(mod.sourceFile);
|
|
1445
|
+
if (previous === undefined || current === undefined) {
|
|
1446
|
+
throw new Error("semantic library cache lost the entry source text");
|
|
1447
|
+
}
|
|
1448
|
+
translationUnit = rebaseLibrarySourceComments(translationUnit, mod.sourceFile, createSourceLineRebaser(mod.sourceFile, previous, current));
|
|
1449
|
+
await writeFile(cPath, translationUnit);
|
|
1450
|
+
}
|
|
1451
|
+
timing("semantic-tu-restore", { output_bytes: Buffer.byteLength(translationUnit) });
|
|
1452
|
+
await rm(join(opts.outDir, `${stem}.lib.${profile.emission === "llvm" ? "c" : "ll"}`), { force: true });
|
|
1453
|
+
let irPath;
|
|
1454
|
+
if (opts.emitIr) {
|
|
1455
|
+
irPath = join(opts.outDir, `${stem}.lib.ir.json`);
|
|
1456
|
+
await writeFile(irPath, serializeModule(mod));
|
|
1457
|
+
}
|
|
1458
|
+
await compileLibraryNative(profile, cPath, archivePath, opts.sanitize ?? false, hit.native);
|
|
1459
|
+
timing("native-archive");
|
|
1460
|
+
let sidecarPath;
|
|
1461
|
+
if (sidecarJson !== null) {
|
|
1462
|
+
sidecarPath = profile.sidecar.path !== null
|
|
1463
|
+
? resolve(dirname(archivePath), profile.sidecar.path)
|
|
1464
|
+
: `${archivePath}.contract.json`;
|
|
1465
|
+
await writeFile(sidecarPath, sidecarJson);
|
|
1466
|
+
}
|
|
1467
|
+
await publishEarlyLibraryCache(cacheRoot, cacheOptions, {
|
|
1468
|
+
cPath,
|
|
1469
|
+
native: hit.native,
|
|
1470
|
+
frontend: hit.frontend,
|
|
1471
|
+
semantic: { mod, sources: hit.sourceTexts },
|
|
1472
|
+
...(irPath !== undefined ? { irPath } : {}),
|
|
1473
|
+
...(sidecarPath !== undefined ? { sidecarPath } : {}),
|
|
1474
|
+
}).catch(() => undefined);
|
|
1475
|
+
await pruneBuildCache(cacheRoot);
|
|
1476
|
+
timing("semantic-cache-publish");
|
|
1477
|
+
timing("complete");
|
|
1478
|
+
return {
|
|
1479
|
+
ok: true,
|
|
1480
|
+
archivePath,
|
|
1481
|
+
cPath,
|
|
1482
|
+
backend: profile.emission,
|
|
1483
|
+
...(irPath !== undefined ? { irPath } : {}),
|
|
1484
|
+
...(sidecarPath !== undefined ? { sidecarPath } : {}),
|
|
1485
|
+
};
|
|
1486
|
+
}
|
|
1205
1487
|
export async function compileLibrary(opts) {
|
|
1488
|
+
const frontendInputs = new FrontendInputTracker();
|
|
1489
|
+
return frontendInputs.run(() => compileLibraryTracked(opts, frontendInputs));
|
|
1490
|
+
}
|
|
1491
|
+
async function compileLibraryTracked(opts, frontendInputs) {
|
|
1206
1492
|
const timingOn = process.env["SCRIPTC_TIMING"] === "1";
|
|
1207
1493
|
const timingStart = performance.now();
|
|
1208
1494
|
let timingLast = timingStart;
|
|
@@ -1227,6 +1513,21 @@ export async function compileLibrary(opts) {
|
|
|
1227
1513
|
const profile = loadedProfile.profile;
|
|
1228
1514
|
const entryPath = profile.entry;
|
|
1229
1515
|
const buildPlatform = buildTargetPlatform();
|
|
1516
|
+
const profileDir = dirname(resolve(opts.profilePath));
|
|
1517
|
+
for (let directory = dirname(entryPath);; directory = dirname(directory)) {
|
|
1518
|
+
for (const name of ["tsconfig.json", "package.json"]) {
|
|
1519
|
+
// Project configuration and package-realm metadata can affect the
|
|
1520
|
+
// frontend even when TypeScript did not request their bytes through
|
|
1521
|
+
// its delegated filesystem callbacks (tsgo may read them server-side).
|
|
1522
|
+
frontendInputs.run(() => {
|
|
1523
|
+
const path = join(directory, name);
|
|
1524
|
+
trackedReadFile(path);
|
|
1525
|
+
});
|
|
1526
|
+
}
|
|
1527
|
+
if (directory === profileDir || dirname(directory) === directory)
|
|
1528
|
+
break;
|
|
1529
|
+
}
|
|
1530
|
+
const archivePath = opts.outPath ?? join(opts.outDir, `${basename(entryPath).replace(/\.(ts|js|mjs|cjs)$/, "")}.lib.a`);
|
|
1230
1531
|
// Mobile-target admission first — a pure env/host check, so a refused
|
|
1231
1532
|
// pairing never reaches toolchain discovery. iOS targets (device and
|
|
1232
1533
|
// simulator) build on darwin hosts only: the Apple SDK sysroot and the
|
|
@@ -1283,6 +1584,44 @@ export async function compileLibrary(opts) {
|
|
|
1283
1584
|
};
|
|
1284
1585
|
}
|
|
1285
1586
|
}
|
|
1587
|
+
const cacheRoot = provenanceSources() === null
|
|
1588
|
+
? await prepareBuildCacheRoot(buildCacheRoot())
|
|
1589
|
+
: null;
|
|
1590
|
+
const earlyCacheOptions = {
|
|
1591
|
+
profilePath: opts.profilePath,
|
|
1592
|
+
profileBytes: profile.profileBytes,
|
|
1593
|
+
entryPath,
|
|
1594
|
+
outDir: opts.outDir,
|
|
1595
|
+
...(opts.outPath !== undefined ? { outPath: opts.outPath } : {}),
|
|
1596
|
+
emitIr: opts.emitIr ?? false,
|
|
1597
|
+
sanitize: opts.sanitize ?? false,
|
|
1598
|
+
target: `${process.env["SCRIPTC_TARGET"] ?? "native"}:${buildPlatform}:${process.arch}`,
|
|
1599
|
+
compiler: [process.env["SCRIPTC_CC"] ?? "clang"],
|
|
1600
|
+
nodeVersion: process.version,
|
|
1601
|
+
implementation: await libraryFrontendImplementationFingerprint(),
|
|
1602
|
+
};
|
|
1603
|
+
const earlyHit = await readEarlyLibraryCache(cacheRoot, earlyCacheOptions, profile.sidecar === null ? undefined : profile.sidecar.path);
|
|
1604
|
+
if (earlyHit !== null) {
|
|
1605
|
+
timing("early-cache-hit");
|
|
1606
|
+
await compileLibraryNative(profile, earlyHit.cPath, archivePath, opts.sanitize ?? false, earlyHit.native);
|
|
1607
|
+
timing("native-archive");
|
|
1608
|
+
timing("complete");
|
|
1609
|
+
return {
|
|
1610
|
+
ok: true,
|
|
1611
|
+
archivePath,
|
|
1612
|
+
cPath: earlyHit.cPath,
|
|
1613
|
+
backend: earlyHit.native.backend,
|
|
1614
|
+
...(earlyHit.irPath !== undefined ? { irPath: earlyHit.irPath } : {}),
|
|
1615
|
+
...(earlyHit.sidecarPath !== undefined ? { sidecarPath: earlyHit.sidecarPath } : {}),
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1618
|
+
timing("early-cache-miss");
|
|
1619
|
+
const semanticHit = await readSemanticLibraryCache(cacheRoot, earlyCacheOptions, profile.sidecar === null ? undefined : profile.sidecar.path);
|
|
1620
|
+
if (semanticHit !== null) {
|
|
1621
|
+
timing("semantic-cache-hit", { changed_sources: semanticHit.changedSources.length });
|
|
1622
|
+
return emitSemanticLibraryHit(semanticHit, profile, opts, archivePath, cacheRoot, earlyCacheOptions, timing);
|
|
1623
|
+
}
|
|
1624
|
+
timing("semantic-cache-miss");
|
|
1286
1625
|
// Bare npm specifiers in a library graph take the STATIC-OR-REFUSE
|
|
1287
1626
|
// posture: "lib" runs the same auto-detection and eligibility bar as
|
|
1288
1627
|
// the executable lane's --npm-static (own .d.ts, unminified shipped JS,
|
|
@@ -1445,9 +1784,9 @@ export async function compileLibrary(opts) {
|
|
|
1445
1784
|
// The ask-2 contract sidecar rides the same invocation. Identity first
|
|
1446
1785
|
// (schema §2's worked build_id definition over compiler version, profile
|
|
1447
1786
|
// bytes, and the sorted canonical module graph; source_hash per the
|
|
1448
|
-
// profile's "module-graph" contract) — the u64 lands on the IR so
|
|
1449
|
-
//
|
|
1450
|
-
// records (V12's coherence by construction), then the projection into
|
|
1787
|
+
// profile's "module-graph" contract) — the u64 lands on the IR so native
|
|
1788
|
+
// archive assembly emits the identity getters from the ONE value the
|
|
1789
|
+
// sidecar records (V12's coherence by construction), then the projection into
|
|
1451
1790
|
// the schema (declaration orders from the AST) and the V1–V14
|
|
1452
1791
|
// self-check before anything is written.
|
|
1453
1792
|
let sidecarJson = null;
|
|
@@ -1532,41 +1871,8 @@ export async function compileLibrary(opts) {
|
|
|
1532
1871
|
irPath = join(opts.outDir, `${stem}.lib.ir.json`);
|
|
1533
1872
|
await writeFile(irPath, serializeModule(mod));
|
|
1534
1873
|
}
|
|
1535
|
-
const
|
|
1536
|
-
|
|
1537
|
-
// the mode-provided entries, the identity getters, and the export map —
|
|
1538
|
-
// is exactly the set the localization step keeps global.
|
|
1539
|
-
const localizeSymbols = profile.localizeRuntime
|
|
1540
|
-
? [
|
|
1541
|
-
profile.initSymbol,
|
|
1542
|
-
profile.sinkRegisterSymbol,
|
|
1543
|
-
...(profile.collectSymbol !== null ? [profile.collectSymbol] : []),
|
|
1544
|
-
...(profile.resultResetSymbol !== null ? [profile.resultResetSymbol] : []),
|
|
1545
|
-
...(profile.callbackRegisterSymbol !== null ? [profile.callbackRegisterSymbol] : []),
|
|
1546
|
-
...(profile.sidecar !== null
|
|
1547
|
-
? [profile.sidecar.buildIdSymbol, profile.sidecar.abiVersionSymbol]
|
|
1548
|
-
: []),
|
|
1549
|
-
...profile.exports.map((e) => e.symbol),
|
|
1550
|
-
]
|
|
1551
|
-
: undefined;
|
|
1552
|
-
await compileLibArchive({
|
|
1553
|
-
cPath,
|
|
1554
|
-
outPath: archivePath,
|
|
1555
|
-
cacheIdentity: "scriptc-generated-library-v1",
|
|
1556
|
-
sanitize: opts.sanitize ?? false,
|
|
1557
|
-
optimization: profile.optimization,
|
|
1558
|
-
...(localizeSymbols !== undefined ? { localizeSymbols } : {}),
|
|
1559
|
-
...(profile.instancePerThread ? { threadInstances: true } : {}),
|
|
1560
|
-
regex: moduleUsesRegex(mod),
|
|
1561
|
-
assert: moduleUsesAssert(mod),
|
|
1562
|
-
inspect: moduleUsesInspect(mod),
|
|
1563
|
-
symbol: moduleUsesSymbol(mod),
|
|
1564
|
-
searchParams: moduleUsesSearchParams(mod),
|
|
1565
|
-
emitter: moduleUsesEmitter(mod),
|
|
1566
|
-
zlib: moduleUsesZlib(mod),
|
|
1567
|
-
copying: moduleUsesCopying(mod),
|
|
1568
|
-
textDecoderLegacy: moduleUsesLegacyTextDecoder(mod),
|
|
1569
|
-
});
|
|
1874
|
+
const nativeFeatures = libraryNativeFeatures(mod, profile.emission);
|
|
1875
|
+
await compileLibraryNative(profile, cPath, archivePath, opts.sanitize ?? false, nativeFeatures);
|
|
1570
1876
|
timing("native-archive");
|
|
1571
1877
|
// The sidecar lands beside the compiled object, written by the same
|
|
1572
1878
|
// invocation (profile-declared name; the neutral default when the
|
|
@@ -1579,6 +1885,17 @@ export async function compileLibrary(opts) {
|
|
|
1579
1885
|
: `${archivePath}.contract.json`;
|
|
1580
1886
|
await writeFile(sidecarPath, sidecarJson);
|
|
1581
1887
|
}
|
|
1888
|
+
const earlyPublish = {
|
|
1889
|
+
cPath,
|
|
1890
|
+
native: nativeFeatures,
|
|
1891
|
+
frontend: frontendInputs.snapshot(),
|
|
1892
|
+
semantic: { mod, sources: sourceTexts },
|
|
1893
|
+
...(irPath !== undefined ? { irPath } : {}),
|
|
1894
|
+
...(sidecarPath !== undefined ? { sidecarPath } : {}),
|
|
1895
|
+
};
|
|
1896
|
+
await publishEarlyLibraryCache(cacheRoot, earlyCacheOptions, earlyPublish).catch(() => undefined);
|
|
1897
|
+
await pruneBuildCache(cacheRoot);
|
|
1898
|
+
timing("early-cache-publish");
|
|
1582
1899
|
timing("complete");
|
|
1583
1900
|
return {
|
|
1584
1901
|
ok: true,
|