@shapeshift-labs/frontier-lang-compiler 0.2.150 → 0.2.151
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 +315 -9
- package/bench/real-repo-corpus-checkout-identity.mjs +134 -0
- package/bench/real-repo-corpus-checkout-proof.mjs +263 -0
- package/bench/real-repo-corpus-command-execution.mjs +314 -0
- package/bench/real-repo-corpus-evidence.mjs +165 -0
- package/bench/real-repo-corpus-suite.mjs +273 -0
- package/bench/smoke.mjs +109 -7
- package/dist/declarations/import-adapter-core.d.ts +4 -3
- package/dist/declarations/import-adapter-options-native.d.ts +21 -0
- package/dist/declarations/js-ts-project-merge-admission-routes.d.ts +35 -0
- package/dist/declarations/js-ts-project-merge-commonjs-interop.d.ts +29 -0
- package/dist/declarations/js-ts-project-merge-confidence.d.ts +64 -0
- package/dist/declarations/js-ts-project-merge-declaration-emit-parity.d.ts +37 -0
- package/dist/declarations/js-ts-project-merge-declarations.d.ts +65 -0
- package/dist/declarations/js-ts-project-merge-diagnostics.d.ts +97 -0
- package/dist/declarations/js-ts-project-merge-global-augmentation.d.ts +30 -0
- package/dist/declarations/js-ts-project-merge-jsx-render-branch.d.ts +48 -0
- package/dist/declarations/js-ts-project-merge-proof-levels.d.ts +109 -0
- package/dist/declarations/js-ts-project-merge-quality-gates.d.ts +38 -0
- package/dist/declarations/js-ts-project-merge-semantic-equivalence-proof.d.ts +45 -0
- package/dist/declarations/js-ts-project-merge-tsconfig.d.ts +43 -0
- package/dist/declarations/js-ts-safe-merge.d.ts +47 -0
- package/dist/declarations/js-ts-safe-project-merge.d.ts +120 -38
- package/dist/declarations/native-project-compiler-assignability-oracle.d.ts +41 -0
- package/dist/declarations/native-project-compiler-callable-signatures.d.ts +31 -0
- package/dist/declarations/native-project-compiler-class-member-runtime-proof.d.ts +87 -0
- package/dist/declarations/native-project-compiler-composite-types.d.ts +23 -0
- package/dist/declarations/native-project-compiler-enum-proof.d.ts +58 -0
- package/dist/declarations/native-project-compiler-index-signature.d.ts +7 -0
- package/dist/declarations/native-project-compiler-public-api-source-binding.d.ts +8 -0
- package/dist/declarations/native-project-compiler-scope.d.ts +37 -0
- package/dist/declarations/native-project-compiler-type-reference-targets.d.ts +38 -0
- package/dist/declarations/native-project-css-modules.d.ts +90 -0
- package/dist/declarations/native-project-decorator-metadata.d.ts +126 -0
- package/dist/declarations/native-project-jsx-graph.d.ts +313 -0
- package/dist/declarations/native-project-module-declarations.d.ts +52 -0
- package/dist/declarations/native-project-module-resolution.d.ts +76 -1
- package/dist/declarations/native-project-runtime-effect-target.d.ts +29 -0
- package/dist/declarations/native-project-runtime-executable-effect-evidence.d.ts +107 -0
- package/dist/declarations/native-project-runtime-mutation-target.d.ts +33 -0
- package/dist/declarations/native-project-runtime-promise-chain.d.ts +30 -0
- package/dist/declarations/native-project-runtime-promise-combinator.d.ts +22 -0
- package/dist/declarations/native-project-runtime-reachability.d.ts +30 -0
- package/dist/declarations/native-project-runtime-resource-management.d.ts +27 -0
- package/dist/declarations/native-project-runtime-yield-delegation.d.ts +10 -0
- package/dist/declarations/native-project-scope-template-reference.d.ts +13 -0
- package/dist/declarations/native-project-source-evidence.d.ts +8 -0
- package/dist/declarations/native-project.d.ts +40 -39
- package/dist/declarations/semantic-edit-script.d.ts +10 -8
- package/dist/declarations/semantic-graph-layers.d.ts +79 -0
- package/dist/declarations/semantic-sidecar.d.ts +3 -2
- package/dist/declarations/semantic-structural-diff.d.ts +94 -0
- package/dist/declarations/source-preservation.d.ts +32 -1
- package/dist/declarations/target-adapters.d.ts +22 -2
- package/dist/index.d.ts +31 -0
- package/dist/index.js +5 -0
- package/dist/internal/index-impl/compileNativeSource.js +53 -5
- package/dist/internal/index-impl/createLightweightNativeImport.js +58 -4
- package/dist/internal/index-impl/createNativeImportFromSyntaxAst.js +17 -1
- package/dist/internal/index-impl/createNativeImportFromTypeScriptAst.js +28 -4
- package/dist/internal/index-impl/createNativeProjectImportResult.js +31 -27
- package/dist/internal/index-impl/createNativeProjectModuleResolutionFromPackageManifests.js +145 -0
- package/dist/internal/index-impl/createNativeSourcePreservation.js +34 -7
- package/dist/internal/index-impl/createSemanticImportSidecar.js +27 -1
- package/dist/internal/index-impl/createTypeScriptCompilerNativeImporterAdapter.js +16 -5
- package/dist/internal/index-impl/dynamicImportExpressionMetadata.js +80 -0
- package/dist/internal/index-impl/importMetaUrlDependencyMetadata.js +176 -0
- package/dist/internal/index-impl/importNativeSource.js +2 -3
- package/dist/internal/index-impl/moduleImportAttributeMetadata.js +232 -0
- package/dist/internal/index-impl/projectSemanticEditScriptToSource.js +8 -1
- package/dist/internal/index-impl/projectSymbolGraphClassStaticBlocks.js +148 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerAdvancedTypeMetadata.js +45 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerCallableSignatureEquivalence.js +107 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerClassPrivateAccessorRuntimeProof.js +280 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerClassShapeEquivalence.js +103 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerConditionalTypeEquivalence.js +242 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerDecoratorRuntimeProof.js +197 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerEnumEquivalence.js +188 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerFacts.js +244 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerIndexSignatureEquivalence.js +58 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerMetadata.js +168 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerTypeEquivalence.js +199 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerTypeEquivalenceProof.js +204 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerTypeReferenceTargetEquivalence.js +99 -0
- package/dist/internal/index-impl/projectSymbolGraphCssModuleRecords.js +264 -0
- package/dist/internal/index-impl/projectSymbolGraphCssModuleScanners.js +242 -0
- package/dist/internal/index-impl/projectSymbolGraphCssModuleUtils.js +152 -0
- package/dist/internal/index-impl/projectSymbolGraphCssModules.js +82 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxComponentImports.js +170 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxComponentProviderLookup.js +167 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxComponentWrappers.js +150 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxContextTargets.js +71 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxContextValues.js +212 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxEventHandlers.js +172 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxHookEffects.js +124 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxHooks.js +281 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxMemberComponents.js +139 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxPropFlows.js +320 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxPropValues.js +145 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxProviderFlows.js +133 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxRecords.js +315 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxRenderCollections.js +155 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxRenderReturns.js +291 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxRenderRisk.js +279 -0
- package/dist/internal/index-impl/projectSymbolGraphModuleDeclarationShapes.js +138 -0
- package/dist/internal/index-impl/projectSymbolGraphModuleResolution.js +89 -87
- package/dist/internal/index-impl/projectSymbolGraphPackageConditions.js +314 -0
- package/dist/internal/index-impl/projectSymbolGraphReExportImportTargets.js +43 -0
- package/dist/internal/index-impl/projectSymbolGraphReExports.js +55 -1
- package/dist/internal/index-impl/projectSymbolGraphRuntimeRegions.js +108 -0
- package/dist/internal/index-impl/projectSymbolGraphScopeUseDefAliases.js +307 -0
- package/dist/internal/index-impl/projectSymbolGraphScopeUseDefLexical.js +320 -0
- package/dist/internal/index-impl/projectSymbolGraphScopeUseDefOwners.js +50 -0
- package/dist/internal/index-impl/projectSymbolGraphScopeUseDefRecordBuilders.js +112 -0
- package/dist/internal/index-impl/projectSymbolGraphScopeUseDefRecords.js +238 -0
- package/dist/internal/index-impl/projectSymbolGraphScopeUseDefStructural.js +104 -0
- package/dist/internal/index-impl/projectSymbolGraphScopeUseDefStructuralNormalize.js +242 -0
- package/dist/internal/index-impl/projectSymbolGraphScopeUseDefUseHashes.js +107 -0
- package/dist/internal/index-impl/projectSymbolGraphSourceMapGeneratedBoundary.js +111 -0
- package/dist/internal/index-impl/projectSymbolGraphSourceRecords.js +268 -0
- package/dist/internal/index-impl/projectSymbolGraphSourceRecordsOwnership.js +309 -0
- package/dist/internal/index-impl/replaySemanticEditProjection.js +53 -39
- package/dist/internal/index-impl/runtimeOrderEvidenceBinding.js +151 -0
- package/dist/internal/index-impl/runtimeOrderProofSurfaces.js +253 -0
- package/dist/internal/index-impl/semanticEditCallsiteArgumentMerge.js +319 -0
- package/dist/internal/index-impl/semanticEditExplicitSourceReplacement.js +7 -2
- package/dist/internal/index-impl/semanticEditProjectionRecord.js +8 -0
- package/dist/internal/index-impl/semanticEditReplayDiagnostics.js +7 -2
- package/dist/internal/index-impl/semanticEditReplayOutputBinding.js +61 -0
- package/dist/internal/index-impl/semanticEditReplayRerunRoute.js +27 -0
- package/dist/internal/index-impl/semanticEditReplaySourceReplacement.js +6 -1
- package/dist/internal/index-impl/semanticEditRuntimeOrderReasons.js +320 -0
- package/dist/internal/index-impl/semanticEditScriptClassification.js +90 -5
- package/dist/internal/index-impl/semanticEditScripts.js +42 -5
- package/dist/internal/index-impl/semanticEditTypeSyntaxReasons.js +134 -0
- package/dist/internal/index-impl/semanticIndexFromNativeDeclarations.js +11 -5
- package/dist/internal/index-impl/semanticStructuralDiffRecords.js +150 -0
- package/dist/internal/index-impl/sourceMapGeneratedBoundaryGate.js +185 -0
- package/dist/internal/index-impl/staticMemberLiteral.js +31 -0
- package/dist/internal/index-impl/staticOptionalMemberReference.js +22 -0
- package/dist/internal/index-impl/syntaxAstSourcePreservation.js +273 -0
- package/dist/internal/index-impl/syntaxCommonJsModuleDeclarationEntries.js +297 -0
- package/dist/internal/index-impl/syntaxModuleDeclarationEntries.js +56 -132
- package/dist/internal/index-impl/syntaxModuleEntryRecords.js +160 -0
- package/dist/internal/index-impl/typeScriptCompilerAdvancedTypeShapes.js +160 -0
- package/dist/internal/index-impl/typeScriptCompilerAssignabilityOracle.js +97 -0
- package/dist/internal/index-impl/typeScriptCompilerClassApi.js +238 -0
- package/dist/internal/index-impl/typeScriptCompilerDecoratorMetadata.js +290 -0
- package/dist/internal/index-impl/typeScriptCompilerEnumShape.js +279 -0
- package/dist/internal/index-impl/typeScriptCompilerFacts.js +294 -0
- package/dist/internal/index-impl/typeScriptCompilerInferenceSyntax.js +170 -0
- package/dist/internal/index-impl/typeScriptCompilerReferenceGraph.js +186 -0
- package/dist/internal/index-impl/typeScriptCompilerSymbolIdentity.js +294 -0
- package/dist/internal/index-impl/typeScriptCompilerTypeReferenceTargets.js +142 -0
- package/dist/internal/index-impl/typeScriptDeclaration.js +10 -38
- package/dist/internal/index-impl/typeScriptModuleDeclarationEntries.js +52 -15
- package/dist/internal/index-impl/typeScriptSourceFilePreservation.js +296 -0
- package/dist/js-ts-safe-member-class-invariants.js +247 -0
- package/dist/js-ts-safe-member-merge-result.js +23 -3
- package/dist/js-ts-safe-member-merge.js +28 -4
- package/dist/js-ts-safe-merge-binding-patterns.js +170 -0
- package/dist/js-ts-safe-merge-jsx-attribute-fallback.js +151 -157
- package/dist/js-ts-safe-merge-jsx-attribute-parser.js +277 -0
- package/dist/js-ts-safe-merge-jsx-child-expression-fallback.js +161 -0
- package/dist/js-ts-safe-merge-jsx-child-expression-merge.js +319 -0
- package/dist/js-ts-safe-merge-jsx-child-expression-parser.js +300 -0
- package/dist/js-ts-safe-merge-parse-declarations.js +46 -2
- package/dist/js-ts-safe-merge-parse-statements.js +8 -0
- package/dist/js-ts-safe-merge-semantic-edit-fallback.js +13 -5
- package/dist/js-ts-safe-merge-source-shape-fallbacks.js +3 -1
- package/dist/js-ts-safe-merge-top-level-rename-fallback.js +31 -5
- package/dist/js-ts-safe-merge-top-level-rename-result.js +7 -2
- package/dist/js-ts-safe-merge-variable-declarator-fallback.js +124 -6
- package/dist/js-ts-safe-merge-variable-declarator-parser.js +34 -4
- package/dist/js-ts-safe-merge.js +136 -0
- package/dist/js-ts-safe-project-merge-admission-routes.js +216 -0
- package/dist/js-ts-safe-project-merge-admission.js +161 -0
- package/dist/js-ts-safe-project-merge-ambient.js +110 -0
- package/dist/js-ts-safe-project-merge-core.js +85 -0
- package/dist/js-ts-safe-project-merge-css-module-conflicts.js +60 -0
- package/dist/js-ts-safe-project-merge-declaration-emit-parity.js +186 -0
- package/dist/js-ts-safe-project-merge-declarations.js +227 -0
- package/dist/js-ts-safe-project-merge-diagnostics-metadata.js +42 -0
- package/dist/js-ts-safe-project-merge-diagnostics-ts.js +73 -0
- package/dist/js-ts-safe-project-merge-diagnostics.js +283 -0
- package/dist/js-ts-safe-project-merge-evidence-routing.js +38 -0
- package/dist/js-ts-safe-project-merge-files.js +70 -0
- package/dist/js-ts-safe-project-merge-global-augmentation-compatibility.js +99 -0
- package/dist/js-ts-safe-project-merge-graph-conflicts.js +90 -2
- package/dist/js-ts-safe-project-merge-graph-delta-commonjs-interop.js +108 -0
- package/dist/js-ts-safe-project-merge-graph-delta-compiler-conflicts.js +179 -0
- package/dist/js-ts-safe-project-merge-graph-delta-compiler-details.js +189 -0
- package/dist/js-ts-safe-project-merge-graph-delta-conflicts.js +51 -184
- package/dist/js-ts-safe-project-merge-graph-delta-identity-conflicts.js +202 -0
- package/dist/js-ts-safe-project-merge-graph-delta-inference-syntax.js +80 -0
- package/dist/js-ts-safe-project-merge-graph-delta-module-declarations.js +155 -0
- package/dist/js-ts-safe-project-merge-graph-limits.js +16 -1
- package/dist/js-ts-safe-project-merge-graph.js +37 -5
- package/dist/js-ts-safe-project-merge-import-removal.js +292 -0
- package/dist/js-ts-safe-project-merge-jsx-graph-conflict-details.js +235 -0
- package/dist/js-ts-safe-project-merge-jsx-graph-conflicts.js +173 -0
- package/dist/js-ts-safe-project-merge-jsx-prop-contracts.js +86 -0
- package/dist/js-ts-safe-project-merge-jsx-render-branch-proof.js +189 -0
- package/dist/js-ts-safe-project-merge-missing-evidence.js +310 -0
- package/dist/js-ts-safe-project-merge-move-rename.js +209 -0
- package/dist/js-ts-safe-project-merge-proof-conflicts.js +44 -0
- package/dist/js-ts-safe-project-merge-proof-levels.js +320 -0
- package/dist/js-ts-safe-project-merge-quality-gates.js +140 -0
- package/dist/js-ts-safe-project-merge-routing-calibration.js +125 -0
- package/dist/js-ts-safe-project-merge-runtime-region-conflicts.js +156 -0
- package/dist/js-ts-safe-project-merge-scope-use-def-conflicts.js +292 -0
- package/dist/js-ts-safe-project-merge-semantic-equivalence-proof.js +175 -0
- package/dist/js-ts-safe-project-merge-semantic-replay-proof.js +311 -0
- package/dist/js-ts-safe-project-merge-semantic-replay-routes.js +179 -0
- package/dist/js-ts-safe-project-merge-source-span-conflicts.js +310 -0
- package/dist/js-ts-safe-project-merge-source-span-roundtrip-proof.js +172 -0
- package/dist/js-ts-safe-project-merge-split-merge-admission.js +96 -0
- package/dist/js-ts-safe-project-merge-split-merge-records.js +320 -0
- package/dist/js-ts-safe-project-merge-split-merge-shapes.js +234 -0
- package/dist/js-ts-safe-project-merge-split-merge.js +218 -0
- package/dist/js-ts-safe-project-merge-summary.js +320 -0
- package/dist/js-ts-safe-project-merge-symbol-move-admission.js +63 -0
- package/dist/js-ts-safe-project-merge-symbol-move-default-admission.js +143 -0
- package/dist/js-ts-safe-project-merge-symbol-move-risks.js +213 -0
- package/dist/js-ts-safe-project-merge-symbol-move.js +316 -0
- package/dist/js-ts-safe-project-merge-symbol-rename-admission.js +59 -0
- package/dist/js-ts-safe-project-merge-symbol-rename-default-admission.js +111 -0
- package/dist/js-ts-safe-project-merge-symbol-rename.js +319 -0
- package/dist/js-ts-safe-project-merge-ts-options.js +205 -0
- package/dist/js-ts-safe-project-merge-ts-program.js +268 -0
- package/dist/js-ts-safe-project-merge-typed-property-rename-rebase-utils.js +69 -0
- package/dist/js-ts-safe-project-merge-typed-property-rename-rebase.js +317 -0
- package/dist/js-ts-safe-project-merge-unsupported-surfaces.js +319 -0
- package/dist/js-ts-safe-project-merge.js +170 -171
- package/dist/js-ts-semantic-scope-use-def-bindings.js +287 -0
- package/dist/js-ts-semantic-scope-use-def-scan.js +241 -0
- package/dist/js-ts-semantic-scope-use-def-utils.js +132 -0
- package/dist/js-ts-semantic-scope-use-def.js +217 -0
- package/dist/lightweight-dependency-effects.js +28 -4
- package/dist/lightweight-dependency-relations.js +13 -7
- package/dist/lightweight-dependency-top-level.js +63 -0
- package/dist/native-import-language-profiles.js +27 -1
- package/dist/native-js-ts-importers.js +9 -5
- package/dist/native-parser-ast-format-profiles.js +12 -0
- package/dist/native-parser-html-css-format-profiles.js +85 -0
- package/dist/native-region-scanner-core.js +5 -3
- package/dist/native-region-scanner-js-commonjs.js +155 -0
- package/dist/native-region-scanner-js-imports.js +51 -13
- package/dist/native-region-scanner-js-reexports.js +79 -0
- package/dist/native-region-scanner-js-ts-helpers.js +23 -0
- package/dist/native-source-ledger-helpers.js +1 -1
- package/dist/native-source-ledger.js +24 -10
- package/dist/native-source-maps-ecma426.js +316 -0
- package/dist/native-source-maps.js +36 -6
- package/dist/native-source-preservation-ownership.js +292 -0
- package/dist/native-source-preservation-scanner.js +63 -25
- package/dist/native-source-preservation-types.d.ts +3 -0
- package/dist/semantic-import-effect-occurrences.js +242 -0
- package/dist/semantic-import-effect-regions.js +95 -58
- package/dist/semantic-import-graph-layers.js +224 -0
- package/dist/semantic-import-runtime-conditional-evidence.js +135 -0
- package/dist/semantic-import-runtime-effect-target-evidence.js +145 -0
- package/dist/semantic-import-runtime-exit-evidence.js +32 -0
- package/dist/semantic-import-runtime-import-meta-evidence.js +33 -0
- package/dist/semantic-import-runtime-mutation-evidence.js +155 -0
- package/dist/semantic-import-runtime-order-evidence.js +318 -0
- package/dist/semantic-import-runtime-promise-chain-evidence.js +103 -0
- package/dist/semantic-import-runtime-promise-combinator-evidence.js +166 -0
- package/dist/semantic-import-runtime-reachability-evidence.js +269 -0
- package/dist/semantic-import-runtime-resource-management-evidence.js +293 -0
- package/dist/semantic-import-runtime-switch-evidence.js +304 -0
- package/dist/semantic-import-runtime-throw-evidence.js +44 -0
- package/dist/semantic-import-runtime-try-finally-evidence.js +172 -0
- package/dist/semantic-import-sidecar-entry.js +4 -0
- package/dist/semantic-import-source-preservation.js +6 -2
- package/package.json +1 -1
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { uniqueStrings } from './native-import-utils.js';
|
|
2
|
+
|
|
3
|
+
const schedulerEffectNames = ['setTimeout', 'setInterval', 'clearTimeout', 'clearInterval', 'requestAnimationFrame', 'cancelAnimationFrame', 'requestIdleCallback', 'cancelIdleCallback', 'queueMicrotask', 'setImmediate', 'clearImmediate'];
|
|
4
|
+
|
|
5
|
+
function splitEffectFactOccurrences(group, sourceText) {
|
|
6
|
+
const concreteKinds = group.factKinds.filter((kind) => kind !== 'async');
|
|
7
|
+
const line = sourceLine(sourceText, group.line);
|
|
8
|
+
if (!concreteKinds.length && group.factKinds.includes('async')) {
|
|
9
|
+
const ranges = effectOccurrenceRanges(line, 'async');
|
|
10
|
+
return ranges.length > 1
|
|
11
|
+
? ranges.map((range, occurrenceIndex) => ({ ...group, factKinds: ['async'], occurrenceRange: range, occurrenceOrdinalHint: occurrenceIndex + 1 }))
|
|
12
|
+
: [group];
|
|
13
|
+
}
|
|
14
|
+
if (!concreteKinds.length) return [group];
|
|
15
|
+
return concreteKinds.flatMap((factKind, index) => {
|
|
16
|
+
const base = {
|
|
17
|
+
...group,
|
|
18
|
+
facts: group.facts.filter((fact) => fact.value?.kind === factKind
|
|
19
|
+
|| (index === 0 && fact.value?.kind === 'async')),
|
|
20
|
+
factKinds: uniqueStrings([factKind, index === 0 && group.factKinds.includes('async') ? 'async' : undefined])
|
|
21
|
+
};
|
|
22
|
+
const ranges = effectOccurrenceRanges(line, factKind);
|
|
23
|
+
return ranges.length > 1
|
|
24
|
+
? ranges.map((range, occurrenceIndex) => ({ ...base, occurrenceRange: range, occurrenceOrdinalHint: occurrenceIndex + 1 }))
|
|
25
|
+
: [base];
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function splitMutationFactOccurrences(group, sourceText) {
|
|
30
|
+
const line = sourceLine(sourceText, group.line);
|
|
31
|
+
return group.factKinds.flatMap((factKind) => {
|
|
32
|
+
const base = {
|
|
33
|
+
...group,
|
|
34
|
+
facts: group.facts.filter((fact) => fact.value?.kind === factKind),
|
|
35
|
+
factKinds: [factKind]
|
|
36
|
+
};
|
|
37
|
+
const ranges = mutationOccurrenceRanges(line, factKind);
|
|
38
|
+
return ranges.length > 1
|
|
39
|
+
? ranges.map((range, occurrenceIndex) => ({ ...base, occurrenceRange: range, occurrenceOrdinalHint: occurrenceIndex + 1 }))
|
|
40
|
+
: [base];
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function effectOccurrenceRanges(line, factKind) {
|
|
45
|
+
if (factKind === 'network') return namedCallRanges(line, ['fetch', 'XMLHttpRequest', 'WebSocket', 'EventSource'], 'network-call');
|
|
46
|
+
if (factKind === 'scheduler') return namedCallRanges(line, schedulerEffectNames, 'scheduler-call');
|
|
47
|
+
if (factKind === 'storage') return tokenExpressionRanges(line, ['localStorage', 'sessionStorage', 'indexedDB', 'caches', 'cookie'], 'storage-effect');
|
|
48
|
+
if (factKind === 'host-context') return importMetaRanges(line);
|
|
49
|
+
if (factKind === 'host') return tokenExpressionRanges(line, ['console', 'process', 'Deno', 'Bun'], 'host-effect');
|
|
50
|
+
if (factKind === 'browser') return sortedRanges([
|
|
51
|
+
...namedCallRanges(line, ['Worker', 'SharedWorker'], 'browser-constructor'),
|
|
52
|
+
...tokenExpressionRanges(line, ['document', 'window', 'navigator', 'location', 'history'], 'browser-effect')
|
|
53
|
+
]);
|
|
54
|
+
if (factKind === 'tagged-template') return taggedTemplateRanges(line);
|
|
55
|
+
if (factKind === 'async') return awaitEffectRanges(line);
|
|
56
|
+
if (factKind === 'generator') return yieldEffectRanges(line);
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function mutationOccurrenceRanges(line, factKind) {
|
|
61
|
+
if (factKind === 'mutating-call') return mutatingCallRanges(line);
|
|
62
|
+
if (factKind === 'delete') return deleteMutationRanges(line);
|
|
63
|
+
if (factKind === 'assignment') return assignmentRanges(line);
|
|
64
|
+
if (factKind === 'update') return updateRanges(line);
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function namedCallRanges(line, names, kind) {
|
|
69
|
+
const text = String(line ?? '');
|
|
70
|
+
const ranges = [];
|
|
71
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
72
|
+
const match = namedCallAt(text, index, names);
|
|
73
|
+
if (!match) continue;
|
|
74
|
+
const open = text.indexOf('(', match.start);
|
|
75
|
+
const close = matchingParenIndex(text, open);
|
|
76
|
+
ranges.push({ start: match.start, end: close === undefined ? statementEnd(text, open) : close + 1, kind });
|
|
77
|
+
index = Math.max(index, open);
|
|
78
|
+
}
|
|
79
|
+
return sortedRanges([...ranges, ...globalBracketCallRanges(text, names, kind)]);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function globalBracketCallRanges(text, names, kind) {
|
|
83
|
+
const ranges = [];
|
|
84
|
+
for (const name of names) {
|
|
85
|
+
const pattern = new RegExp(`(?:^|[^\\w$.])((?:new\\s+)?(?:window|globalThis|self)\\s*(?:\\?\\.)?\\s*\\[\\s*(['"\`])${name}\\2\\s*\\]\\s*(?:\\?\\.)?\\s*\\()`, 'g');
|
|
86
|
+
for (const match of text.matchAll(pattern)) {
|
|
87
|
+
const start = match.index + match[0].indexOf(match[1]);
|
|
88
|
+
const open = text.indexOf('(', start);
|
|
89
|
+
const close = matchingParenIndex(text, open);
|
|
90
|
+
ranges.push({ start, end: close === undefined ? statementEnd(text, open) : close + 1, kind });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return ranges;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function mutatingCallRanges(line) {
|
|
97
|
+
const text = String(line ?? '');
|
|
98
|
+
const ranges = [];
|
|
99
|
+
const pattern = /[A-Za-z_$][\w$]*(?:(?:\s*(?:\.|\?\.)\s*[A-Za-z_$][\w$]*)|\s*\[[^\]]+\])*\s*(?:(?:\.|\?\.)\s*(?:push|pop|shift|unshift|splice|sort|reverse|set|add|delete|clear)\s*(?:\?\.)?|\s*(?:\?\.)?\s*\[\s*(['"`])(?:push|pop|shift|unshift|splice|sort|reverse|set|add|delete|clear)\1\s*\]\s*(?:\?\.)?)\s*\(/g;
|
|
100
|
+
for (const match of text.matchAll(pattern)) {
|
|
101
|
+
const open = text.indexOf('(', match.index);
|
|
102
|
+
const close = matchingParenIndex(text, open);
|
|
103
|
+
ranges.push({ start: match.index, end: close === undefined ? statementEnd(text, open) : close + 1, kind: 'mutating-call' });
|
|
104
|
+
}
|
|
105
|
+
return ranges;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function deleteMutationRanges(line) {
|
|
109
|
+
const text = String(line ?? '');
|
|
110
|
+
return [...text.matchAll(/\bdelete\s+[A-Za-z_$][\w$]*(?:(?:\s*(?:\.|\?\.)\s*[A-Za-z_$][\w$]*)|\s*\[[^\]]+\])*/g)]
|
|
111
|
+
.map((match) => ({ start: match.index, end: statementEnd(text, match.index), kind: 'delete-mutation' }));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function assignmentRanges(line) {
|
|
115
|
+
const text = String(line ?? '');
|
|
116
|
+
return [...text.matchAll(/(^|[^\w$])([A-Za-z_$][\w$]*(?:(?:\s*(?:\.|\?\.)\s*[A-Za-z_$][\w$]*)|\s*\[[^\]]+\])*)\s*=(?!=|>)/g)]
|
|
117
|
+
.map((match) => ({ start: match.index + match[1].length, end: statementEnd(text, match.index + match[1].length), kind: 'assignment' }));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function updateRanges(line) {
|
|
121
|
+
const text = String(line ?? '');
|
|
122
|
+
return [...text.matchAll(/(^|[^\w$])((?:\+\+|--)\s*)?[A-Za-z_$][\w$]*(?:(?:\s*(?:\.|\?\.)\s*[A-Za-z_$][\w$]*)|\s*\[[^\]]+\])*(?:\s*(?:\+\+|--|\+=|-=|\*=|\/=|%=|\|\|=|&&=|\?\?=))/g)]
|
|
123
|
+
.map((match) => ({ start: match.index + match[1].length, end: statementEnd(text, match.index + match[1].length), kind: 'update' }));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function tokenExpressionRanges(line, tokens, kind) {
|
|
127
|
+
const text = String(line ?? '');
|
|
128
|
+
const pattern = new RegExp(`\\b(?:${tokens.join('|')})\\b`, 'g');
|
|
129
|
+
return [...text.matchAll(pattern)].map((match) => ({
|
|
130
|
+
start: match.index,
|
|
131
|
+
end: statementEnd(text, match.index),
|
|
132
|
+
kind
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function awaitEffectRanges(line) {
|
|
137
|
+
const text = String(line ?? '');
|
|
138
|
+
return [...text.matchAll(/\bawait\b/g)]
|
|
139
|
+
.map((match) => ({ start: match.index, end: statementEnd(text, match.index), kind: 'async-effect' }));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function yieldEffectRanges(line) {
|
|
143
|
+
const text = String(line ?? '');
|
|
144
|
+
return [...text.matchAll(/\byield\s*\*?/g)]
|
|
145
|
+
.map((match) => ({ start: match.index, end: statementEnd(text, match.index), kind: 'generator-effect' }));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function importMetaRanges(line) {
|
|
149
|
+
const text = String(line ?? '');
|
|
150
|
+
return [...text.matchAll(/\bimport\s*\.\s*meta(?:\s*\.\s*[A-Za-z_$][\w$]*)*/g)]
|
|
151
|
+
.map((match) => ({ start: match.index, end: statementEnd(text, match.index), kind: 'import-meta-host-context' }));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function taggedTemplateRanges(line) {
|
|
155
|
+
const text = String(line ?? '');
|
|
156
|
+
const ranges = [];
|
|
157
|
+
const pattern = /(?:^|[^\w$.)\]])([A-Za-z_$][\w$]*(?:(?:\s*\.\s*[A-Za-z_$][\w$]*)|\s*\[[^\]]+\])*)\s*`/g;
|
|
158
|
+
for (const match of text.matchAll(pattern)) {
|
|
159
|
+
const start = match.index + match[0].indexOf(match[1]);
|
|
160
|
+
const tick = text.indexOf('`', start);
|
|
161
|
+
ranges.push({ start, end: templateEnd(text, tick), kind: 'tagged-template' });
|
|
162
|
+
}
|
|
163
|
+
return ranges;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function namedCallAt(text, index, names) {
|
|
167
|
+
if (isIdentifierPart(text[index - 1]) || text[index - 1] === '.' || text[index - 1] === '$') return undefined;
|
|
168
|
+
const receiverLength = receiverPrefixLength(text, index);
|
|
169
|
+
const start = index + receiverLength;
|
|
170
|
+
for (const name of names) {
|
|
171
|
+
if (text.slice(start, start + name.length) !== name || isIdentifierPart(text[start + name.length])) continue;
|
|
172
|
+
const open = optionalCallOpen(text, skipSpaces(text, start + name.length));
|
|
173
|
+
if (text[open] === '(') return { start: constructorStartBefore(text, index) ?? index };
|
|
174
|
+
}
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function receiverPrefixLength(text, index) {
|
|
179
|
+
for (const prefix of ['window?.', 'globalThis?.', 'self?.', 'window.', 'globalThis.', 'self.']) {
|
|
180
|
+
if (text.slice(index, index + prefix.length) === prefix) return prefix.length;
|
|
181
|
+
}
|
|
182
|
+
return 0;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function optionalCallOpen(text, index) {
|
|
186
|
+
return text[index] === '?' && text[index + 1] === '.' ? skipSpaces(text, index + 2) : index;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function constructorStartBefore(text, index) {
|
|
190
|
+
let cursor = index - 1;
|
|
191
|
+
while (/\s/.test(text[cursor] ?? '')) cursor -= 1;
|
|
192
|
+
const end = cursor + 1;
|
|
193
|
+
const start = end - 3;
|
|
194
|
+
return text.slice(start, end) === 'new' && !isIdentifierPart(text[start - 1]) ? start : undefined;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function sortedRanges(ranges) {
|
|
198
|
+
return ranges.slice().sort((left, right) => left.start - right.start || left.end - right.end);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function sourceLine(sourceText, lineNumber) {
|
|
202
|
+
return String(sourceText ?? '').split(/\r\n|\n|\r/)[Number(lineNumber) - 1] ?? '';
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function statementEnd(line, start) {
|
|
206
|
+
const semicolon = String(line ?? '').indexOf(';', Math.max(0, start));
|
|
207
|
+
return semicolon === -1 ? String(line ?? '').length : semicolon + 1;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function templateEnd(line, start) {
|
|
211
|
+
for (let index = start + 1, escaped = false; index < line.length; index += 1) {
|
|
212
|
+
if (escaped) escaped = false;
|
|
213
|
+
else if (line[index] === '\\') escaped = true;
|
|
214
|
+
else if (line[index] === '`') return index + 1;
|
|
215
|
+
}
|
|
216
|
+
return line.length;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function matchingParenIndex(line, open) {
|
|
220
|
+
if (open < 0) return undefined;
|
|
221
|
+
let depth = 0;
|
|
222
|
+
let quote;
|
|
223
|
+
let escaped = false;
|
|
224
|
+
for (let index = open; index < line.length; index += 1) {
|
|
225
|
+
const char = line[index];
|
|
226
|
+
if (quote) {
|
|
227
|
+
if (escaped) escaped = false;
|
|
228
|
+
else if (char === '\\') escaped = true;
|
|
229
|
+
else if (char === quote) quote = undefined;
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
if (char === '\'' || char === '"' || char === '`') { quote = char; continue; }
|
|
233
|
+
if (char === '(') depth += 1;
|
|
234
|
+
else if (char === ')' && --depth === 0) return index;
|
|
235
|
+
}
|
|
236
|
+
return undefined;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function skipSpaces(text, index) { let cursor = index; while (/\s/.test(text[cursor] ?? '')) cursor += 1; return cursor; }
|
|
240
|
+
function isIdentifierPart(char) { return /[A-Za-z0-9_$]/.test(char ?? ''); }
|
|
241
|
+
|
|
242
|
+
export { splitEffectFactOccurrences, splitMutationFactOccurrences };
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { hashSemanticValue } from '@shapeshift-labs/frontier-lang-kernel';
|
|
1
2
|
import { caseSensitiveIdFragment, idFragment, uniqueRecordsById, uniqueStrings } from './native-import-utils.js';
|
|
3
|
+
import { splitEffectFactOccurrences, splitMutationFactOccurrences } from './semantic-import-effect-occurrences.js';
|
|
4
|
+
import { semanticFactOrderInfo, semanticFactRuntimeOrderEvidence, semanticFactRuntimeOrderSignatureEvidence } from './semantic-import-runtime-order-evidence.js';
|
|
2
5
|
|
|
3
6
|
const semanticFactRegionKinds = new Set(['controlFlow', 'effect', 'mutation']);
|
|
7
|
+
const schedulerEffectNames = ['setTimeout', 'setInterval', 'clearTimeout', 'clearInterval', 'requestAnimationFrame', 'cancelAnimationFrame', 'requestIdleCallback', 'cancelIdleCallback', 'queueMicrotask', 'setImmediate', 'clearImmediate'];
|
|
4
8
|
|
|
5
9
|
export function semanticEffectRegionRecordsForImport(imported, semanticIndex, options = {}) {
|
|
6
10
|
const symbolsById = new Map((semanticIndex?.symbols ?? []).map((symbol) => [symbol.id, symbol]));
|
|
@@ -8,12 +12,15 @@ export function semanticEffectRegionRecordsForImport(imported, semanticIndex, op
|
|
|
8
12
|
&& semanticFactSubjectCanOwnRuntimeRegion(symbolsById.get(fact.subjectId)));
|
|
9
13
|
if (!facts.length) return { symbols: [], ownershipRegions: [] };
|
|
10
14
|
const sourceText = nativeImportSourceText(imported);
|
|
11
|
-
const groups = semanticFactRegionGroups(facts);
|
|
15
|
+
const groups = semanticFactRegionGroups(facts, sourceText);
|
|
12
16
|
const ordinals = new Map();
|
|
17
|
+
const orderInfo = semanticFactOrderInfo(groups);
|
|
13
18
|
const records = groups.map((group, index) => {
|
|
14
19
|
const fact = group.facts[0];
|
|
15
20
|
const spanInfo = semanticFactSpanInfo(sourceText, group, fact, imported);
|
|
21
|
+
const runtimeOrderEvidence = semanticFactRuntimeOrderEvidence(sourceText, group, fact, spanInfo, orderInfo.get(group));
|
|
16
22
|
const owner = symbolsById.get(fact.subjectId);
|
|
23
|
+
const signatureHash = hashSemanticValue({ kind: 'frontier.lang.semanticFactRuntimeRegionSignature', subjectId: fact.subjectId, subjectName: owner?.name, regionKind: group.regionKind, factKinds: group.factKinds, spanKind: spanInfo.kind, runtimeOrderEvidence: semanticFactRuntimeOrderSignatureEvidence(runtimeOrderEvidence) });
|
|
17
24
|
const sourcePath = fact.value?.sourcePath ?? imported?.sourcePath ?? imported?.nativeSource?.sourcePath;
|
|
18
25
|
const language = imported?.language ?? imported?.nativeSource?.language ?? imported?.nativeAst?.language;
|
|
19
26
|
const signature = semanticFactRegionSignature(group);
|
|
@@ -42,6 +49,7 @@ export function semanticEffectRegionRecordsForImport(imported, semanticIndex, op
|
|
|
42
49
|
factLine: group.line,
|
|
43
50
|
predicate: group.regionKind,
|
|
44
51
|
spanKind: spanInfo.kind,
|
|
52
|
+
runtimeOrderEvidence,
|
|
45
53
|
occurrenceOrdinal: ordinal,
|
|
46
54
|
subjectId: fact.subjectId,
|
|
47
55
|
subjectName: owner?.name
|
|
@@ -56,6 +64,7 @@ export function semanticEffectRegionRecordsForImport(imported, semanticIndex, op
|
|
|
56
64
|
language,
|
|
57
65
|
nativeAstNodeId: region.nativeAstNodeId,
|
|
58
66
|
sourceSpan: region.sourceSpan,
|
|
67
|
+
signatureHash,
|
|
59
68
|
ownershipRegionId: region.id,
|
|
60
69
|
ownershipKey: region.key,
|
|
61
70
|
ownershipRegionKind: group.regionKind,
|
|
@@ -69,7 +78,7 @@ export function semanticEffectRegionRecordsForImport(imported, semanticIndex, op
|
|
|
69
78
|
};
|
|
70
79
|
}
|
|
71
80
|
|
|
72
|
-
function semanticFactRegionGroups(facts) {
|
|
81
|
+
function semanticFactRegionGroups(facts, sourceText) {
|
|
73
82
|
const groups = new Map();
|
|
74
83
|
for (const fact of facts) {
|
|
75
84
|
const line = Number(fact?.value?.line);
|
|
@@ -81,45 +90,27 @@ function semanticFactRegionGroups(facts) {
|
|
|
81
90
|
group.factKinds = uniqueStrings(group.facts.map((item) => item.value?.kind).filter(Boolean));
|
|
82
91
|
groups.set(key, group);
|
|
83
92
|
}
|
|
84
|
-
return [...groups.values()].flatMap(splitSemanticFactGroup);
|
|
93
|
+
return [...groups.values()].flatMap((group) => splitSemanticFactGroup(group, sourceText));
|
|
85
94
|
}
|
|
86
95
|
|
|
87
|
-
function splitSemanticFactGroup(group) {
|
|
88
|
-
if (group.regionKind === 'effect') return splitEffectFactGroup(group);
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
facts: group.facts.filter((fact) => fact.value?.kind === factKind),
|
|
92
|
-
factKinds: [factKind]
|
|
93
|
-
}));
|
|
96
|
+
function splitSemanticFactGroup(group, sourceText) {
|
|
97
|
+
if (group.regionKind === 'effect') return splitEffectFactGroup(group, sourceText);
|
|
98
|
+
if (group.regionKind === 'mutation') return splitMutationFactOccurrences(group, sourceText);
|
|
99
|
+
return group.factKinds.map((factKind) => ({ ...group, facts: group.facts.filter((fact) => fact.value?.kind === factKind), factKinds: [factKind] }));
|
|
94
100
|
}
|
|
95
101
|
|
|
96
|
-
function splitEffectFactGroup(group) {
|
|
97
|
-
const concreteKinds = group.factKinds.filter((kind) => kind !== 'async');
|
|
98
|
-
if (!concreteKinds.length) return [group];
|
|
99
|
-
return concreteKinds.map((factKind, index) => ({
|
|
100
|
-
...group,
|
|
101
|
-
facts: group.facts.filter((fact) => fact.value?.kind === factKind
|
|
102
|
-
|| (index === 0 && fact.value?.kind === 'async')),
|
|
103
|
-
factKinds: uniqueStrings([factKind, index === 0 && group.factKinds.includes('async') ? 'async' : undefined])
|
|
104
|
-
}));
|
|
105
|
-
}
|
|
102
|
+
function splitEffectFactGroup(group, sourceText) { return splitEffectFactOccurrences(group, sourceText); }
|
|
106
103
|
|
|
107
|
-
function semanticFactRegionSignature(group) {
|
|
108
|
-
return (group.factKinds?.length ? group.factKinds : [group.regionKind]).join('+');
|
|
109
|
-
}
|
|
104
|
+
function semanticFactRegionSignature(group) { return (group.factKinds?.length ? group.factKinds : [group.regionKind]).join('+'); }
|
|
110
105
|
|
|
111
106
|
function nextSemanticFactOrdinal(ordinals, group, fact, signature) {
|
|
112
107
|
const key = [group.regionKind, fact.subjectId, group.sourcePath, signature].join('\0');
|
|
113
|
-
const next = (ordinals.get(key) ?? 0) + 1;
|
|
114
|
-
ordinals.set(key, next);
|
|
115
|
-
return next;
|
|
108
|
+
const next = (ordinals.get(key) ?? 0) + 1; ordinals.set(key, next); return next;
|
|
116
109
|
}
|
|
117
110
|
|
|
118
111
|
function semanticFactSubjectCanOwnRuntimeRegion(symbol) {
|
|
119
|
-
if (!symbol) return true;
|
|
120
|
-
|
|
121
|
-
return /function|method|action|effect|handler|constructor/
|
|
122
|
-
.test(String(symbol.kind ?? '').toLowerCase());
|
|
112
|
+
if (!symbol || symbol.metadata?.ownershipRegionKind === 'body') return true;
|
|
113
|
+
return /function|method|action|effect|handler|constructor/.test(String(symbol.kind ?? '').toLowerCase());
|
|
123
114
|
}
|
|
124
115
|
|
|
125
116
|
function semanticFactSpanInfo(sourceText, group, fact, imported) {
|
|
@@ -143,6 +134,7 @@ function semanticFactSpanInfo(sourceText, group, fact, imported) {
|
|
|
143
134
|
}
|
|
144
135
|
|
|
145
136
|
function semanticFactExpressionRange(line, group) {
|
|
137
|
+
if (group.occurrenceRange) return group.occurrenceRange;
|
|
146
138
|
if (group.regionKind === 'effect') return effectRange(line, group.factKinds);
|
|
147
139
|
if (group.regionKind === 'mutation') return mutationRange(line, group.factKinds);
|
|
148
140
|
if (group.regionKind === 'controlFlow') return controlFlowRange(line, group.factKinds);
|
|
@@ -150,12 +142,18 @@ function semanticFactExpressionRange(line, group) {
|
|
|
150
142
|
}
|
|
151
143
|
|
|
152
144
|
function effectRange(line, kinds) {
|
|
145
|
+
if (kinds.includes('tagged-template')) return taggedTemplateRange(line);
|
|
146
|
+
if (kinds.includes('template-interpolation') || kinds.includes('template-literal')) return templateLiteralRange(line);
|
|
153
147
|
if (kinds.includes('network')) return namedCallRange(line, ['fetch', 'XMLHttpRequest', 'WebSocket', 'EventSource'], 'network-call');
|
|
154
|
-
if (kinds.includes('scheduler')) return namedCallRange(line,
|
|
148
|
+
if (kinds.includes('scheduler')) return namedCallRange(line, schedulerEffectNames, 'scheduler-call');
|
|
155
149
|
if (kinds.includes('storage')) return tokenExpressionRange(line, ['localStorage', 'sessionStorage', 'indexedDB', 'caches', 'cookie'], 'storage-effect');
|
|
150
|
+
if (kinds.includes('host-context')) return tokenExpressionRange(line, ['import\\s*\\.\\s*meta(?:\\s*\\.\\s*[A-Za-z_$][\\w$]*)*'], 'import-meta-host-context');
|
|
156
151
|
if (kinds.includes('host')) return tokenExpressionRange(line, ['console', 'process', 'Deno', 'Bun'], 'host-effect');
|
|
157
|
-
if (kinds.includes('browser')) return
|
|
158
|
-
|
|
152
|
+
if (kinds.includes('browser')) return namedCallRange(line, ['Worker', 'SharedWorker'], 'browser-constructor')
|
|
153
|
+
?? tokenExpressionRange(line, ['document', 'window', 'navigator', 'location', 'history'], 'browser-effect');
|
|
154
|
+
if (kinds.includes('async')) return keywordExpressionRange(line, /(await|async)\b/, 'async-effect');
|
|
155
|
+
if (kinds.includes('generator')) return keywordExpressionRange(line, /\byield\b|\bfunction\s*\*/, 'generator-effect');
|
|
156
|
+
if (kinds.includes('getter')) return getterAccessRange(line);
|
|
159
157
|
return undefined;
|
|
160
158
|
}
|
|
161
159
|
|
|
@@ -173,55 +171,66 @@ function controlFlowRange(line, kinds) {
|
|
|
173
171
|
?? caseHeadRange(line) ?? keywordExpressionRange(line, /else\b/, 'control-branch');
|
|
174
172
|
if (kinds.includes('loop')) return controlHeadRange(line, /(for|while)\b/, 'control-loop')
|
|
175
173
|
?? keywordExpressionRange(line, /do\b/, 'control-loop');
|
|
174
|
+
if (kinds.includes('transfer')) return keywordExpressionRange(line, /(break|continue)\b/, 'control-transfer');
|
|
176
175
|
if (kinds.includes('exception')) return keywordExpressionRange(line, /(throw|catch|finally|try)\b/, 'control-exception');
|
|
177
176
|
if (kinds.includes('async')) return keywordExpressionRange(line, /(await|async)\b/, 'control-async');
|
|
178
177
|
return undefined;
|
|
179
178
|
}
|
|
180
179
|
|
|
181
180
|
function namedCallRange(line, names, kind) {
|
|
181
|
+
const ranges = [];
|
|
182
182
|
for (const name of names) {
|
|
183
|
-
const pattern = new RegExp(`(?:^|[^\\w$.])((?:window|globalThis|self)\\s
|
|
183
|
+
const pattern = new RegExp(`(?:^|[^\\w$.])((?:new\\s+)?(?:(?:window|globalThis|self)\\s*(?:\\.|\\?\\.)\\s*)?${name}\\s*(?:\\?\\.)?\\s*\\()`);
|
|
184
184
|
const match = pattern.exec(line);
|
|
185
185
|
if (!match) continue;
|
|
186
|
-
const start = match.index + match[0].search(new RegExp(`((?:window|globalThis|self)\\s
|
|
187
|
-
|
|
188
|
-
const close = matchingParenIndex(line, open);
|
|
189
|
-
return { start, end: close === undefined ? statementEnd(line, open) : close + 1, kind };
|
|
186
|
+
const start = match.index + match[0].search(new RegExp(`(?:new\\s+)?(?:(?:window|globalThis|self)\\s*(?:\\.|\\?\\.)\\s*)?${name}\\s*(?:\\?\\.)?\\s*\\(`));
|
|
187
|
+
ranges.push(callRange(line, start, kind));
|
|
190
188
|
}
|
|
191
|
-
|
|
189
|
+
ranges.push(...globalBracketCallRanges(line, names, kind));
|
|
190
|
+
return ranges.sort((left, right) => left.start - right.start || left.end - right.end)[0];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function globalBracketCallRanges(line, names, kind) {
|
|
194
|
+
const ranges = [];
|
|
195
|
+
for (const name of names) {
|
|
196
|
+
const pattern = new RegExp(`(?:^|[^\\w$.])((?:new\\s+)?(?:window|globalThis|self)\\s*(?:\\?\\.)?\\s*\\[\\s*(['"\`])${name}\\2\\s*\\]\\s*(?:\\?\\.)?\\s*\\()`, 'g');
|
|
197
|
+
for (const match of line.matchAll(pattern)) {
|
|
198
|
+
const start = match.index + match[0].indexOf(match[1]);
|
|
199
|
+
ranges.push(callRange(line, start, kind));
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return ranges;
|
|
192
203
|
}
|
|
193
204
|
|
|
205
|
+
function callRange(line, start, kind) { const open = line.indexOf('(', start); const close = matchingParenIndex(line, open); return { start, end: close === undefined ? statementEnd(line, open) : close + 1, kind }; }
|
|
206
|
+
|
|
194
207
|
function controlHeadRange(line, keyword, kind) {
|
|
195
208
|
const match = keyword.exec(line);
|
|
196
209
|
if (!match) return undefined;
|
|
197
|
-
const open = line.indexOf('(', match.index);
|
|
198
|
-
const close = matchingParenIndex(line, open);
|
|
210
|
+
const open = line.indexOf('(', match.index), close = matchingParenIndex(line, open);
|
|
199
211
|
return close === undefined ? undefined : { start: match.index, end: close + 1, kind };
|
|
200
212
|
}
|
|
201
213
|
|
|
202
214
|
function caseHeadRange(line) {
|
|
203
215
|
const match = /\b(case|default)\b/.exec(line);
|
|
204
216
|
if (!match) return undefined;
|
|
205
|
-
const colon = line.indexOf(':', match.index);
|
|
206
|
-
return { start: match.index, end: colon === -1 ? statementEnd(line, match.index) : colon + 1, kind: 'control-branch' };
|
|
217
|
+
const colon = line.indexOf(':', match.index); return { start: match.index, end: colon === -1 ? statementEnd(line, match.index) : colon + 1, kind: 'control-branch' };
|
|
207
218
|
}
|
|
208
219
|
|
|
209
220
|
function mutatingCallRange(line) {
|
|
210
|
-
const match = /[A-Za-z_$][\w
|
|
221
|
+
const match = /[A-Za-z_$][\w$]*(?:(?:\s*(?:\.|\?\.)\s*[A-Za-z_$][\w$]*)|\s*\[[^\]]+\])*\s*(?:(?:\.|\?\.)\s*(?:push|pop|shift|unshift|splice|sort|reverse|set|add|delete|clear)\s*(?:\?\.)?|\s*(?:\?\.)?\s*\[\s*(['"`])(?:push|pop|shift|unshift|splice|sort|reverse|set|add|delete|clear)\1\s*\]\s*(?:\?\.)?)\s*\(/.exec(line);
|
|
211
222
|
if (!match) return undefined;
|
|
212
|
-
const open = line.indexOf('(', match.index);
|
|
213
|
-
const close = matchingParenIndex(line, open);
|
|
223
|
+
const open = line.indexOf('(', match.index), close = matchingParenIndex(line, open);
|
|
214
224
|
return { start: match.index, end: close === undefined ? statementEnd(line, open) : close + 1, kind: 'mutating-call' };
|
|
215
225
|
}
|
|
216
226
|
|
|
217
227
|
function assignmentRange(line) {
|
|
218
|
-
const match =
|
|
219
|
-
return match ? { start: match.index, end: statementEnd(line, match.index), kind: 'assignment' } : undefined;
|
|
228
|
+
const match = /(^|[^\w$])([A-Za-z_$][\w$]*(?:(?:\s*(?:\.|\?\.)\s*[A-Za-z_$][\w$]*)|\s*\[[^\]]+\])*)\s*=(?!=|>)/.exec(line);
|
|
229
|
+
return match ? { start: match.index + match[1].length, end: statementEnd(line, match.index + match[1].length), kind: 'assignment' } : undefined;
|
|
220
230
|
}
|
|
221
|
-
|
|
222
231
|
function updateRange(line) {
|
|
223
|
-
const match =
|
|
224
|
-
return match ? { start: match.index, end: statementEnd(line, match.index), kind: 'update' } : undefined;
|
|
232
|
+
const match = /(^|[^\w$])([A-Za-z_$][\w$]*(?:(?:\s*(?:\.|\?\.)\s*[A-Za-z_$][\w$]*)|\s*\[[^\]]+\])*)(?:\+\+|--|\s*(?:\+=|-=|\*=|\/=|%=|\|\|=|&&=|\?\?=))/.exec(line);
|
|
233
|
+
return match ? { start: match.index + match[1].length, end: statementEnd(line, match.index + match[1].length), kind: 'update' } : undefined;
|
|
225
234
|
}
|
|
226
235
|
|
|
227
236
|
function tokenExpressionRange(line, tokens, kind) {
|
|
@@ -230,10 +239,43 @@ function tokenExpressionRange(line, tokens, kind) {
|
|
|
230
239
|
return match ? { start: match.index, end: statementEnd(line, match.index), kind } : undefined;
|
|
231
240
|
}
|
|
232
241
|
|
|
242
|
+
function getterAccessRange(line) {
|
|
243
|
+
const pattern = /\b[A-Za-z_$][\w$]*(?:(?:\s*\?\.\s*|\s*\.\s*)[A-Za-z_$][\w$]*|\s*\[[^\]]+\])+/g;
|
|
244
|
+
for (const match of line.matchAll(pattern)) {
|
|
245
|
+
const next = nextNonSpace(line, match.index + match[0].length);
|
|
246
|
+
if (next === '(') continue;
|
|
247
|
+
return { start: match.index, end: match.index + match[0].length, kind: 'getter-access' };
|
|
248
|
+
}
|
|
249
|
+
return undefined;
|
|
250
|
+
}
|
|
251
|
+
function taggedTemplateRange(line) {
|
|
252
|
+
const match = /(?:^|[^\w$.)\]])([A-Za-z_$][\w$]*(?:(?:\s*\.\s*[A-Za-z_$][\w$]*)|\s*\[[^\]]+\])*)\s*`/.exec(line);
|
|
253
|
+
if (!match) return templateLiteralRange(line);
|
|
254
|
+
const start = match.index + match[0].indexOf(match[1]);
|
|
255
|
+
return { start, end: templateEnd(line, line.indexOf('`', start)), kind: 'tagged-template' };
|
|
256
|
+
}
|
|
257
|
+
function templateLiteralRange(line) {
|
|
258
|
+
const start = line.indexOf('`');
|
|
259
|
+
return start < 0 ? undefined : { start, end: templateEnd(line, start), kind: 'template-literal' };
|
|
260
|
+
}
|
|
261
|
+
function templateEnd(line, start) {
|
|
262
|
+
for (let index = start + 1, escaped = false; index < line.length; index += 1) {
|
|
263
|
+
if (escaped) escaped = false;
|
|
264
|
+
else if (line[index] === '\\') escaped = true;
|
|
265
|
+
else if (line[index] === '`') return index + 1;
|
|
266
|
+
}
|
|
267
|
+
return line.length;
|
|
268
|
+
}
|
|
233
269
|
function keywordExpressionRange(line, keyword, kind) {
|
|
234
270
|
const match = keyword instanceof RegExp ? keyword.exec(line) : new RegExp(`\\b${keyword}\\b`).exec(line);
|
|
235
271
|
return match ? { start: match.index, end: statementEnd(line, match.index), kind } : undefined;
|
|
236
272
|
}
|
|
273
|
+
function nextNonSpace(line, index) {
|
|
274
|
+
for (let cursor = index; cursor < line.length; cursor += 1) {
|
|
275
|
+
if (!/\s/.test(line[cursor])) return line[cursor];
|
|
276
|
+
}
|
|
277
|
+
return '';
|
|
278
|
+
}
|
|
237
279
|
|
|
238
280
|
function statementEnd(line, start) {
|
|
239
281
|
const semicolon = line.indexOf(';', Math.max(0, start));
|
|
@@ -264,9 +306,7 @@ function matchingParenIndex(line, open) {
|
|
|
264
306
|
}
|
|
265
307
|
|
|
266
308
|
function semanticFactRegionKey(prefix = 'source', sourcePath, regionKind, symbolName, index) {
|
|
267
|
-
return [prefix, sourcePath ?? 'memory', regionKind, symbolName || `unknown#${index + 1}`]
|
|
268
|
-
.map((part) => String(part).replace(/\s+/g, ' ').trim())
|
|
269
|
-
.join('#');
|
|
309
|
+
return [prefix, sourcePath ?? 'memory', regionKind, symbolName || `unknown#${index + 1}`].map((part) => String(part).replace(/\s+/g, ' ').trim()).join('#');
|
|
270
310
|
}
|
|
271
311
|
|
|
272
312
|
function semanticFactRegionMergePolicy(regionKind) {
|
|
@@ -276,8 +316,5 @@ function semanticFactRegionMergePolicy(regionKind) {
|
|
|
276
316
|
}
|
|
277
317
|
|
|
278
318
|
function nativeImportSourceText(imported) {
|
|
279
|
-
return imported?.metadata?.sourcePreservation?.sourceText
|
|
280
|
-
?? imported?.nativeSource?.metadata?.sourcePreservation?.sourceText
|
|
281
|
-
?? imported?.nativeAst?.metadata?.sourcePreservation?.sourceText
|
|
282
|
-
?? imported?.universalAst?.metadata?.sourcePreservation?.sourceText;
|
|
319
|
+
return imported?.metadata?.sourcePreservation?.sourceText ?? imported?.nativeSource?.metadata?.sourcePreservation?.sourceText ?? imported?.nativeAst?.metadata?.sourcePreservation?.sourceText ?? imported?.universalAst?.metadata?.sourcePreservation?.sourceText;
|
|
283
320
|
}
|