@shapeshift-labs/frontier-lang-compiler 0.2.20 → 0.2.22
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/README.md +25 -1
- package/bench/smoke.mjs +17 -1
- package/dist/index.d.ts +53 -0
- package/dist/index.js +512 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -64,6 +64,25 @@ console.log(readiness.readiness);
|
|
|
64
64
|
|
|
65
65
|
The loss taxonomy separates broad scanner limits from specific round-trip risks such as conditional compilation, reflection, overload/type-inference gaps, comments/trivia preservation, source-map approximation, parser diagnostics, and target projection loss. These records are evidence labels for merge admission; they are not claims that the lightweight scanner expanded macros, evaluated inactive branches, resolved overloads, or ran a type checker.
|
|
66
66
|
|
|
67
|
+
High-risk native features also have explicit evidence policies. These policies are advisory in this package: they tell a swarm or admission queue what evidence is missing without silently changing the existing readiness classification.
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
import {
|
|
71
|
+
getNativeImportFeatureEvidencePolicy,
|
|
72
|
+
summarizeNativeImportFeatureEvidence
|
|
73
|
+
} from '@shapeshift-labs/frontier-lang-compiler';
|
|
74
|
+
|
|
75
|
+
const policy = getNativeImportFeatureEvidencePolicy('preprocessor');
|
|
76
|
+
console.log(policy.requiredEvidenceKeys); // ["preprocessedOutputHash", "definesHash"]
|
|
77
|
+
|
|
78
|
+
const featureEvidence = summarizeNativeImportFeatureEvidence(imported.losses, {
|
|
79
|
+
evidence: imported.evidence
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
console.log(featureEvidence.highestRisk);
|
|
83
|
+
console.log(featureEvidence.missingRequiredEvidence);
|
|
84
|
+
```
|
|
85
|
+
|
|
67
86
|
Ask the compiler what is actually covered before sending native imports into a merge queue:
|
|
68
87
|
|
|
69
88
|
```js
|
|
@@ -183,15 +202,18 @@ console.log(compiledJs.readiness.readiness); // scanner imports can still be "ne
|
|
|
183
202
|
|
|
184
203
|
const rustCandidate = compileNativeSource(compiledJs.importResult, {
|
|
185
204
|
target: 'rust',
|
|
205
|
+
targetPath: 'dist/runtime.rs',
|
|
186
206
|
emitOnBlocked: true
|
|
187
207
|
});
|
|
188
208
|
|
|
189
209
|
console.log(rustCandidate.outputMode); // "target-stubs"
|
|
190
210
|
console.log(rustCandidate.targetCoverage.lossClass); // "missingAdapter" without a JS-to-Rust adapter
|
|
191
211
|
console.log(rustCandidate.ok); // true only because emitOnBlocked requested code anyway
|
|
212
|
+
console.log(rustCandidate.sourceMap.targetPath); // "dist/runtime.rs"
|
|
213
|
+
console.log(rustCandidate.sourceMap.mappings[0]?.semanticSymbolId); // generated span -> source symbol
|
|
192
214
|
```
|
|
193
215
|
|
|
194
|
-
`compileNativeSource` returns the import result, projection, target loss matrix cell, combined losses, readiness, evidence, and output hash. Admission queues should treat `ok` as "code was emitted", not as merge approval; `readiness` and
|
|
216
|
+
`compileNativeSource` returns the import result, projection, target loss matrix cell, combined losses, readiness, evidence, output hash, and generated-output source maps. Same-language preserved output uses exact source mappings when the hash matches; generated stubs use declaration-level spans; adapter output uses adapter-supplied maps when present and otherwise gets an estimated fallback. Admission queues should treat `ok` as "code was emitted", not as merge approval; `readiness`, `targetCoverage`, and source-map precision carry the merge signal.
|
|
195
217
|
|
|
196
218
|
Provide a target projection adapter when the host owns real native-to-target translation semantics:
|
|
197
219
|
|
|
@@ -220,12 +242,14 @@ const jsToRustAdapter = {
|
|
|
220
242
|
|
|
221
243
|
const rustWithAdapter = compileNativeSource(compiledJs.importResult, {
|
|
222
244
|
target: 'rust',
|
|
245
|
+
targetPath: 'dist/runtime.rs',
|
|
223
246
|
targetAdapters: [jsToRustAdapter]
|
|
224
247
|
});
|
|
225
248
|
|
|
226
249
|
console.log(rustWithAdapter.outputMode); // "target-adapter"
|
|
227
250
|
console.log(rustWithAdapter.targetCoverage.lossClass); // "targetAdapterProjection"
|
|
228
251
|
console.log(rustWithAdapter.targetProjection.adapter.id); // "app-js-to-rust"
|
|
252
|
+
console.log(rustWithAdapter.sourceMaps.length); // adapter maps or compiler fallback map
|
|
229
253
|
```
|
|
230
254
|
|
|
231
255
|
Project a native import back to source. Exact source is preserved when the import carries matching source-preservation evidence or when supplied text matches the import hash; otherwise the compiler emits declaration stubs with review-required loss evidence:
|
package/bench/smoke.mjs
CHANGED
|
@@ -9,7 +9,8 @@ import {
|
|
|
9
9
|
createSemanticImportSidecar,
|
|
10
10
|
importNativeSource,
|
|
11
11
|
projectNativeImportToSource,
|
|
12
|
-
runNativeImporterAdapter
|
|
12
|
+
runNativeImporterAdapter,
|
|
13
|
+
summarizeNativeImportFeatureEvidence
|
|
13
14
|
} from '../dist/index.js';
|
|
14
15
|
|
|
15
16
|
const source = `
|
|
@@ -88,6 +89,13 @@ const semanticSidecars = nativeImportResults.map((imported) => createSemanticImp
|
|
|
88
89
|
const sidecarDurationMs = performance.now() - sidecarStart;
|
|
89
90
|
const sidecarOwnershipRegions = semanticSidecars.reduce((sum, sidecar) => sum + sidecar.ownershipRegions.length, 0);
|
|
90
91
|
|
|
92
|
+
const featureEvidenceStart = performance.now();
|
|
93
|
+
const featureEvidenceSummaries = nativeImportResults.map((imported) => summarizeNativeImportFeatureEvidence(imported.losses, {
|
|
94
|
+
evidence: imported.evidence
|
|
95
|
+
}));
|
|
96
|
+
const featureEvidenceDurationMs = performance.now() - featureEvidenceStart;
|
|
97
|
+
const featureEvidencePolicyMatches = featureEvidenceSummaries.reduce((sum, summary) => sum + summary.total, 0);
|
|
98
|
+
|
|
91
99
|
const projectionStart = performance.now();
|
|
92
100
|
const nativeProjections = nativeImportResults.map((imported) => projectNativeImportToSource(imported));
|
|
93
101
|
const projectionDurationMs = performance.now() - projectionStart;
|
|
@@ -100,6 +108,8 @@ const nativeCompiles = nativeImportResults.map((imported, index) => compileNativ
|
|
|
100
108
|
}));
|
|
101
109
|
const nativeCompileDurationMs = performance.now() - nativeCompileStart;
|
|
102
110
|
const nativeCompileBytes = nativeCompiles.reduce((sum, result) => sum + result.output.length, 0);
|
|
111
|
+
const nativeCompileSourceMaps = nativeCompiles.reduce((sum, result) => sum + result.sourceMaps.length, 0);
|
|
112
|
+
const nativeCompileSourceMapMappings = nativeCompiles.reduce((sum, result) => sum + result.sourceMaps.reduce((mapSum, sourceMap) => mapSum + sourceMap.mappings.length, 0), 0);
|
|
103
113
|
const nativeCompileBlocked = nativeCompiles.filter((result) => result.readiness.readiness === 'blocked').length;
|
|
104
114
|
const nativeTargetAdapterStart = performance.now();
|
|
105
115
|
const nativeTargetAdapterCompiles = nativeImportResults.slice(0, 25).map((imported, index) => {
|
|
@@ -122,6 +132,7 @@ const nativeTargetAdapterCompiles = nativeImportResults.slice(0, 25).map((import
|
|
|
122
132
|
});
|
|
123
133
|
const nativeTargetAdapterDurationMs = performance.now() - nativeTargetAdapterStart;
|
|
124
134
|
const nativeTargetAdapterBytes = nativeTargetAdapterCompiles.reduce((sum, result) => sum + result.output.length, 0);
|
|
135
|
+
const nativeTargetAdapterSourceMaps = nativeTargetAdapterCompiles.reduce((sum, result) => sum + result.sourceMaps.length, 0);
|
|
125
136
|
|
|
126
137
|
console.log(JSON.stringify({
|
|
127
138
|
compiles: 250,
|
|
@@ -147,14 +158,19 @@ console.log(JSON.stringify({
|
|
|
147
158
|
semanticSidecars: semanticSidecars.length,
|
|
148
159
|
sidecarOwnershipRegions,
|
|
149
160
|
sidecarDurationMs: Number(sidecarDurationMs.toFixed(2)),
|
|
161
|
+
featureEvidencePolicyMatches,
|
|
162
|
+
featureEvidenceDurationMs: Number(featureEvidenceDurationMs.toFixed(2)),
|
|
150
163
|
nativeProjections: nativeProjections.length,
|
|
151
164
|
projectionBytes,
|
|
152
165
|
projectionDurationMs: Number(projectionDurationMs.toFixed(2)),
|
|
153
166
|
nativeCompiles: nativeCompiles.length,
|
|
154
167
|
nativeCompileBytes,
|
|
168
|
+
nativeCompileSourceMaps,
|
|
169
|
+
nativeCompileSourceMapMappings,
|
|
155
170
|
nativeCompileBlocked,
|
|
156
171
|
nativeCompileDurationMs: Number(nativeCompileDurationMs.toFixed(2)),
|
|
157
172
|
nativeTargetAdapterCompiles: nativeTargetAdapterCompiles.length,
|
|
158
173
|
nativeTargetAdapterBytes,
|
|
174
|
+
nativeTargetAdapterSourceMaps,
|
|
159
175
|
nativeTargetAdapterDurationMs: Number(nativeTargetAdapterDurationMs.toFixed(2))
|
|
160
176
|
}));
|
package/dist/index.d.ts
CHANGED
|
@@ -151,6 +151,49 @@ export interface NativeImportLossSummaryOptions {
|
|
|
151
151
|
readonly semanticStatus?: string;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
export type NativeImportFeatureEvidenceRisk = 'low' | 'medium' | 'high' | 'critical' | string;
|
|
155
|
+
|
|
156
|
+
export interface NativeImportFeatureEvidencePolicy {
|
|
157
|
+
readonly kind: NativeImportKnownLossKind;
|
|
158
|
+
readonly category: NativeImportTaxonomyKind;
|
|
159
|
+
readonly risk: NativeImportFeatureEvidenceRisk;
|
|
160
|
+
readonly minimumReadiness: SemanticMergeReadiness;
|
|
161
|
+
readonly missingEvidenceReadiness: SemanticMergeReadiness;
|
|
162
|
+
readonly requiredEvidenceKeys: readonly string[];
|
|
163
|
+
readonly recommendedEvidenceKeys: readonly string[];
|
|
164
|
+
readonly notes: readonly string[];
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export interface NativeImportFeatureEvidenceIssue {
|
|
168
|
+
readonly lossId: string;
|
|
169
|
+
readonly kind: NativeImportKnownLossKind;
|
|
170
|
+
readonly policyKind: NativeImportKnownLossKind;
|
|
171
|
+
readonly risk: NativeImportFeatureEvidenceRisk;
|
|
172
|
+
readonly category: NativeImportTaxonomyKind;
|
|
173
|
+
readonly readiness: SemanticMergeReadiness;
|
|
174
|
+
readonly missingRequiredEvidence: readonly string[];
|
|
175
|
+
readonly presentRequiredEvidence: readonly string[];
|
|
176
|
+
readonly presentRecommendedEvidence: readonly string[];
|
|
177
|
+
readonly evidenceIds: readonly string[];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export interface NativeImportFeatureEvidenceSummary {
|
|
181
|
+
readonly total: number;
|
|
182
|
+
readonly policyKinds: readonly NativeImportKnownLossKind[];
|
|
183
|
+
readonly byKind: Readonly<Record<string, number>>;
|
|
184
|
+
readonly byRisk: Readonly<Record<string, number>>;
|
|
185
|
+
readonly highestRisk: NativeImportFeatureEvidenceRisk;
|
|
186
|
+
readonly semanticMergeReadiness: SemanticMergeReadiness;
|
|
187
|
+
readonly missingRequiredEvidence: readonly {
|
|
188
|
+
readonly lossId: string;
|
|
189
|
+
readonly kind: NativeImportKnownLossKind;
|
|
190
|
+
readonly policyKind: NativeImportKnownLossKind;
|
|
191
|
+
readonly evidenceKey: string;
|
|
192
|
+
}[];
|
|
193
|
+
readonly issues: readonly NativeImportFeatureEvidenceIssue[];
|
|
194
|
+
readonly reasons: readonly string[];
|
|
195
|
+
}
|
|
196
|
+
|
|
154
197
|
export interface NativeImportLossSummary {
|
|
155
198
|
readonly total: number;
|
|
156
199
|
readonly hasLosses: boolean;
|
|
@@ -165,6 +208,7 @@ export interface NativeImportLossSummary {
|
|
|
165
208
|
readonly reviewLossIds: readonly string[];
|
|
166
209
|
readonly informationalLossIds: readonly string[];
|
|
167
210
|
readonly failedEvidenceIds: readonly string[];
|
|
211
|
+
readonly featureEvidence: NativeImportFeatureEvidenceSummary;
|
|
168
212
|
readonly parser?: string;
|
|
169
213
|
readonly scanKind?: string;
|
|
170
214
|
readonly semanticStatus?: string;
|
|
@@ -1331,6 +1375,10 @@ export interface CompileNativeSourceOptions extends ProjectNativeImportToSourceO
|
|
|
1331
1375
|
readonly languages?: readonly NativeImportLanguageProfile[];
|
|
1332
1376
|
readonly generatedAt?: number;
|
|
1333
1377
|
readonly emitOnBlocked?: boolean;
|
|
1378
|
+
readonly emitSourceMap?: boolean;
|
|
1379
|
+
readonly targetPath?: string;
|
|
1380
|
+
readonly targetHash?: string;
|
|
1381
|
+
readonly sourceMapId?: string;
|
|
1334
1382
|
readonly projectionId?: string;
|
|
1335
1383
|
readonly projectionEvidenceId?: string;
|
|
1336
1384
|
readonly compileEvidenceId?: string;
|
|
@@ -1349,6 +1397,8 @@ export interface NativeSourceCompileResult {
|
|
|
1349
1397
|
readonly output: string;
|
|
1350
1398
|
readonly outputHash: string;
|
|
1351
1399
|
readonly outputMode: NativeSourceCompileOutputMode;
|
|
1400
|
+
readonly sourceMap?: SourceMapRecord;
|
|
1401
|
+
readonly sourceMaps: readonly SourceMapRecord[];
|
|
1352
1402
|
readonly importResult: NativeSourceImportResult;
|
|
1353
1403
|
readonly projection: NativeSourceProjectionResult;
|
|
1354
1404
|
readonly targetProjection?: NativeTargetProjectionResult;
|
|
@@ -1422,6 +1472,7 @@ export declare const NativeImportLossKinds: readonly NativeImportKnownLossKind[]
|
|
|
1422
1472
|
export declare const NativeImportRegionTaxonomyKinds: readonly NativeImportRegionTaxonomyKind[];
|
|
1423
1473
|
export declare const ProjectionTargetLossClasses: readonly ProjectionTargetLossClass[];
|
|
1424
1474
|
export declare const NativeImportReadinessBySeverity: Readonly<Record<NativeImportLossSummary['highestSeverity'], SemanticMergeReadiness>>;
|
|
1475
|
+
export declare const NativeImportFeatureEvidencePolicies: Readonly<Record<string, NativeImportFeatureEvidencePolicy>>;
|
|
1425
1476
|
export declare const NativeImportLanguageProfiles: readonly NativeImportLanguageProfile[];
|
|
1426
1477
|
export declare function normalizeCompileTarget(target?: string): FrontierCompileTarget;
|
|
1427
1478
|
export declare function compileFrontierSource(source: string, options?: FrontierCompileOptions): FrontierCompileResult;
|
|
@@ -1432,6 +1483,8 @@ export declare function renderTargetAst(ast: FrontierTargetAst, target?: Frontie
|
|
|
1432
1483
|
export declare function renderTargetAstWithSourceMap(ast: FrontierTargetAst, target?: FrontierCompileOptions['target'], options?: FrontierCompileEmitOptions): FrontierTargetSourceMapResult;
|
|
1433
1484
|
export declare function emitForTargetWithSourceMap(document: FrontierLangDocument, target?: FrontierCompileOptions['target'], options?: FrontierCompileEmitOptions): FrontierTargetDocumentSourceMapResult;
|
|
1434
1485
|
export declare function resolveCapabilityAdapters(document: FrontierLangDocument, target?: FrontierCompileOptions['target'], options?: { readonly platform?: string }): readonly CapabilityResolution[];
|
|
1486
|
+
export declare function getNativeImportFeatureEvidencePolicy(kind: NativeImportKnownLossKind | string): NativeImportFeatureEvidencePolicy | undefined;
|
|
1487
|
+
export declare function summarizeNativeImportFeatureEvidence(losses?: readonly NativeAstLossRecord[], options?: NativeImportLossSummaryOptions): NativeImportFeatureEvidenceSummary;
|
|
1435
1488
|
export declare function summarizeNativeImportLosses(losses?: readonly NativeAstLossRecord[], options?: NativeImportLossSummaryOptions): NativeImportLossSummary;
|
|
1436
1489
|
export declare function classifyNativeImportReadiness(losses?: readonly NativeAstLossRecord[], options?: NativeImportLossSummaryOptions): NativeImportReadinessClassification;
|
|
1437
1490
|
export declare function classifyNativeImportRoundtripReadiness(importResult: NativeSourceImportResult | NativeProjectImportResult, options?: NativeImportRoundtripReadinessOptions): NativeImportRoundtripReadinessClassification;
|
package/dist/index.js
CHANGED
|
@@ -76,6 +76,13 @@ const semanticMergeReadinessRank = Object.freeze({
|
|
|
76
76
|
blocked: 3
|
|
77
77
|
});
|
|
78
78
|
|
|
79
|
+
const nativeFeatureEvidenceRiskRank = Object.freeze({
|
|
80
|
+
low: 0,
|
|
81
|
+
medium: 1,
|
|
82
|
+
high: 2,
|
|
83
|
+
critical: 3
|
|
84
|
+
});
|
|
85
|
+
|
|
79
86
|
export const NativeImportRoundtripReadinessStatuses = Object.freeze([
|
|
80
87
|
'exact',
|
|
81
88
|
'preserved-source',
|
|
@@ -136,6 +143,117 @@ export const NativeImportReadinessBySeverity = Object.freeze({
|
|
|
136
143
|
error: 'blocked'
|
|
137
144
|
});
|
|
138
145
|
|
|
146
|
+
export const NativeImportFeatureEvidencePolicies = Object.freeze({
|
|
147
|
+
macroExpansion: nativeImportFeatureEvidencePolicy('macroExpansion', {
|
|
148
|
+
category: 'macroExpansion',
|
|
149
|
+
risk: 'high',
|
|
150
|
+
minimumReadiness: 'needs-review',
|
|
151
|
+
requiredEvidenceKeys: ['macroDefinitionsHash', 'expandedSourceHash'],
|
|
152
|
+
recommendedEvidenceKeys: ['expansionMapId', 'sourceMapId', 'macroCallSites'],
|
|
153
|
+
notes: ['Macro-expanded code must retain a link from generated output back to macro call sites before semantic merges can be trusted.']
|
|
154
|
+
}),
|
|
155
|
+
macroHygiene: nativeImportFeatureEvidencePolicy('macroHygiene', {
|
|
156
|
+
category: 'macroExpansion',
|
|
157
|
+
risk: 'critical',
|
|
158
|
+
minimumReadiness: 'needs-review',
|
|
159
|
+
missingEvidenceReadiness: 'blocked',
|
|
160
|
+
requiredEvidenceKeys: ['hygieneContextHash', 'bindingMapId'],
|
|
161
|
+
recommendedEvidenceKeys: ['expansionMapId', 'captureSetHash'],
|
|
162
|
+
notes: ['Hygiene-sensitive macros can change binding identity even when emitted text looks equivalent.']
|
|
163
|
+
}),
|
|
164
|
+
preprocessor: nativeImportFeatureEvidencePolicy('preprocessor', {
|
|
165
|
+
category: 'preprocessor',
|
|
166
|
+
risk: 'high',
|
|
167
|
+
minimumReadiness: 'needs-review',
|
|
168
|
+
requiredEvidenceKeys: ['preprocessedOutputHash', 'definesHash'],
|
|
169
|
+
recommendedEvidenceKeys: ['includeGraphHash', 'conditionalBranches', 'sourceMapId'],
|
|
170
|
+
notes: ['Preprocessor imports need the active defines/includes and preprocessed output hash to make replayable claims.']
|
|
171
|
+
}),
|
|
172
|
+
conditionalCompilation: nativeImportFeatureEvidencePolicy('conditionalCompilation', {
|
|
173
|
+
category: 'conditionalCompilation',
|
|
174
|
+
risk: 'high',
|
|
175
|
+
minimumReadiness: 'needs-review',
|
|
176
|
+
requiredEvidenceKeys: ['activeBranches', 'inactiveBranchesHash'],
|
|
177
|
+
recommendedEvidenceKeys: ['compileTarget', 'featureFlags', 'preprocessedOutputHash'],
|
|
178
|
+
notes: ['Conditional branches that were not active still affect portability and conflict review.']
|
|
179
|
+
}),
|
|
180
|
+
metaprogramming: nativeImportFeatureEvidencePolicy('metaprogramming', {
|
|
181
|
+
category: 'metaprogramming',
|
|
182
|
+
risk: 'critical',
|
|
183
|
+
minimumReadiness: 'needs-review',
|
|
184
|
+
missingEvidenceReadiness: 'blocked',
|
|
185
|
+
requiredEvidenceKeys: ['generatedArtifactHash', 'generatorIdentity'],
|
|
186
|
+
recommendedEvidenceKeys: ['generatorInputsHash', 'generatedRanges', 'replayCommand'],
|
|
187
|
+
notes: ['Generated or metaprogrammed declarations need replayable generator identity and input evidence.']
|
|
188
|
+
}),
|
|
189
|
+
reflection: nativeImportFeatureEvidencePolicy('reflection', {
|
|
190
|
+
category: 'reflection',
|
|
191
|
+
risk: 'high',
|
|
192
|
+
minimumReadiness: 'needs-review',
|
|
193
|
+
requiredEvidenceKeys: ['reflectionSurface', 'runtimeContract'],
|
|
194
|
+
recommendedEvidenceKeys: ['observedMembers', 'fixtureIds', 'runtimeVersion'],
|
|
195
|
+
notes: ['Reflection-heavy code needs a declared runtime contract because static AST evidence is incomplete.']
|
|
196
|
+
}),
|
|
197
|
+
dynamicRuntime: nativeImportFeatureEvidencePolicy('dynamicRuntime', {
|
|
198
|
+
category: 'reflection',
|
|
199
|
+
risk: 'high',
|
|
200
|
+
minimumReadiness: 'needs-review',
|
|
201
|
+
requiredEvidenceKeys: ['runtimeContract'],
|
|
202
|
+
recommendedEvidenceKeys: ['fixtureIds', 'observedEffects', 'runtimeVersion'],
|
|
203
|
+
notes: ['Dynamic runtime behavior should stay review-required until fixtures or traces describe the observed contract.']
|
|
204
|
+
}),
|
|
205
|
+
dynamicDispatch: nativeImportFeatureEvidencePolicy('dynamicDispatch', {
|
|
206
|
+
category: 'overloadTypeInference',
|
|
207
|
+
risk: 'medium',
|
|
208
|
+
minimumReadiness: 'needs-review',
|
|
209
|
+
requiredEvidenceKeys: ['dispatchTargets'],
|
|
210
|
+
recommendedEvidenceKeys: ['callGraphId', 'typeEvidenceId', 'fixtureIds'],
|
|
211
|
+
notes: ['Dynamic dispatch needs candidate target evidence before call graph or porting claims are merge-ready.']
|
|
212
|
+
}),
|
|
213
|
+
generatedCode: nativeImportFeatureEvidencePolicy('generatedCode', {
|
|
214
|
+
category: 'generatedCode',
|
|
215
|
+
risk: 'high',
|
|
216
|
+
minimumReadiness: 'needs-review',
|
|
217
|
+
requiredEvidenceKeys: ['generatedArtifactHash', 'generatedRanges'],
|
|
218
|
+
recommendedEvidenceKeys: ['generatorIdentity', 'generatorInputsHash', 'sourceMapId'],
|
|
219
|
+
notes: ['Generated code must preserve generated ranges and artifact hashes so workers can avoid editing derived output blindly.']
|
|
220
|
+
}),
|
|
221
|
+
overloadResolution: nativeImportFeatureEvidencePolicy('overloadResolution', {
|
|
222
|
+
category: 'overloadTypeInference',
|
|
223
|
+
risk: 'medium',
|
|
224
|
+
minimumReadiness: 'needs-review',
|
|
225
|
+
requiredEvidenceKeys: ['resolvedOverloads'],
|
|
226
|
+
recommendedEvidenceKeys: ['typeEvidenceId', 'compilerVersion', 'callSiteSpans'],
|
|
227
|
+
notes: ['Overload-sensitive imports should record compiler/type evidence for each call site.']
|
|
228
|
+
}),
|
|
229
|
+
typeInference: nativeImportFeatureEvidencePolicy('typeInference', {
|
|
230
|
+
category: 'overloadTypeInference',
|
|
231
|
+
risk: 'medium',
|
|
232
|
+
minimumReadiness: 'needs-review',
|
|
233
|
+
requiredEvidenceKeys: ['inferredTypesHash'],
|
|
234
|
+
recommendedEvidenceKeys: ['typeEvidenceId', 'compilerVersion', 'symbolTableHash'],
|
|
235
|
+
notes: ['Inferred types need a stable type-evidence hash before cross-language projection can claim fidelity.']
|
|
236
|
+
}),
|
|
237
|
+
unsupportedSyntax: nativeImportFeatureEvidencePolicy('unsupportedSyntax', {
|
|
238
|
+
category: 'unsupportedSyntax',
|
|
239
|
+
risk: 'high',
|
|
240
|
+
minimumReadiness: 'needs-review',
|
|
241
|
+
missingEvidenceReadiness: 'blocked',
|
|
242
|
+
requiredEvidenceKeys: ['unsupportedSyntaxKind', 'sourceSpan'],
|
|
243
|
+
recommendedEvidenceKeys: ['parserDiagnosticId', 'nativeAstNodeId', 'sourceSnippetHash'],
|
|
244
|
+
notes: ['Unsupported syntax must remain anchored to source spans and parser diagnostics for later adapter work.']
|
|
245
|
+
}),
|
|
246
|
+
unsupportedSemantic: nativeImportFeatureEvidencePolicy('unsupportedSemantic', {
|
|
247
|
+
category: 'unsupportedSyntax',
|
|
248
|
+
risk: 'high',
|
|
249
|
+
minimumReadiness: 'needs-review',
|
|
250
|
+
missingEvidenceReadiness: 'blocked',
|
|
251
|
+
requiredEvidenceKeys: ['unsupportedSemanticKind', 'semanticSymbolId'],
|
|
252
|
+
recommendedEvidenceKeys: ['semanticIndexId', 'sourceMapId', 'reason'],
|
|
253
|
+
notes: ['Unsupported semantics should name the affected symbol so merge tools can isolate the unsafe region.']
|
|
254
|
+
})
|
|
255
|
+
});
|
|
256
|
+
|
|
139
257
|
export const NativeImportRegionTaxonomyKinds = Object.freeze([
|
|
140
258
|
'symbol',
|
|
141
259
|
'declaration',
|
|
@@ -359,6 +477,25 @@ export function compileNativeSource(input, options = {}) {
|
|
|
359
477
|
scanKind: 'native-source-compile',
|
|
360
478
|
semanticStatus: importResult.metadata?.semanticStatus ?? options.semanticStatus
|
|
361
479
|
});
|
|
480
|
+
const sourceMaps = options.emitSourceMap === false
|
|
481
|
+
? []
|
|
482
|
+
: nativeSourceCompileSourceMaps({
|
|
483
|
+
id: options.sourceMapId ?? `source_map_${idFragment(id)}_${idFragment(target)}`,
|
|
484
|
+
importResult,
|
|
485
|
+
projection,
|
|
486
|
+
targetProjection,
|
|
487
|
+
sourceLanguage,
|
|
488
|
+
target,
|
|
489
|
+
targetPath: options.targetPath ?? targetProjection?.targetPath,
|
|
490
|
+
targetHash: options.targetHash ?? outputHash,
|
|
491
|
+
output,
|
|
492
|
+
outputHash,
|
|
493
|
+
outputMode,
|
|
494
|
+
evidence,
|
|
495
|
+
losses,
|
|
496
|
+
compileResultId: id
|
|
497
|
+
});
|
|
498
|
+
const sourceMap = sourceMaps[0];
|
|
362
499
|
return {
|
|
363
500
|
kind: 'frontier.lang.nativeSourceCompileResult',
|
|
364
501
|
version: 1,
|
|
@@ -370,6 +507,8 @@ export function compileNativeSource(input, options = {}) {
|
|
|
370
507
|
output,
|
|
371
508
|
outputHash,
|
|
372
509
|
outputMode,
|
|
510
|
+
sourceMap,
|
|
511
|
+
sourceMaps,
|
|
373
512
|
importResult,
|
|
374
513
|
projection,
|
|
375
514
|
targetProjection,
|
|
@@ -388,8 +527,13 @@ export function compileNativeSource(input, options = {}) {
|
|
|
388
527
|
projectionId: projection.id,
|
|
389
528
|
targetProjectionId: targetProjection?.id,
|
|
390
529
|
targetProjectionAdapterId: targetProjection?.adapter?.id,
|
|
530
|
+
sourceMapId: sourceMap?.id,
|
|
531
|
+
sourceMapIds: sourceMaps.map((record) => record.id).filter(Boolean),
|
|
532
|
+
sourceMapMappings: sourceMaps.reduce((sum, record) => sum + (record.mappings?.length ?? 0), 0),
|
|
391
533
|
projectionMode: projection.mode,
|
|
392
534
|
outputMode,
|
|
535
|
+
targetPath: sourceMap?.targetPath ?? options.targetPath ?? targetProjection?.targetPath,
|
|
536
|
+
targetHash: sourceMap?.targetHash ?? options.targetHash ?? outputHash,
|
|
393
537
|
sourceTarget,
|
|
394
538
|
sameSourceTarget,
|
|
395
539
|
targetLossClass: targetCoverage.lossClass,
|
|
@@ -447,6 +591,70 @@ export function resolveCapabilityAdapters(document, target = 'typescript', optio
|
|
|
447
591
|
});
|
|
448
592
|
}
|
|
449
593
|
|
|
594
|
+
export function getNativeImportFeatureEvidencePolicy(kind) {
|
|
595
|
+
const normalized = normalizeNativeLossKind({ kind }, 'warning');
|
|
596
|
+
return NativeImportFeatureEvidencePolicies[normalized] ?? NativeImportFeatureEvidencePolicies[String(kind ?? '')];
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
export function summarizeNativeImportFeatureEvidence(losses = [], options = {}) {
|
|
600
|
+
const normalizedLosses = normalizeNativeLossRecords(losses);
|
|
601
|
+
const evidence = options.evidence ?? [];
|
|
602
|
+
const issues = [];
|
|
603
|
+
const byKind = {};
|
|
604
|
+
const byRisk = {};
|
|
605
|
+
const policyKinds = [];
|
|
606
|
+
let highestRisk = 'low';
|
|
607
|
+
let semanticMergeReadiness = 'ready';
|
|
608
|
+
|
|
609
|
+
for (const loss of normalizedLosses) {
|
|
610
|
+
const policy = getNativeImportFeatureEvidencePolicy(loss.kind);
|
|
611
|
+
if (!policy) continue;
|
|
612
|
+
byKind[policy.kind] = (byKind[policy.kind] ?? 0) + 1;
|
|
613
|
+
byRisk[policy.risk] = (byRisk[policy.risk] ?? 0) + 1;
|
|
614
|
+
if ((nativeFeatureEvidenceRiskRank[policy.risk] ?? 0) > (nativeFeatureEvidenceRiskRank[highestRisk] ?? 0)) {
|
|
615
|
+
highestRisk = policy.risk;
|
|
616
|
+
}
|
|
617
|
+
policyKinds.push(policy.kind);
|
|
618
|
+
semanticMergeReadiness = maxSemanticMergeReadiness(semanticMergeReadiness, policy.minimumReadiness);
|
|
619
|
+
const missingRequiredEvidence = policy.requiredEvidenceKeys.filter((key) => !nativeImportFeatureEvidenceHasKey(loss, evidence, key));
|
|
620
|
+
const presentRequiredEvidence = policy.requiredEvidenceKeys.filter((key) => !missingRequiredEvidence.includes(key));
|
|
621
|
+
const presentRecommendedEvidence = policy.recommendedEvidenceKeys.filter((key) => nativeImportFeatureEvidenceHasKey(loss, evidence, key));
|
|
622
|
+
if (missingRequiredEvidence.length) {
|
|
623
|
+
semanticMergeReadiness = maxSemanticMergeReadiness(semanticMergeReadiness, policy.missingEvidenceReadiness);
|
|
624
|
+
}
|
|
625
|
+
issues.push({
|
|
626
|
+
lossId: loss.id,
|
|
627
|
+
kind: loss.kind,
|
|
628
|
+
policyKind: policy.kind,
|
|
629
|
+
risk: policy.risk,
|
|
630
|
+
category: policy.category,
|
|
631
|
+
readiness: missingRequiredEvidence.length ? policy.missingEvidenceReadiness : policy.minimumReadiness,
|
|
632
|
+
missingRequiredEvidence,
|
|
633
|
+
presentRequiredEvidence,
|
|
634
|
+
presentRecommendedEvidence,
|
|
635
|
+
evidenceIds: nativeImportFeatureEvidenceIds(loss, evidence, policy)
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
const missingRequiredEvidence = issues.flatMap((issue) => issue.missingRequiredEvidence.map((key) => ({
|
|
640
|
+
lossId: issue.lossId,
|
|
641
|
+
kind: issue.kind,
|
|
642
|
+
policyKind: issue.policyKind,
|
|
643
|
+
evidenceKey: key
|
|
644
|
+
})));
|
|
645
|
+
return {
|
|
646
|
+
total: issues.length,
|
|
647
|
+
policyKinds: uniqueStrings(policyKinds),
|
|
648
|
+
byKind,
|
|
649
|
+
byRisk,
|
|
650
|
+
highestRisk: issues.length ? highestRisk : 'low',
|
|
651
|
+
semanticMergeReadiness,
|
|
652
|
+
missingRequiredEvidence,
|
|
653
|
+
issues,
|
|
654
|
+
reasons: nativeImportFeatureEvidenceReasons(issues)
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
|
|
450
658
|
export function summarizeNativeImportLosses(losses = [], options = {}) {
|
|
451
659
|
const normalizedLosses = normalizeNativeLossRecords(losses);
|
|
452
660
|
const bySeverity = { info: 0, warning: 0, error: 0 };
|
|
@@ -486,6 +694,9 @@ export function summarizeNativeImportLosses(losses = [], options = {}) {
|
|
|
486
694
|
reviewLossIds,
|
|
487
695
|
informationalLossIds
|
|
488
696
|
});
|
|
697
|
+
const featureEvidence = summarizeNativeImportFeatureEvidence(normalizedLosses, {
|
|
698
|
+
evidence: options.evidence
|
|
699
|
+
});
|
|
489
700
|
|
|
490
701
|
return {
|
|
491
702
|
total: normalizedLosses.length,
|
|
@@ -501,6 +712,7 @@ export function summarizeNativeImportLosses(losses = [], options = {}) {
|
|
|
501
712
|
reviewLossIds,
|
|
502
713
|
informationalLossIds,
|
|
503
714
|
failedEvidenceIds,
|
|
715
|
+
featureEvidence,
|
|
504
716
|
parser: options.parser,
|
|
505
717
|
scanKind: options.scanKind,
|
|
506
718
|
semanticStatus: options.semanticStatus
|
|
@@ -4086,6 +4298,61 @@ function nativeImportCategoryForLossKind(kind) {
|
|
|
4086
4298
|
return String(kind ?? 'opaqueNative');
|
|
4087
4299
|
}
|
|
4088
4300
|
|
|
4301
|
+
function nativeImportFeatureEvidencePolicy(kind, input = {}) {
|
|
4302
|
+
return Object.freeze({
|
|
4303
|
+
kind,
|
|
4304
|
+
category: input.category ?? nativeImportCategoryForLossKind(kind),
|
|
4305
|
+
risk: input.risk ?? 'medium',
|
|
4306
|
+
minimumReadiness: normalizeSemanticMergeReadiness(input.minimumReadiness) ?? 'needs-review',
|
|
4307
|
+
missingEvidenceReadiness: normalizeSemanticMergeReadiness(input.missingEvidenceReadiness) ?? 'needs-review',
|
|
4308
|
+
requiredEvidenceKeys: Object.freeze(uniqueStrings(input.requiredEvidenceKeys ?? [])),
|
|
4309
|
+
recommendedEvidenceKeys: Object.freeze(uniqueStrings(input.recommendedEvidenceKeys ?? [])),
|
|
4310
|
+
notes: Object.freeze(uniqueStrings(input.notes ?? []))
|
|
4311
|
+
});
|
|
4312
|
+
}
|
|
4313
|
+
|
|
4314
|
+
function nativeImportFeatureEvidenceHasKey(loss, evidence, key) {
|
|
4315
|
+
return nativeImportFeatureEvidenceValuePresent(nativeImportFeatureEvidenceValue(loss, key))
|
|
4316
|
+
|| (evidence ?? []).some((record) => nativeImportFeatureEvidenceValuePresent(nativeImportFeatureEvidenceValue(record, key)));
|
|
4317
|
+
}
|
|
4318
|
+
|
|
4319
|
+
function nativeImportFeatureEvidenceValue(record, key) {
|
|
4320
|
+
if (!record || !key) return undefined;
|
|
4321
|
+
const candidates = [record, record.metadata].filter(Boolean);
|
|
4322
|
+
for (const candidate of candidates) {
|
|
4323
|
+
const direct = candidate[key];
|
|
4324
|
+
if (direct !== undefined) return direct;
|
|
4325
|
+
const dotted = String(key).split('.').reduce((current, part) => current?.[part], candidate);
|
|
4326
|
+
if (dotted !== undefined) return dotted;
|
|
4327
|
+
}
|
|
4328
|
+
return undefined;
|
|
4329
|
+
}
|
|
4330
|
+
|
|
4331
|
+
function nativeImportFeatureEvidenceValuePresent(value) {
|
|
4332
|
+
if (value === undefined || value === null) return false;
|
|
4333
|
+
if (typeof value === 'string') return value.trim().length > 0;
|
|
4334
|
+
if (Array.isArray(value)) return value.length > 0;
|
|
4335
|
+
if (typeof value === 'object') return Object.keys(value).length > 0;
|
|
4336
|
+
return true;
|
|
4337
|
+
}
|
|
4338
|
+
|
|
4339
|
+
function nativeImportFeatureEvidenceIds(loss, evidence, policy) {
|
|
4340
|
+
const keys = [...policy.requiredEvidenceKeys, ...policy.recommendedEvidenceKeys];
|
|
4341
|
+
return uniqueStrings((evidence ?? [])
|
|
4342
|
+
.filter((record) => keys.some((key) => nativeImportFeatureEvidenceValuePresent(nativeImportFeatureEvidenceValue(record, key))))
|
|
4343
|
+
.map((record) => record.id)
|
|
4344
|
+
.filter(Boolean)
|
|
4345
|
+
.concat(loss.evidenceIds ?? []));
|
|
4346
|
+
}
|
|
4347
|
+
|
|
4348
|
+
function nativeImportFeatureEvidenceReasons(issues) {
|
|
4349
|
+
return uniqueStrings((issues ?? []).flatMap((issue) => {
|
|
4350
|
+
const missing = issue.missingRequiredEvidence ?? [];
|
|
4351
|
+
if (!missing.length) return [];
|
|
4352
|
+
return [`${issue.kind} loss ${issue.lossId} is missing required evidence: ${missing.join(', ')}.`];
|
|
4353
|
+
}));
|
|
4354
|
+
}
|
|
4355
|
+
|
|
4089
4356
|
function normalizeProjectionMatrixTargets(targets) {
|
|
4090
4357
|
return uniqueStrings((Array.isArray(targets) ? targets : [targets])
|
|
4091
4358
|
.map((target) => {
|
|
@@ -4544,6 +4811,251 @@ function nativeSourceCompileEvidence(input) {
|
|
|
4544
4811
|
};
|
|
4545
4812
|
}
|
|
4546
4813
|
|
|
4814
|
+
function nativeSourceCompileSourceMaps(input) {
|
|
4815
|
+
const adapterSourceMaps = input.targetProjection?.sourceMaps ?? [];
|
|
4816
|
+
if (adapterSourceMaps.length) return adapterSourceMaps;
|
|
4817
|
+
const targetPath = nativeSourceCompileTargetPath(input);
|
|
4818
|
+
const targetHash = input.targetHash ?? input.outputHash;
|
|
4819
|
+
const target = nativeSourceCompileMapTarget(input, targetPath);
|
|
4820
|
+
const mappings = input.projection.mode === 'preserved-source'
|
|
4821
|
+
? nativeSourceCompilePreservedMappings({ ...input, targetPath, targetHash, target })
|
|
4822
|
+
: nativeSourceCompileDeclarationMappings({ ...input, targetPath, targetHash, target });
|
|
4823
|
+
const resolvedMappings = mappings.length
|
|
4824
|
+
? mappings
|
|
4825
|
+
: [nativeSourceCompileFileMapping({ ...input, targetPath, targetHash, target })];
|
|
4826
|
+
return [createSourceMapRecord({
|
|
4827
|
+
id: input.id,
|
|
4828
|
+
sourcePath: input.importResult.sourcePath ?? input.importResult.nativeSource?.sourcePath,
|
|
4829
|
+
sourceHash: input.importResult.nativeSource?.sourceHash ?? input.importResult.nativeAst?.sourceHash ?? input.importResult.sourceHash,
|
|
4830
|
+
target,
|
|
4831
|
+
targetPath: targetPath ?? commonGeneratedTargetPath(resolvedMappings),
|
|
4832
|
+
targetHash,
|
|
4833
|
+
semanticIndexId: input.importResult.semanticIndex?.id ?? input.importResult.universalAst?.semanticIndex?.id,
|
|
4834
|
+
universalAstId: input.importResult.universalAst?.id,
|
|
4835
|
+
nativeAstId: input.importResult.nativeAst?.id ?? input.importResult.nativeSource?.ast?.id,
|
|
4836
|
+
nativeSourceId: input.importResult.nativeSource?.id,
|
|
4837
|
+
mappings: resolvedMappings,
|
|
4838
|
+
evidence: input.evidence ?? [],
|
|
4839
|
+
metadata: {
|
|
4840
|
+
compileResultId: input.compileResultId,
|
|
4841
|
+
importId: input.importResult.id,
|
|
4842
|
+
projectionId: input.projection.id,
|
|
4843
|
+
targetProjectionId: input.targetProjection?.id,
|
|
4844
|
+
targetProjectionAdapterId: input.targetProjection?.adapter?.id,
|
|
4845
|
+
sourceLanguage: input.sourceLanguage,
|
|
4846
|
+
target: input.target,
|
|
4847
|
+
outputMode: input.outputMode,
|
|
4848
|
+
outputHash: input.outputHash,
|
|
4849
|
+
generatedBy: 'compileNativeSource'
|
|
4850
|
+
}
|
|
4851
|
+
})];
|
|
4852
|
+
}
|
|
4853
|
+
|
|
4854
|
+
function nativeSourceCompilePreservedMappings(input) {
|
|
4855
|
+
const sourceMaps = input.importResult.sourceMaps ?? input.importResult.universalAst?.sourceMaps ?? [];
|
|
4856
|
+
const sourceHash = input.importResult.nativeSource?.sourceHash ?? input.importResult.nativeAst?.sourceHash ?? input.importResult.sourceHash;
|
|
4857
|
+
const exact = input.projection.mode === 'preserved-source' && (!input.projection.sourceHash || input.outputHash === input.projection.sourceHash);
|
|
4858
|
+
const usedIds = new Set();
|
|
4859
|
+
return sourceMaps
|
|
4860
|
+
.flatMap((sourceMap) => sourceMap?.mappings ?? [])
|
|
4861
|
+
.filter((mapping) => mapping?.sourceSpan)
|
|
4862
|
+
.map((mapping, index) => ({
|
|
4863
|
+
id: reserveUniqueId(`compile_map_${idFragment(mapping.id ?? mapping.semanticSymbolId ?? mapping.nativeAstNodeId ?? index + 1)}`, usedIds),
|
|
4864
|
+
nativeSourceId: mapping.nativeSourceId ?? input.importResult.nativeSource?.id,
|
|
4865
|
+
nativeAstNodeId: mapping.nativeAstNodeId,
|
|
4866
|
+
semanticSymbolId: mapping.semanticSymbolId,
|
|
4867
|
+
semanticOccurrenceId: mapping.semanticOccurrenceId,
|
|
4868
|
+
semanticNodeId: mapping.semanticNodeId,
|
|
4869
|
+
mergeCandidateId: mapping.mergeCandidateId,
|
|
4870
|
+
sourceSpan: {
|
|
4871
|
+
...mapping.sourceSpan,
|
|
4872
|
+
sourceId: mapping.sourceSpan.sourceId ?? sourceHash,
|
|
4873
|
+
path: mapping.sourceSpan.path ?? input.importResult.sourcePath ?? input.importResult.nativeSource?.sourcePath
|
|
4874
|
+
},
|
|
4875
|
+
generatedSpan: nativeSourceCompileGeneratedSpanFromSource(mapping.sourceSpan, input, mapping.generatedName),
|
|
4876
|
+
target: input.target,
|
|
4877
|
+
generatedName: mapping.generatedName,
|
|
4878
|
+
evidenceIds: uniqueStrings([
|
|
4879
|
+
...(mapping.evidenceIds ?? []),
|
|
4880
|
+
...(input.evidence ?? []).map((record) => record.id).filter(Boolean)
|
|
4881
|
+
]),
|
|
4882
|
+
lossIds: uniqueStrings([
|
|
4883
|
+
...(mapping.lossIds ?? []),
|
|
4884
|
+
...lossIdsForNativeNode(input.losses ?? [], mapping.nativeAstNodeId)
|
|
4885
|
+
]),
|
|
4886
|
+
ownershipRegionId: mapping.ownershipRegionId,
|
|
4887
|
+
ownershipRegionKey: mapping.ownershipRegionKey,
|
|
4888
|
+
ownershipRegionKind: mapping.ownershipRegionKind,
|
|
4889
|
+
precision: exact ? 'exact' : mapping.precision === 'exact' ? 'line' : mapping.precision ?? 'line',
|
|
4890
|
+
metadata: {
|
|
4891
|
+
...mapping.metadata,
|
|
4892
|
+
compileResultId: input.compileResultId,
|
|
4893
|
+
sourceMapOrigin: 'preserved-source'
|
|
4894
|
+
}
|
|
4895
|
+
}));
|
|
4896
|
+
}
|
|
4897
|
+
|
|
4898
|
+
function nativeSourceCompileDeclarationMappings(input) {
|
|
4899
|
+
const usedIds = new Set();
|
|
4900
|
+
return (input.projection.declarations ?? []).map((declaration, index) => {
|
|
4901
|
+
const generated = nativeSourceCompileDeclarationGeneratedSpan(input, declaration);
|
|
4902
|
+
return {
|
|
4903
|
+
id: reserveUniqueId(`compile_map_${idFragment(declaration.symbolId ?? declaration.nativeAstNodeId ?? declaration.name ?? index + 1)}`, usedIds),
|
|
4904
|
+
nativeSourceId: input.importResult.nativeSource?.id,
|
|
4905
|
+
nativeAstNodeId: declaration.nativeAstNodeId,
|
|
4906
|
+
semanticSymbolId: declaration.symbolId,
|
|
4907
|
+
sourceSpan: declaration.sourceSpan,
|
|
4908
|
+
generatedSpan: generated.span,
|
|
4909
|
+
target: input.target,
|
|
4910
|
+
generatedName: generated.name,
|
|
4911
|
+
evidenceIds: (input.evidence ?? []).map((record) => record.id).filter(Boolean),
|
|
4912
|
+
lossIds: lossIdsForNativeNode(input.losses ?? [], declaration.nativeAstNodeId),
|
|
4913
|
+
ownershipRegionId: declaration.ownershipRegionId,
|
|
4914
|
+
ownershipRegionKey: declaration.metadata?.ownershipRegionKey,
|
|
4915
|
+
ownershipRegionKind: declaration.metadata?.ownershipRegionKind,
|
|
4916
|
+
precision: generated.exactName ? 'declaration' : 'estimated',
|
|
4917
|
+
metadata: {
|
|
4918
|
+
...declaration.metadata,
|
|
4919
|
+
compileResultId: input.compileResultId,
|
|
4920
|
+
declarationKind: declaration.kind,
|
|
4921
|
+
sourceMapOrigin: input.outputMode === 'target-adapter' ? 'target-adapter-fallback' : 'declaration-stub'
|
|
4922
|
+
}
|
|
4923
|
+
};
|
|
4924
|
+
});
|
|
4925
|
+
}
|
|
4926
|
+
|
|
4927
|
+
function nativeSourceCompileFileMapping(input) {
|
|
4928
|
+
const rootSpan = input.importResult.nativeAst?.nodes?.[input.importResult.nativeAst?.rootId]?.span
|
|
4929
|
+
?? input.importResult.nativeSource?.ast?.nodes?.[input.importResult.nativeSource?.ast?.rootId]?.span
|
|
4930
|
+
?? input.projection.declarations?.find((declaration) => declaration.sourceSpan)?.sourceSpan;
|
|
4931
|
+
return {
|
|
4932
|
+
id: `compile_map_${idFragment(input.compileResultId ?? input.id)}_file`,
|
|
4933
|
+
nativeSourceId: input.importResult.nativeSource?.id,
|
|
4934
|
+
sourceSpan: rootSpan,
|
|
4935
|
+
generatedSpan: nativeSourceCompileFullGeneratedSpan(input),
|
|
4936
|
+
target: input.target,
|
|
4937
|
+
evidenceIds: (input.evidence ?? []).map((record) => record.id).filter(Boolean),
|
|
4938
|
+
precision: input.projection.mode === 'preserved-source' && input.outputHash === input.projection.sourceHash ? 'line' : 'estimated',
|
|
4939
|
+
metadata: {
|
|
4940
|
+
compileResultId: input.compileResultId,
|
|
4941
|
+
sourceMapOrigin: 'file-fallback'
|
|
4942
|
+
}
|
|
4943
|
+
};
|
|
4944
|
+
}
|
|
4945
|
+
|
|
4946
|
+
function nativeSourceCompileGeneratedSpanFromSource(sourceSpan, input, generatedName) {
|
|
4947
|
+
if (!sourceSpan) return nativeSourceCompileFullGeneratedSpan(input, generatedName);
|
|
4948
|
+
return {
|
|
4949
|
+
...sourceSpan,
|
|
4950
|
+
sourceId: input.targetHash ?? input.outputHash,
|
|
4951
|
+
path: input.targetPath,
|
|
4952
|
+
target: input.target,
|
|
4953
|
+
targetPath: input.targetPath,
|
|
4954
|
+
targetHash: input.targetHash ?? input.outputHash,
|
|
4955
|
+
generatedName
|
|
4956
|
+
};
|
|
4957
|
+
}
|
|
4958
|
+
|
|
4959
|
+
function nativeSourceCompileDeclarationGeneratedSpan(input, declaration) {
|
|
4960
|
+
const identifiers = uniqueStrings([
|
|
4961
|
+
declaration.name,
|
|
4962
|
+
safeProjectionIdentifier(declaration.name),
|
|
4963
|
+
upperFirst(safeProjectionIdentifier(declaration.name)),
|
|
4964
|
+
safeProjectionIdentifier(declaration.name).toUpperCase()
|
|
4965
|
+
]).filter(Boolean);
|
|
4966
|
+
for (const identifier of identifiers) {
|
|
4967
|
+
const offset = input.output.indexOf(identifier);
|
|
4968
|
+
if (offset >= 0) {
|
|
4969
|
+
return {
|
|
4970
|
+
name: identifier,
|
|
4971
|
+
exactName: true,
|
|
4972
|
+
span: nativeSourceCompileGeneratedSpanForOffset(input, offset, identifier.length, identifier)
|
|
4973
|
+
};
|
|
4974
|
+
}
|
|
4975
|
+
}
|
|
4976
|
+
return {
|
|
4977
|
+
name: safeProjectionIdentifier(declaration.name),
|
|
4978
|
+
exactName: false,
|
|
4979
|
+
span: nativeSourceCompileFullGeneratedSpan(input, safeProjectionIdentifier(declaration.name))
|
|
4980
|
+
};
|
|
4981
|
+
}
|
|
4982
|
+
|
|
4983
|
+
function nativeSourceCompileGeneratedSpanForOffset(input, offset, length, generatedName) {
|
|
4984
|
+
const start = lineColumnForOffset(input.output, offset);
|
|
4985
|
+
const end = lineColumnForOffset(input.output, offset + Math.max(1, length));
|
|
4986
|
+
return {
|
|
4987
|
+
sourceId: input.targetHash ?? input.outputHash,
|
|
4988
|
+
path: input.targetPath,
|
|
4989
|
+
startLine: start.line,
|
|
4990
|
+
startColumn: start.column,
|
|
4991
|
+
endLine: end.line,
|
|
4992
|
+
endColumn: end.column,
|
|
4993
|
+
target: input.target,
|
|
4994
|
+
targetPath: input.targetPath,
|
|
4995
|
+
targetHash: input.targetHash ?? input.outputHash,
|
|
4996
|
+
generatedName
|
|
4997
|
+
};
|
|
4998
|
+
}
|
|
4999
|
+
|
|
5000
|
+
function nativeSourceCompileFullGeneratedSpan(input, generatedName) {
|
|
5001
|
+
const lines = String(input.output ?? '').split(/\r?\n/);
|
|
5002
|
+
const lastLine = lines.at(-1) ?? '';
|
|
5003
|
+
return {
|
|
5004
|
+
sourceId: input.targetHash ?? input.outputHash,
|
|
5005
|
+
path: input.targetPath,
|
|
5006
|
+
startLine: 1,
|
|
5007
|
+
startColumn: 1,
|
|
5008
|
+
endLine: Math.max(1, lines.length),
|
|
5009
|
+
endColumn: Math.max(1, lastLine.length + 1),
|
|
5010
|
+
target: input.target,
|
|
5011
|
+
targetPath: input.targetPath,
|
|
5012
|
+
targetHash: input.targetHash ?? input.outputHash,
|
|
5013
|
+
generatedName
|
|
5014
|
+
};
|
|
5015
|
+
}
|
|
5016
|
+
|
|
5017
|
+
function nativeSourceCompileTargetPath(input) {
|
|
5018
|
+
if (input.targetPath) return input.targetPath;
|
|
5019
|
+
const sourcePath = input.importResult.sourcePath ?? input.importResult.nativeSource?.sourcePath;
|
|
5020
|
+
if (!sourcePath) return undefined;
|
|
5021
|
+
const targetExt = nativeSourceCompileTargetExtension(input.target);
|
|
5022
|
+
if (!targetExt) return sourcePath;
|
|
5023
|
+
return sourcePath.replace(/(\.[^./\\]+)?$/, targetExt);
|
|
5024
|
+
}
|
|
5025
|
+
|
|
5026
|
+
function nativeSourceCompileTargetExtension(target) {
|
|
5027
|
+
const normalized = normalizeNativeLanguageId(target);
|
|
5028
|
+
if (normalized === 'typescript') return '.ts';
|
|
5029
|
+
if (normalized === 'javascript') return '.js';
|
|
5030
|
+
if (normalized === 'rust') return '.rs';
|
|
5031
|
+
if (normalized === 'python') return '.py';
|
|
5032
|
+
if (normalized === 'c') return '.h';
|
|
5033
|
+
return undefined;
|
|
5034
|
+
}
|
|
5035
|
+
|
|
5036
|
+
function nativeSourceCompileMapTarget(input, targetPath) {
|
|
5037
|
+
return {
|
|
5038
|
+
language: input.target,
|
|
5039
|
+
emitPath: targetPath
|
|
5040
|
+
};
|
|
5041
|
+
}
|
|
5042
|
+
|
|
5043
|
+
function lineColumnForOffset(source, offset) {
|
|
5044
|
+
const text = String(source ?? '');
|
|
5045
|
+
const safeOffset = Math.max(0, Math.min(offset, text.length));
|
|
5046
|
+
let line = 1;
|
|
5047
|
+
let column = 1;
|
|
5048
|
+
for (let index = 0; index < safeOffset; index += 1) {
|
|
5049
|
+
if (text[index] === '\n') {
|
|
5050
|
+
line += 1;
|
|
5051
|
+
column = 1;
|
|
5052
|
+
} else {
|
|
5053
|
+
column += 1;
|
|
5054
|
+
}
|
|
5055
|
+
}
|
|
5056
|
+
return { line, column };
|
|
5057
|
+
}
|
|
5058
|
+
|
|
4547
5059
|
function nativeProjectionTargetsForLanguage(language, aliases = []) {
|
|
4548
5060
|
const target = nativeLanguageCompileTarget(language, aliases);
|
|
4549
5061
|
return target ? [target] : [];
|
package/package.json
CHANGED