@scriptc/compiler 0.0.32 → 0.0.34
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 +430 -1
- package/dist/backend/cc-cache.test.js.map +1 -1
- package/dist/backend/cc.d.ts +25 -0
- package/dist/backend/cc.js +818 -88
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emit-exprs.js +79 -3
- 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 +23 -7
- package/dist/backend/emission/emitter.js +171 -27
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/emission/may-throw.js +7 -4
- package/dist/backend/emission/may-throw.js.map +1 -1
- package/dist/backend/ffi-callbacks.d.ts +38 -1
- package/dist/backend/ffi-callbacks.js +76 -3
- package/dist/backend/ffi-callbacks.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 +278 -17
- 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/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 +37 -13
- package/dist/backend/object-localize.test.js.map +1 -1
- package/dist/diagnostics/diagnostic.js +2 -0
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/ffi/profile.d.ts +17 -5
- package/dist/ffi/profile.js +169 -22
- 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 +2 -8
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +1 -0
- package/dist/frontend/lowering/lower-calls.js +244 -163
- 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 +113 -28
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.js +67 -1
- 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-modules.js +1 -1
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +48 -3
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +79 -29
- package/dist/frontend/lowering/lowerer.js +429 -87
- package/dist/frontend/lowering/lowerer.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 +2 -6
- 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 +2 -0
- package/dist/frontend/ts7/checker.js +20 -3
- 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 +41 -0
- package/dist/frontend/types.js +147 -8
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +275 -41
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +42 -12
- package/dist/ir/nodes.js +7 -1
- 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 +104 -1
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/early-cache.d.ts +65 -0
- package/dist/library/early-cache.js +380 -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/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/profile.d.ts +3 -0
- package/dist/library/profile.js +9 -1
- package/dist/library/profile.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/package.json +2 -2
- package/surface-manifest.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
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, 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 { rebaseLibrarySourceComments, replaceLibraryIdentity, stripLibraryIdentity, stripLibrarySourceComments } from "./backend/library-identity.js";
|
|
6
7
|
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
8
|
import { checkLibraryIntegerSlots, classSeed, hasIntSlots, numberCarrierKind } from "./library/int-infer.js";
|
|
8
9
|
import { loadLibraryProfile, profileRemediation, profileTeaching } from "./library/profile.js";
|
|
9
10
|
import { decorateLibraryRefusals, evaluateLibraryFences } from "./library/fence-eval.js";
|
|
10
11
|
import { assembleTrapTeaching } from "./library/trap-teaching.js";
|
|
11
|
-
import { buildSidecar, canonicalModuleGraph, canonicalPath, compilerReleaseVersion, libraryIdentityHashes, } from "./library/sidecar.js";
|
|
12
|
+
import { buildSidecar, canonicalModuleGraph, canonicalPath, compilerReleaseVersion, libraryIdentityHashes, updateSidecarIdentity, } from "./library/sidecar.js";
|
|
12
13
|
import { validateSidecar } from "./library/sidecar-validate.js";
|
|
13
14
|
import { entryFunctionExports } from "./frontend/lib-exports.js";
|
|
14
15
|
import { entryContractFacts } from "./frontend/lib-contract.js";
|
|
@@ -18,10 +19,14 @@ import { validateModule } from "./ir/validate.js";
|
|
|
18
19
|
import { canonicalBuiltinModule, checkPreflight, isNodeTypesPath, loadProgram, locOf, requiresOf, resolveNpmImport } from "./frontend/program.js";
|
|
19
20
|
import { npmStaticIneligibleReason, npmStaticOffenders, npmStaticPackageOfPath } from "./frontend/npm-static.js";
|
|
20
21
|
import { provenanceSources } from "./frontend/provenance-registry.js";
|
|
21
|
-
import { resolveBareModule } from "./frontend/resolve.js";
|
|
22
|
+
import { clearResolveCaches, resolveBareModule } from "./frontend/resolve.js";
|
|
22
23
|
import { isJsSourceFileName, isRelativeSpecifier } from "./frontend/shared.js";
|
|
23
24
|
import { lowerToIr } from "./frontend/lowering/lowerer.js";
|
|
24
25
|
import { loadFfiProfile } from "./ffi/profile.js";
|
|
26
|
+
import { hasForeignFfiCallback } from "./backend/ffi-callbacks.js";
|
|
27
|
+
import { FrontendInputTracker, trackedReadFile } from "./frontend/input-tracker.js";
|
|
28
|
+
import { libraryFrontendImplementationFingerprint, publishEarlyLibraryCache, readEarlyLibraryCache, readSemanticLibraryCache } from "./library/early-cache.js";
|
|
29
|
+
import { createSourceLineRebaser } from "./library/semantic-source.js";
|
|
25
30
|
export const VERSION = "0.0.1";
|
|
26
31
|
export { compileC, runtimeSrcDir } from "./backend/cc.js";
|
|
27
32
|
export { ANDROID_MIN_API, IPHONEOS_MIN_VERSION, isAndroidTarget, isIosTarget, isMobileTarget, mobileLibraryTarget, mobileTargetRefusal } from "./backend/cc.js";
|
|
@@ -316,6 +321,11 @@ function packageNameOfBareSpecifier(specifier) {
|
|
|
316
321
|
* static-or-refuse teaching, and the detection closes over the opted-in
|
|
317
322
|
* packages' own bare edges (no island exists to serve a dep from). */
|
|
318
323
|
function runFrontend(entryPath, npmStatic, externalTypes) {
|
|
324
|
+
// Resolver package/workspace metadata is intentionally shared across the
|
|
325
|
+
// several load attempts of ONE auto-detection fixpoint, but never across
|
|
326
|
+
// separate compiles in a long-lived process. A cache miss must observe
|
|
327
|
+
// package.json edits before it can publish a new early-library entry.
|
|
328
|
+
clearResolveCaches();
|
|
319
329
|
const statuses = [];
|
|
320
330
|
const npmSites = new Map();
|
|
321
331
|
const judged = new Set();
|
|
@@ -844,6 +854,7 @@ export async function compile(entryPath, opts) {
|
|
|
844
854
|
dgram: moduleUsesDgram(lowered.module),
|
|
845
855
|
// The link switch for scr_watch.c: fs.watch/watcher.* libCalls on the IR.
|
|
846
856
|
watch: moduleUsesFsWatch(lowered.module),
|
|
857
|
+
foreignFfi: hasForeignFfiCallback(lowered.module.ffiImports ?? []),
|
|
847
858
|
// The link switch for scr_test.c: test.* libCalls on the IR.
|
|
848
859
|
nodeTest: moduleUsesNodeTest(lowered.module),
|
|
849
860
|
// The link switch for scr_tls.c + the vendored mbedTLS archive:
|
|
@@ -1200,14 +1211,205 @@ function mergeSidecarIntSlots(cfg, facts, mod) {
|
|
|
1200
1211
|
}
|
|
1201
1212
|
return { ok: true, config: cfg };
|
|
1202
1213
|
}
|
|
1214
|
+
function libraryNativeFeatures(mod, backend) {
|
|
1215
|
+
return {
|
|
1216
|
+
backend,
|
|
1217
|
+
regex: moduleUsesRegex(mod),
|
|
1218
|
+
assert: moduleUsesAssert(mod),
|
|
1219
|
+
inspect: moduleUsesInspect(mod),
|
|
1220
|
+
symbol: moduleUsesSymbol(mod),
|
|
1221
|
+
searchParams: moduleUsesSearchParams(mod),
|
|
1222
|
+
emitter: moduleUsesEmitter(mod),
|
|
1223
|
+
zlib: moduleUsesZlib(mod),
|
|
1224
|
+
copying: moduleUsesCopying(mod),
|
|
1225
|
+
textDecoderLegacy: moduleUsesLegacyTextDecoder(mod),
|
|
1226
|
+
...(mod.lib?.identity !== undefined ? { buildId: mod.lib.identity.buildId } : {}),
|
|
1227
|
+
};
|
|
1228
|
+
}
|
|
1229
|
+
function libraryLocalizeSymbols(profile) {
|
|
1230
|
+
return profile.localizeRuntime
|
|
1231
|
+
? [
|
|
1232
|
+
profile.initSymbol,
|
|
1233
|
+
profile.sinkRegisterSymbol,
|
|
1234
|
+
...(profile.collectSymbol !== null ? [profile.collectSymbol] : []),
|
|
1235
|
+
...(profile.resultResetSymbol !== null ? [profile.resultResetSymbol] : []),
|
|
1236
|
+
...(profile.callbackRegisterSymbol !== null ? [profile.callbackRegisterSymbol] : []),
|
|
1237
|
+
...(profile.sidecar !== null
|
|
1238
|
+
? [profile.sidecar.buildIdSymbol, profile.sidecar.abiVersionSymbol]
|
|
1239
|
+
: []),
|
|
1240
|
+
...profile.exports.map((entry) => entry.symbol),
|
|
1241
|
+
]
|
|
1242
|
+
: undefined;
|
|
1243
|
+
}
|
|
1244
|
+
async function compileLibraryNative(profile, cPath, archivePath, sanitize, features) {
|
|
1245
|
+
const localizeSymbols = libraryLocalizeSymbols(profile);
|
|
1246
|
+
let identityCSource;
|
|
1247
|
+
let programSource;
|
|
1248
|
+
if (profile.sidecar !== null || profile.emission === "c") {
|
|
1249
|
+
const publicSource = await readFile(cPath, "utf8");
|
|
1250
|
+
programSource = publicSource;
|
|
1251
|
+
}
|
|
1252
|
+
if (profile.sidecar !== null) {
|
|
1253
|
+
if (features.buildId === undefined)
|
|
1254
|
+
throw new Error("library identity TU has no build id");
|
|
1255
|
+
const withoutIdentity = stripLibraryIdentity(programSource, profile.emission);
|
|
1256
|
+
if (withoutIdentity === programSource) {
|
|
1257
|
+
throw new Error("generated public library TU has no identity region");
|
|
1258
|
+
}
|
|
1259
|
+
programSource = withoutIdentity;
|
|
1260
|
+
identityCSource = [
|
|
1261
|
+
"#include <stdint.h>",
|
|
1262
|
+
"#include <inttypes.h>",
|
|
1263
|
+
`uint64_t ${profile.sidecar.buildIdSymbol}(void) { return UINT64_C(0x${features.buildId}); }`,
|
|
1264
|
+
`uint32_t ${profile.sidecar.abiVersionSymbol}(void) { return ${profile.sidecar.abiVersion}u; }`,
|
|
1265
|
+
"",
|
|
1266
|
+
].join("\n");
|
|
1267
|
+
}
|
|
1268
|
+
if (profile.emission === "c") {
|
|
1269
|
+
programSource = stripLibrarySourceComments(programSource, profile.entry);
|
|
1270
|
+
}
|
|
1271
|
+
await compileLibArchive({
|
|
1272
|
+
cPath,
|
|
1273
|
+
...(programSource !== undefined ? { programSource } : {}),
|
|
1274
|
+
...(identityCSource !== undefined ? { identityCSource } : {}),
|
|
1275
|
+
outPath: archivePath,
|
|
1276
|
+
cacheIdentity: "scriptc-generated-library-v1",
|
|
1277
|
+
sanitize,
|
|
1278
|
+
optimization: profile.optimization,
|
|
1279
|
+
...(localizeSymbols !== undefined ? { localizeSymbols } : {}),
|
|
1280
|
+
...(profile.instancePerThread ? { threadInstances: true } : {}),
|
|
1281
|
+
regex: features.regex,
|
|
1282
|
+
assert: features.assert,
|
|
1283
|
+
inspect: features.inspect,
|
|
1284
|
+
symbol: features.symbol,
|
|
1285
|
+
searchParams: features.searchParams,
|
|
1286
|
+
emitter: features.emitter,
|
|
1287
|
+
zlib: features.zlib,
|
|
1288
|
+
copying: features.copying,
|
|
1289
|
+
textDecoderLegacy: features.textDecoderLegacy,
|
|
1290
|
+
});
|
|
1291
|
+
}
|
|
1292
|
+
async function emitSemanticLibraryHit(hit, profile, opts, archivePath, cacheRoot, cacheOptions, timing) {
|
|
1293
|
+
const mod = hit.mod;
|
|
1294
|
+
const rootDir = dirname(resolve(opts.profilePath));
|
|
1295
|
+
let sidecarJson = hit.sidecarJson;
|
|
1296
|
+
if (profile.sidecar !== null) {
|
|
1297
|
+
if (mod.lib?.identity === undefined || sidecarJson === null) {
|
|
1298
|
+
throw new Error("semantic library cache lost sidecar identity metadata");
|
|
1299
|
+
}
|
|
1300
|
+
const modules = canonicalModuleGraph(rootDir, hit.sourceTexts);
|
|
1301
|
+
const { buildId, sourceHash } = libraryIdentityHashes(compilerReleaseVersion(), profile.profileBytes, modules);
|
|
1302
|
+
mod.lib.identity.buildId = buildId;
|
|
1303
|
+
hit.native.buildId = buildId;
|
|
1304
|
+
sidecarJson = updateSidecarIdentity(sidecarJson, buildId, sourceHash);
|
|
1305
|
+
}
|
|
1306
|
+
const validation = validateModule(mod);
|
|
1307
|
+
if (validation.length > 0) {
|
|
1308
|
+
return {
|
|
1309
|
+
ok: false,
|
|
1310
|
+
diagnostics: validation.map((violation) => iceDiag(violation.message, violation.loc)),
|
|
1311
|
+
sourceTexts: hit.sourceTexts,
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
await mkdir(opts.outDir, { recursive: true });
|
|
1315
|
+
const stem = basename(profile.entry).replace(/\.(ts|js|mjs|cjs)$/, "");
|
|
1316
|
+
const cPath = join(opts.outDir, `${stem}.lib.${profile.emission === "llvm" ? "ll" : "c"}`);
|
|
1317
|
+
let translationUnit = hit.translationUnit;
|
|
1318
|
+
if (profile.sidecar !== null) {
|
|
1319
|
+
translationUnit = replaceLibraryIdentity(translationUnit, profile.emission, mod.lib.identity);
|
|
1320
|
+
}
|
|
1321
|
+
if (profile.emission === "llvm") {
|
|
1322
|
+
await writeFile(cPath, translationUnit);
|
|
1323
|
+
}
|
|
1324
|
+
else {
|
|
1325
|
+
const previous = hit.previousSources.get(mod.sourceFile);
|
|
1326
|
+
const current = hit.sourceTexts.get(mod.sourceFile);
|
|
1327
|
+
if (previous === undefined || current === undefined) {
|
|
1328
|
+
throw new Error("semantic library cache lost the entry source text");
|
|
1329
|
+
}
|
|
1330
|
+
translationUnit = rebaseLibrarySourceComments(translationUnit, mod.sourceFile, createSourceLineRebaser(mod.sourceFile, previous, current));
|
|
1331
|
+
await writeFile(cPath, translationUnit);
|
|
1332
|
+
}
|
|
1333
|
+
timing("semantic-tu-restore", { output_bytes: Buffer.byteLength(translationUnit) });
|
|
1334
|
+
await rm(join(opts.outDir, `${stem}.lib.${profile.emission === "llvm" ? "c" : "ll"}`), { force: true });
|
|
1335
|
+
let irPath;
|
|
1336
|
+
if (opts.emitIr) {
|
|
1337
|
+
irPath = join(opts.outDir, `${stem}.lib.ir.json`);
|
|
1338
|
+
await writeFile(irPath, serializeModule(mod));
|
|
1339
|
+
}
|
|
1340
|
+
await compileLibraryNative(profile, cPath, archivePath, opts.sanitize ?? false, hit.native);
|
|
1341
|
+
timing("native-archive");
|
|
1342
|
+
let sidecarPath;
|
|
1343
|
+
if (sidecarJson !== null) {
|
|
1344
|
+
sidecarPath = profile.sidecar.path !== null
|
|
1345
|
+
? resolve(dirname(archivePath), profile.sidecar.path)
|
|
1346
|
+
: `${archivePath}.contract.json`;
|
|
1347
|
+
await writeFile(sidecarPath, sidecarJson);
|
|
1348
|
+
}
|
|
1349
|
+
await publishEarlyLibraryCache(cacheRoot, cacheOptions, {
|
|
1350
|
+
cPath,
|
|
1351
|
+
native: hit.native,
|
|
1352
|
+
frontend: hit.frontend,
|
|
1353
|
+
semantic: { mod, sources: hit.sourceTexts },
|
|
1354
|
+
...(irPath !== undefined ? { irPath } : {}),
|
|
1355
|
+
...(sidecarPath !== undefined ? { sidecarPath } : {}),
|
|
1356
|
+
}).catch(() => undefined);
|
|
1357
|
+
await pruneBuildCache(cacheRoot);
|
|
1358
|
+
timing("semantic-cache-publish");
|
|
1359
|
+
timing("complete");
|
|
1360
|
+
return {
|
|
1361
|
+
ok: true,
|
|
1362
|
+
archivePath,
|
|
1363
|
+
cPath,
|
|
1364
|
+
backend: profile.emission,
|
|
1365
|
+
...(irPath !== undefined ? { irPath } : {}),
|
|
1366
|
+
...(sidecarPath !== undefined ? { sidecarPath } : {}),
|
|
1367
|
+
};
|
|
1368
|
+
}
|
|
1203
1369
|
export async function compileLibrary(opts) {
|
|
1370
|
+
const frontendInputs = new FrontendInputTracker();
|
|
1371
|
+
return frontendInputs.run(() => compileLibraryTracked(opts, frontendInputs));
|
|
1372
|
+
}
|
|
1373
|
+
async function compileLibraryTracked(opts, frontendInputs) {
|
|
1374
|
+
const timingOn = process.env["SCRIPTC_TIMING"] === "1";
|
|
1375
|
+
const timingStart = performance.now();
|
|
1376
|
+
let timingLast = timingStart;
|
|
1377
|
+
const timing = (phase, detail = {}) => {
|
|
1378
|
+
if (!timingOn)
|
|
1379
|
+
return;
|
|
1380
|
+
const now = performance.now();
|
|
1381
|
+
process.stderr.write(`scriptc timing ${JSON.stringify({
|
|
1382
|
+
phase,
|
|
1383
|
+
phase_ms: Math.round((now - timingLast) * 10) / 10,
|
|
1384
|
+
total_ms: Math.round((now - timingStart) * 10) / 10,
|
|
1385
|
+
rss_mb: Math.round(process.memoryUsage().rss / 1024 / 1024),
|
|
1386
|
+
...detail,
|
|
1387
|
+
})}\n`);
|
|
1388
|
+
timingLast = now;
|
|
1389
|
+
};
|
|
1204
1390
|
const loadedProfile = loadLibraryProfile(resolve(opts.profilePath));
|
|
1391
|
+
timing("profile-load");
|
|
1205
1392
|
if (!loadedProfile.ok) {
|
|
1206
1393
|
return { ok: false, diagnostics: loadedProfile.diagnostics, sourceTexts: new Map() };
|
|
1207
1394
|
}
|
|
1208
1395
|
const profile = loadedProfile.profile;
|
|
1209
1396
|
const entryPath = profile.entry;
|
|
1210
1397
|
const buildPlatform = buildTargetPlatform();
|
|
1398
|
+
const profileDir = dirname(resolve(opts.profilePath));
|
|
1399
|
+
for (let directory = dirname(entryPath);; directory = dirname(directory)) {
|
|
1400
|
+
for (const name of ["tsconfig.json", "package.json"]) {
|
|
1401
|
+
// Project configuration and package-realm metadata can affect the
|
|
1402
|
+
// frontend even when TypeScript did not request their bytes through
|
|
1403
|
+
// its delegated filesystem callbacks (tsgo may read them server-side).
|
|
1404
|
+
frontendInputs.run(() => {
|
|
1405
|
+
const path = join(directory, name);
|
|
1406
|
+
trackedReadFile(path);
|
|
1407
|
+
});
|
|
1408
|
+
}
|
|
1409
|
+
if (directory === profileDir || dirname(directory) === directory)
|
|
1410
|
+
break;
|
|
1411
|
+
}
|
|
1412
|
+
const archivePath = opts.outPath ?? join(opts.outDir, `${basename(entryPath).replace(/\.(ts|js|mjs|cjs)$/, "")}.lib.a`);
|
|
1211
1413
|
// Mobile-target admission first — a pure env/host check, so a refused
|
|
1212
1414
|
// pairing never reaches toolchain discovery. iOS targets (device and
|
|
1213
1415
|
// simulator) build on darwin hosts only: the Apple SDK sysroot and the
|
|
@@ -1264,6 +1466,44 @@ export async function compileLibrary(opts) {
|
|
|
1264
1466
|
};
|
|
1265
1467
|
}
|
|
1266
1468
|
}
|
|
1469
|
+
const cacheRoot = provenanceSources() === null
|
|
1470
|
+
? await prepareBuildCacheRoot(buildCacheRoot())
|
|
1471
|
+
: null;
|
|
1472
|
+
const earlyCacheOptions = {
|
|
1473
|
+
profilePath: opts.profilePath,
|
|
1474
|
+
profileBytes: profile.profileBytes,
|
|
1475
|
+
entryPath,
|
|
1476
|
+
outDir: opts.outDir,
|
|
1477
|
+
...(opts.outPath !== undefined ? { outPath: opts.outPath } : {}),
|
|
1478
|
+
emitIr: opts.emitIr ?? false,
|
|
1479
|
+
sanitize: opts.sanitize ?? false,
|
|
1480
|
+
target: `${process.env["SCRIPTC_TARGET"] ?? "native"}:${buildPlatform}:${process.arch}`,
|
|
1481
|
+
compiler: [process.env["SCRIPTC_CC"] ?? "clang"],
|
|
1482
|
+
nodeVersion: process.version,
|
|
1483
|
+
implementation: await libraryFrontendImplementationFingerprint(),
|
|
1484
|
+
};
|
|
1485
|
+
const earlyHit = await readEarlyLibraryCache(cacheRoot, earlyCacheOptions, profile.sidecar === null ? undefined : profile.sidecar.path);
|
|
1486
|
+
if (earlyHit !== null) {
|
|
1487
|
+
timing("early-cache-hit");
|
|
1488
|
+
await compileLibraryNative(profile, earlyHit.cPath, archivePath, opts.sanitize ?? false, earlyHit.native);
|
|
1489
|
+
timing("native-archive");
|
|
1490
|
+
timing("complete");
|
|
1491
|
+
return {
|
|
1492
|
+
ok: true,
|
|
1493
|
+
archivePath,
|
|
1494
|
+
cPath: earlyHit.cPath,
|
|
1495
|
+
backend: earlyHit.native.backend,
|
|
1496
|
+
...(earlyHit.irPath !== undefined ? { irPath: earlyHit.irPath } : {}),
|
|
1497
|
+
...(earlyHit.sidecarPath !== undefined ? { sidecarPath: earlyHit.sidecarPath } : {}),
|
|
1498
|
+
};
|
|
1499
|
+
}
|
|
1500
|
+
timing("early-cache-miss");
|
|
1501
|
+
const semanticHit = await readSemanticLibraryCache(cacheRoot, earlyCacheOptions, profile.sidecar === null ? undefined : profile.sidecar.path);
|
|
1502
|
+
if (semanticHit !== null) {
|
|
1503
|
+
timing("semantic-cache-hit", { changed_sources: semanticHit.changedSources.length });
|
|
1504
|
+
return emitSemanticLibraryHit(semanticHit, profile, opts, archivePath, cacheRoot, earlyCacheOptions, timing);
|
|
1505
|
+
}
|
|
1506
|
+
timing("semantic-cache-miss");
|
|
1267
1507
|
// Bare npm specifiers in a library graph take the STATIC-OR-REFUSE
|
|
1268
1508
|
// posture: "lib" runs the same auto-detection and eligibility bar as
|
|
1269
1509
|
// the executable lane's --npm-static (own .d.ts, unminified shipped JS,
|
|
@@ -1271,6 +1511,10 @@ export async function compileLibrary(opts) {
|
|
|
1271
1511
|
// island/dynamic tier to offer (SC4006's ground), so eligibility needs
|
|
1272
1512
|
// no flag and a miss is a refusal, never a fallback.
|
|
1273
1513
|
const fe = runFrontend(entryPath, "lib");
|
|
1514
|
+
timing("frontend-load", {
|
|
1515
|
+
entry_bytes: fe.entryText().length,
|
|
1516
|
+
source_files: fe.sourceTexts().size,
|
|
1517
|
+
});
|
|
1274
1518
|
let lowered;
|
|
1275
1519
|
let entryText;
|
|
1276
1520
|
let sourceTexts;
|
|
@@ -1372,6 +1616,9 @@ export async function compileLibrary(opts) {
|
|
|
1372
1616
|
]),
|
|
1373
1617
|
],
|
|
1374
1618
|
});
|
|
1619
|
+
timing("lower", {
|
|
1620
|
+
lib_roots: profile.exports.length + contractSurfaceRoots.length,
|
|
1621
|
+
});
|
|
1375
1622
|
}
|
|
1376
1623
|
catch (e) {
|
|
1377
1624
|
if (!isCheckerPanic(e))
|
|
@@ -1388,6 +1635,7 @@ export async function compileLibrary(opts) {
|
|
|
1388
1635
|
fe.dispose();
|
|
1389
1636
|
}
|
|
1390
1637
|
const mod = lowered.module;
|
|
1638
|
+
timing("frontend-dispose");
|
|
1391
1639
|
const fail = (diagnostics) => ({
|
|
1392
1640
|
ok: false,
|
|
1393
1641
|
diagnostics: decorateLibraryRefusals(diagnostics, profile),
|
|
@@ -1418,9 +1666,9 @@ export async function compileLibrary(opts) {
|
|
|
1418
1666
|
// The ask-2 contract sidecar rides the same invocation. Identity first
|
|
1419
1667
|
// (schema §2's worked build_id definition over compiler version, profile
|
|
1420
1668
|
// bytes, and the sorted canonical module graph; source_hash per the
|
|
1421
|
-
// profile's "module-graph" contract) — the u64 lands on the IR so
|
|
1422
|
-
//
|
|
1423
|
-
// records (V12's coherence by construction), then the projection into
|
|
1669
|
+
// profile's "module-graph" contract) — the u64 lands on the IR so native
|
|
1670
|
+
// archive assembly emits the identity getters from the ONE value the
|
|
1671
|
+
// sidecar records (V12's coherence by construction), then the projection into
|
|
1424
1672
|
// the schema (declaration orders from the AST) and the V1–V14
|
|
1425
1673
|
// self-check before anything is written.
|
|
1426
1674
|
let sidecarJson = null;
|
|
@@ -1457,6 +1705,7 @@ export async function compileLibrary(opts) {
|
|
|
1457
1705
|
return fail([merged.diagnostic]);
|
|
1458
1706
|
intCfg = merged.config;
|
|
1459
1707
|
}
|
|
1708
|
+
timing("contract-sidecar", { source_files: sourceTexts.size });
|
|
1460
1709
|
// Ask 4: the integer-boundary inference — every value that can reach a
|
|
1461
1710
|
// profile-declared i64/u64 slot must PROVE representability, wholeness,
|
|
1462
1711
|
// and range, or the build refuses with the failed obligation, the
|
|
@@ -1471,17 +1720,21 @@ export async function compileLibrary(opts) {
|
|
|
1471
1720
|
return fail(refusals.map((v) => libIntBoundaryDiag(v.path, v.cls, v.obligation, v.detail, v.fix, v.loc)));
|
|
1472
1721
|
}
|
|
1473
1722
|
}
|
|
1723
|
+
timing("integer-proof");
|
|
1474
1724
|
const validation = validateModule(mod);
|
|
1475
1725
|
if (validation.length > 0)
|
|
1476
1726
|
return fail(validation.map((v) => iceDiag(v.message, v.loc)));
|
|
1727
|
+
timing("ir-validate");
|
|
1477
1728
|
await mkdir(opts.outDir, { recursive: true });
|
|
1478
1729
|
const stem = basename(entryPath).replace(/\.(ts|js|mjs|cjs)$/, "");
|
|
1479
1730
|
let cPath;
|
|
1480
1731
|
if (profile.emission === "llvm") {
|
|
1481
1732
|
try {
|
|
1482
1733
|
const ll = emitLlvmModule(mod);
|
|
1734
|
+
timing("llvm-emit", { output_bytes: Buffer.byteLength(ll) });
|
|
1483
1735
|
cPath = join(opts.outDir, `${stem}.lib.ll`);
|
|
1484
1736
|
await writeFile(cPath, ll);
|
|
1737
|
+
timing("llvm-write");
|
|
1485
1738
|
}
|
|
1486
1739
|
catch (err) {
|
|
1487
1740
|
if (!(err instanceof LlvmUnsupportedError))
|
|
@@ -1500,40 +1753,9 @@ export async function compileLibrary(opts) {
|
|
|
1500
1753
|
irPath = join(opts.outDir, `${stem}.lib.ir.json`);
|
|
1501
1754
|
await writeFile(irPath, serializeModule(mod));
|
|
1502
1755
|
}
|
|
1503
|
-
const
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
// is exactly the set the localization step keeps global.
|
|
1507
|
-
const localizeSymbols = profile.localizeRuntime
|
|
1508
|
-
? [
|
|
1509
|
-
profile.initSymbol,
|
|
1510
|
-
profile.sinkRegisterSymbol,
|
|
1511
|
-
...(profile.collectSymbol !== null ? [profile.collectSymbol] : []),
|
|
1512
|
-
...(profile.resultResetSymbol !== null ? [profile.resultResetSymbol] : []),
|
|
1513
|
-
...(profile.callbackRegisterSymbol !== null ? [profile.callbackRegisterSymbol] : []),
|
|
1514
|
-
...(profile.sidecar !== null
|
|
1515
|
-
? [profile.sidecar.buildIdSymbol, profile.sidecar.abiVersionSymbol]
|
|
1516
|
-
: []),
|
|
1517
|
-
...profile.exports.map((e) => e.symbol),
|
|
1518
|
-
]
|
|
1519
|
-
: undefined;
|
|
1520
|
-
await compileLibArchive({
|
|
1521
|
-
cPath,
|
|
1522
|
-
outPath: archivePath,
|
|
1523
|
-
cacheIdentity: "scriptc-generated-library-v1",
|
|
1524
|
-
sanitize: opts.sanitize ?? false,
|
|
1525
|
-
...(localizeSymbols !== undefined ? { localizeSymbols } : {}),
|
|
1526
|
-
...(profile.instancePerThread ? { threadInstances: true } : {}),
|
|
1527
|
-
regex: moduleUsesRegex(mod),
|
|
1528
|
-
assert: moduleUsesAssert(mod),
|
|
1529
|
-
inspect: moduleUsesInspect(mod),
|
|
1530
|
-
symbol: moduleUsesSymbol(mod),
|
|
1531
|
-
searchParams: moduleUsesSearchParams(mod),
|
|
1532
|
-
emitter: moduleUsesEmitter(mod),
|
|
1533
|
-
zlib: moduleUsesZlib(mod),
|
|
1534
|
-
copying: moduleUsesCopying(mod),
|
|
1535
|
-
textDecoderLegacy: moduleUsesLegacyTextDecoder(mod),
|
|
1536
|
-
});
|
|
1756
|
+
const nativeFeatures = libraryNativeFeatures(mod, profile.emission);
|
|
1757
|
+
await compileLibraryNative(profile, cPath, archivePath, opts.sanitize ?? false, nativeFeatures);
|
|
1758
|
+
timing("native-archive");
|
|
1537
1759
|
// The sidecar lands beside the compiled object, written by the same
|
|
1538
1760
|
// invocation (profile-declared name; the neutral default when the
|
|
1539
1761
|
// profile states none is <out>.contract.json).
|
|
@@ -1545,6 +1767,18 @@ export async function compileLibrary(opts) {
|
|
|
1545
1767
|
: `${archivePath}.contract.json`;
|
|
1546
1768
|
await writeFile(sidecarPath, sidecarJson);
|
|
1547
1769
|
}
|
|
1770
|
+
const earlyPublish = {
|
|
1771
|
+
cPath,
|
|
1772
|
+
native: nativeFeatures,
|
|
1773
|
+
frontend: frontendInputs.snapshot(),
|
|
1774
|
+
semantic: { mod, sources: sourceTexts },
|
|
1775
|
+
...(irPath !== undefined ? { irPath } : {}),
|
|
1776
|
+
...(sidecarPath !== undefined ? { sidecarPath } : {}),
|
|
1777
|
+
};
|
|
1778
|
+
await publishEarlyLibraryCache(cacheRoot, earlyCacheOptions, earlyPublish).catch(() => undefined);
|
|
1779
|
+
await pruneBuildCache(cacheRoot);
|
|
1780
|
+
timing("early-cache-publish");
|
|
1781
|
+
timing("complete");
|
|
1548
1782
|
return {
|
|
1549
1783
|
ok: true,
|
|
1550
1784
|
archivePath,
|