@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
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { JsTsSafeMergeStatuses } from './js-ts-safe-merge-constants.js';
|
|
1
|
+
import { JsTsSafeMergeStatuses, jsTsSafeMergeGateOrder } from './js-ts-safe-merge-constants.js';
|
|
2
2
|
import { createJsTsSafeMergeSemanticArtifacts } from './js-ts-safe-merge-semantic-artifacts.js';
|
|
3
3
|
import { uniqueStrings } from './js-ts-safe-merge-context.js';
|
|
4
|
+
import { attributeMap, isJsxComponentTag, isJsxSpreadAttribute, parseJsxTags, sameAttributeNames, sameAttrText, sameTagText } from './js-ts-safe-merge-jsx-attribute-parser.js';
|
|
5
|
+
import { hasConditionalChildExpressionOperator, parseDirectChildren, parseJsxSource } from './js-ts-safe-merge-jsx-child-expression-parser.js';
|
|
4
6
|
import { semanticFallbackChangedExistingDeclarations } from './js-ts-safe-merge-semantic-edit-fallback-utils.js';
|
|
5
7
|
|
|
6
8
|
function createJsxAttributeSemanticFallbackResult(input, topLevelResult, stagedFallback) {
|
|
@@ -13,7 +15,8 @@ function createJsxAttributeSemanticFallbackResult(input, topLevelResult, stagedF
|
|
|
13
15
|
headSourceText: input.headSourceText,
|
|
14
16
|
currentSourceText
|
|
15
17
|
});
|
|
16
|
-
if (!merge.ok
|
|
18
|
+
if (!merge.ok) return merge.policyBlocker ? jsxAttributeBlockedResult(input, topLevelResult, merge, stagedFallback) : undefined;
|
|
19
|
+
if (merge.sourceText === currentSourceText) return undefined;
|
|
17
20
|
const resultBase = stagedFallback?.stagedTopLevelResult ?? topLevelResult;
|
|
18
21
|
const language = input.language ?? topLevelResult.language ?? 'tsx';
|
|
19
22
|
const sourcePath = input.sourcePath ?? topLevelResult.sourcePath ?? 'inline.tsx';
|
|
@@ -63,6 +66,8 @@ function createJsxAttributeSemanticFallbackResult(input, topLevelResult, stagedF
|
|
|
63
66
|
semanticEditReplayStatus: artifacts.replay.status,
|
|
64
67
|
jsxAttributeTags: merge.summary.tags,
|
|
65
68
|
jsxAttributeEdits: merge.summary.edits,
|
|
69
|
+
jsxComponentPropContractCandidates: merge.summary.componentPropContracts.length,
|
|
70
|
+
jsxComponentPropContractAttributes: merge.summary.componentPropContractAttributes,
|
|
66
71
|
composedPhases: 2
|
|
67
72
|
},
|
|
68
73
|
metadata: {
|
|
@@ -84,6 +89,62 @@ function createJsxAttributeSemanticFallbackResult(input, topLevelResult, stagedF
|
|
|
84
89
|
};
|
|
85
90
|
}
|
|
86
91
|
|
|
92
|
+
function jsxAttributeBlockedResult(input, topLevelResult, merge, stagedFallback) {
|
|
93
|
+
const reasonCodes = uniqueStrings(merge.reasonCodes);
|
|
94
|
+
const gates = jsTsSafeMergeGateOrder.map((id, index) => ({
|
|
95
|
+
id,
|
|
96
|
+
status: index === 0 ? 'blocked' : 'skipped',
|
|
97
|
+
reasonCodes: index === 0 ? reasonCodes : []
|
|
98
|
+
}));
|
|
99
|
+
return {
|
|
100
|
+
...topLevelResult,
|
|
101
|
+
id: String(input.id ?? topLevelResult.id),
|
|
102
|
+
status: JsTsSafeMergeStatuses.blocked,
|
|
103
|
+
mergedSourceText: undefined,
|
|
104
|
+
outputSourceText: undefined,
|
|
105
|
+
conflicts: [{
|
|
106
|
+
code: 'jsx-attribute-policy-blocked',
|
|
107
|
+
gateId: 'parse-ledger',
|
|
108
|
+
message: 'JSX attribute merge policy could not prove stable prop identity and render ordering.',
|
|
109
|
+
side: 'worker',
|
|
110
|
+
sourcePath: input.sourcePath ?? topLevelResult.sourcePath,
|
|
111
|
+
details: { reasonCodes }
|
|
112
|
+
}],
|
|
113
|
+
gates,
|
|
114
|
+
admission: {
|
|
115
|
+
status: 'blocked',
|
|
116
|
+
action: 'human-review',
|
|
117
|
+
reviewRequired: true,
|
|
118
|
+
autoApplyCandidate: false,
|
|
119
|
+
autoMergeClaim: false,
|
|
120
|
+
semanticEquivalenceClaim: false,
|
|
121
|
+
reasonCodes
|
|
122
|
+
},
|
|
123
|
+
summary: {
|
|
124
|
+
...topLevelResult.summary,
|
|
125
|
+
changedExistingDeclarations: semanticFallbackChangedExistingDeclarations(topLevelResult, topLevelResult, stagedFallback),
|
|
126
|
+
conflicts: 1,
|
|
127
|
+
gatesPassed: 0,
|
|
128
|
+
jsxAttributePolicyBlocked: true,
|
|
129
|
+
composedPhases: 2
|
|
130
|
+
},
|
|
131
|
+
metadata: {
|
|
132
|
+
...topLevelResult.metadata,
|
|
133
|
+
composed: {
|
|
134
|
+
phase: stagedFallback ? 'staged-top-level-jsx-attribute-policy-blocked' : 'jsx-attribute-policy-blocked',
|
|
135
|
+
phases: stagedFallback
|
|
136
|
+
? ['top-level-neutralization', 'top-level-ledger', 'jsx-attribute-policy']
|
|
137
|
+
: ['top-level-ledger', 'jsx-attribute-policy'],
|
|
138
|
+
originalReasonCodes: topLevelResult.admission?.reasonCodes ?? [],
|
|
139
|
+
stagedTopLevelSummary: stagedFallback?.stagedTopLevelResult?.summary,
|
|
140
|
+
neutralization: stagedFallback?.neutralization?.summary,
|
|
141
|
+
jsxAttributePolicy: { reasonCodes }
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
semanticArtifacts: topLevelResult.semanticArtifacts
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
87
148
|
function mergeJsxAttributeSources(input) {
|
|
88
149
|
if (![input.baseSourceText, input.workerSourceText, input.headSourceText, input.currentSourceText].every(isString)) {
|
|
89
150
|
return blocked('missing-source-text');
|
|
@@ -91,7 +152,15 @@ function mergeJsxAttributeSources(input) {
|
|
|
91
152
|
const parsed = ['base', 'worker', 'head', 'current'].map((side) => parseJsxTags(input[`${side}SourceText`]));
|
|
92
153
|
if (parsed.some((source) => source.reasonCodes.length)) return blocked('jsx-attribute-parse-blocked');
|
|
93
154
|
const [base, worker, head, current] = parsed;
|
|
155
|
+
if (![worker, head, current].every((source) => sameJsxTagIdentitySequence(base.tags, source.tags))) {
|
|
156
|
+
return blocked('jsx-attribute-element-identity-changed');
|
|
157
|
+
}
|
|
158
|
+
const conditionalChildExpressionRanges = Object.fromEntries(['base', 'worker', 'head', 'current'].map((side) => [
|
|
159
|
+
side,
|
|
160
|
+
jsxConditionalChildExpressionRanges(input[`${side}SourceText`])
|
|
161
|
+
]));
|
|
94
162
|
const edits = [];
|
|
163
|
+
const componentPropContracts = [];
|
|
95
164
|
let changedTags = 0;
|
|
96
165
|
for (const baseTag of base.tags) {
|
|
97
166
|
const workerTag = worker.byKey.get(baseTag.key);
|
|
@@ -99,15 +168,28 @@ function mergeJsxAttributeSources(input) {
|
|
|
99
168
|
const currentTag = current.byKey.get(baseTag.key);
|
|
100
169
|
if (!workerTag || !headTag || !currentTag) continue;
|
|
101
170
|
if (sameTagText(baseTag, workerTag)) continue;
|
|
171
|
+
if (tagInConditionalChildExpression({ base: baseTag, worker: workerTag, head: headTag, current: currentTag }, conditionalChildExpressionRanges)) {
|
|
172
|
+
return blocked('jsx-child-conditional-expression-unsupported');
|
|
173
|
+
}
|
|
102
174
|
const merged = mergeTagAttributes(baseTag, workerTag, headTag, currentTag);
|
|
103
175
|
if (merged.status === 'blocked') return blocked(...merged.reasonCodes);
|
|
104
176
|
for (const edit of merged.edits) edits.push(edit);
|
|
177
|
+
for (const contract of merged.componentPropContracts ?? []) componentPropContracts.push(contract);
|
|
105
178
|
if (merged.edits.length) changedTags += 1;
|
|
106
179
|
}
|
|
107
180
|
if (!edits.length) return blocked('no-jsx-attribute-merge-candidate');
|
|
108
181
|
const sourceText = edits.sort((left, right) => right.start - left.start)
|
|
109
182
|
.reduce((text, edit) => text.slice(0, edit.start) + edit.replacement + text.slice(edit.end), input.currentSourceText);
|
|
110
|
-
return {
|
|
183
|
+
return {
|
|
184
|
+
ok: true,
|
|
185
|
+
sourceText,
|
|
186
|
+
summary: {
|
|
187
|
+
tags: changedTags,
|
|
188
|
+
edits: edits.length,
|
|
189
|
+
componentPropContracts,
|
|
190
|
+
componentPropContractAttributes: componentPropContracts.reduce((total, contract) => total + contract.attributeCount, 0)
|
|
191
|
+
}
|
|
192
|
+
};
|
|
111
193
|
}
|
|
112
194
|
|
|
113
195
|
function mergeTagAttributes(base, worker, head, current) {
|
|
@@ -119,12 +201,23 @@ function mergeTagAttributes(base, worker, head, current) {
|
|
|
119
201
|
}
|
|
120
202
|
const [, workerAttrs, headAttrs, currentAttrs] = maps.map((map) => map.byName);
|
|
121
203
|
const edits = [];
|
|
204
|
+
const changedAttributes = [];
|
|
205
|
+
let workerSpread = false, headSpread = false, workerNamed = false, headNamed = false;
|
|
122
206
|
for (const baseAttr of base.attributes) {
|
|
123
207
|
const workerAttr = workerAttrs.get(baseAttr.name);
|
|
124
208
|
const headAttr = headAttrs.get(baseAttr.name);
|
|
125
209
|
const currentAttr = currentAttrs.get(baseAttr.name);
|
|
126
210
|
const workerChanged = !sameAttrText(baseAttr, workerAttr);
|
|
127
211
|
const headChanged = !sameAttrText(baseAttr, headAttr);
|
|
212
|
+
if (baseAttr.name === 'key' && (workerChanged || headChanged)) {
|
|
213
|
+
return blockedTag('jsx-attribute-key-identity-changed');
|
|
214
|
+
}
|
|
215
|
+
if (workerChanged || headChanged) {
|
|
216
|
+
changedAttributes.push(baseAttr.name);
|
|
217
|
+
const spread = isJsxSpreadAttribute(baseAttr);
|
|
218
|
+
workerSpread ||= spread && workerChanged; headSpread ||= spread && headChanged;
|
|
219
|
+
workerNamed ||= !spread && workerChanged; headNamed ||= !spread && headChanged;
|
|
220
|
+
}
|
|
128
221
|
if (workerChanged && headChanged && !sameAttrText(workerAttr, headAttr)) {
|
|
129
222
|
return blockedTag('jsx-attribute-conflict');
|
|
130
223
|
}
|
|
@@ -135,163 +228,34 @@ function mergeTagAttributes(base, worker, head, current) {
|
|
|
135
228
|
edits.push({ start: currentAttr.start, end: currentAttr.end, replacement: workerAttr.text });
|
|
136
229
|
}
|
|
137
230
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const parsed = parseOpeningTag(sourceText, start);
|
|
150
|
-
if (!parsed) {
|
|
151
|
-
index = start + 1;
|
|
152
|
-
continue;
|
|
153
|
-
}
|
|
154
|
-
if (parsed.reasonCodes.length) reasonCodes.push(...parsed.reasonCodes);
|
|
155
|
-
const ordinal = (ordinals.get(parsed.tagName) ?? 0) + 1;
|
|
156
|
-
ordinals.set(parsed.tagName, ordinal);
|
|
157
|
-
tags.push({ ...parsed, key: `${parsed.tagName}#${ordinal}` });
|
|
158
|
-
index = parsed.end;
|
|
159
|
-
}
|
|
160
|
-
return { tags, byKey: new Map(tags.map((tag) => [tag.key, tag])), reasonCodes: uniqueStrings(reasonCodes) };
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function parseOpeningTag(sourceText, start) {
|
|
164
|
-
const afterOpen = start + 1;
|
|
165
|
-
if (/[/!?>]/.test(sourceText[afterOpen] ?? '')) return undefined;
|
|
166
|
-
const nameMatch = /^[A-Za-z_$][\w$]*(?:[.:][A-Za-z_$][\w$]*|-[\w$]+)*/.exec(sourceText.slice(afterOpen));
|
|
167
|
-
if (!nameMatch) return undefined;
|
|
168
|
-
const tagName = nameMatch[0];
|
|
169
|
-
const nameEnd = afterOpen + tagName.length;
|
|
170
|
-
const end = openingTagEnd(sourceText, nameEnd);
|
|
171
|
-
if (end === undefined) return undefined;
|
|
172
|
-
const attributes = parseAttributes(sourceText, nameEnd, end - 1);
|
|
173
|
-
return {
|
|
174
|
-
tagName,
|
|
175
|
-
start,
|
|
176
|
-
end,
|
|
177
|
-
text: sourceText.slice(start, end),
|
|
178
|
-
attributes: attributes.values,
|
|
179
|
-
reasonCodes: attributes.reasonCodes
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function parseAttributes(sourceText, start, end) {
|
|
184
|
-
const values = [];
|
|
185
|
-
const reasonCodes = [];
|
|
186
|
-
let cursor = start;
|
|
187
|
-
while (cursor < end) {
|
|
188
|
-
while (cursor < end && /\s/.test(sourceText[cursor])) cursor += 1;
|
|
189
|
-
if (sourceText[cursor] === '/') {
|
|
190
|
-
cursor += 1;
|
|
191
|
-
continue;
|
|
192
|
-
}
|
|
193
|
-
const attrStart = cursor;
|
|
194
|
-
const nameMatch = /^[A-Za-z_$][\w$:-]*/.exec(sourceText.slice(cursor, end));
|
|
195
|
-
if (!nameMatch) {
|
|
196
|
-
reasonCodes.push('jsx-attribute-token-unsupported');
|
|
197
|
-
break;
|
|
198
|
-
}
|
|
199
|
-
const name = nameMatch[0];
|
|
200
|
-
cursor += name.length;
|
|
201
|
-
while (cursor < end && /\s/.test(sourceText[cursor])) cursor += 1;
|
|
202
|
-
if (sourceText[cursor] === '=') {
|
|
203
|
-
cursor += 1;
|
|
204
|
-
while (cursor < end && /\s/.test(sourceText[cursor])) cursor += 1;
|
|
205
|
-
cursor = attributeValueEnd(sourceText, cursor, end);
|
|
206
|
-
if (cursor === undefined) return { values, reasonCodes: ['jsx-attribute-value-unterminated'] };
|
|
207
|
-
}
|
|
208
|
-
values.push({ name, start: attrStart, end: cursor, text: sourceText.slice(attrStart, cursor) });
|
|
209
|
-
}
|
|
210
|
-
return { values, reasonCodes: uniqueStrings(reasonCodes) };
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
function openingTagEnd(sourceText, start) {
|
|
214
|
-
let quote;
|
|
215
|
-
let escaped = false;
|
|
216
|
-
let braceDepth = 0;
|
|
217
|
-
for (let index = start; index < sourceText.length; index += 1) {
|
|
218
|
-
const char = sourceText[index];
|
|
219
|
-
if (quote) {
|
|
220
|
-
if (escaped) escaped = false;
|
|
221
|
-
else if (char === '\\') escaped = true;
|
|
222
|
-
else if (char === quote) quote = undefined;
|
|
223
|
-
continue;
|
|
224
|
-
}
|
|
225
|
-
if (char === '"' || char === '\'' || char === '`') quote = char;
|
|
226
|
-
else if (char === '{') braceDepth += 1;
|
|
227
|
-
else if (char === '}') braceDepth = Math.max(0, braceDepth - 1);
|
|
228
|
-
else if (char === '>' && braceDepth === 0) return index + 1;
|
|
229
|
-
}
|
|
230
|
-
return undefined;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
function attributeValueEnd(sourceText, start, end) {
|
|
234
|
-
const first = sourceText[start];
|
|
235
|
-
if (first === '"' || first === '\'') return quotedValueEnd(sourceText, start, end, first);
|
|
236
|
-
if (first === '{') return bracedValueEnd(sourceText, start, end);
|
|
237
|
-
let cursor = start;
|
|
238
|
-
while (cursor < end && !/[\s/]/.test(sourceText[cursor])) cursor += 1;
|
|
239
|
-
return cursor;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
function quotedValueEnd(sourceText, start, end, quote) {
|
|
243
|
-
let escaped = false;
|
|
244
|
-
for (let cursor = start + 1; cursor < end; cursor += 1) {
|
|
245
|
-
const char = sourceText[cursor];
|
|
246
|
-
if (escaped) escaped = false;
|
|
247
|
-
else if (char === '\\') escaped = true;
|
|
248
|
-
else if (char === quote) return cursor + 1;
|
|
249
|
-
}
|
|
250
|
-
return undefined;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
function bracedValueEnd(sourceText, start, end) {
|
|
254
|
-
let depth = 0;
|
|
255
|
-
let quote;
|
|
256
|
-
let escaped = false;
|
|
257
|
-
for (let cursor = start; cursor < end; cursor += 1) {
|
|
258
|
-
const char = sourceText[cursor];
|
|
259
|
-
if (quote) {
|
|
260
|
-
if (escaped) escaped = false;
|
|
261
|
-
else if (char === '\\') escaped = true;
|
|
262
|
-
else if (char === quote) quote = undefined;
|
|
263
|
-
continue;
|
|
264
|
-
}
|
|
265
|
-
if (char === '"' || char === '\'' || char === '`') quote = char;
|
|
266
|
-
else if (char === '{') depth += 1;
|
|
267
|
-
else if (char === '}') {
|
|
268
|
-
depth -= 1;
|
|
269
|
-
if (depth === 0) return cursor + 1;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
return undefined;
|
|
231
|
+
if ((workerSpread && headNamed) || (headSpread && workerNamed)) return blockedTag('jsx-attribute-spread-explicit-precedence-unsupported');
|
|
232
|
+
const contractAttributes = uniqueStrings(changedAttributes);
|
|
233
|
+
const componentPropContracts = isJsxComponentTag(base.tagName) && contractAttributes.length
|
|
234
|
+
? [{
|
|
235
|
+
tagName: base.tagName,
|
|
236
|
+
tagKey: base.key,
|
|
237
|
+
attributes: contractAttributes,
|
|
238
|
+
attributeCount: contractAttributes.length
|
|
239
|
+
}]
|
|
240
|
+
: [];
|
|
241
|
+
return { status: 'merged', edits, componentPropContracts };
|
|
273
242
|
}
|
|
274
243
|
|
|
275
|
-
function
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
if (
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
return left.attributes.map((attr) => attr.name).join('\0') === right.attributes.map((attr) => attr.name).join('\0');
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
function sameTagText(left, right) {
|
|
290
|
-
return String(left?.text ?? '').trim() === String(right?.text ?? '').trim();
|
|
244
|
+
function jsxConditionalChildExpressionRanges(sourceText) {
|
|
245
|
+
const parsed = parseJsxSource(sourceText);
|
|
246
|
+
if (parsed.reasonCodes.length) return [];
|
|
247
|
+
return parsed.elements.flatMap((element) => {
|
|
248
|
+
if (element.selfClosing) return [];
|
|
249
|
+
const children = parseDirectChildren(sourceText, parsed, element);
|
|
250
|
+
if (children.reasonCodes.length) return [];
|
|
251
|
+
return children.tokens
|
|
252
|
+
.filter((token) => token.kind === 'expression' && hasConditionalChildExpressionOperator(token.text))
|
|
253
|
+
.map((token) => ({ start: token.start, end: token.end }));
|
|
254
|
+
});
|
|
291
255
|
}
|
|
292
256
|
|
|
293
|
-
function
|
|
294
|
-
return
|
|
257
|
+
function tagInConditionalChildExpression(tagsBySide, rangesBySide) {
|
|
258
|
+
return Object.entries(tagsBySide).some(([side, tag]) => (rangesBySide[side] ?? []).some((range) => range.start < tag.start && tag.end < range.end));
|
|
295
259
|
}
|
|
296
260
|
|
|
297
261
|
function semanticArtifactGates(artifacts) {
|
|
@@ -308,7 +272,12 @@ function gate(id, passed, reasonCodes = []) {
|
|
|
308
272
|
}
|
|
309
273
|
|
|
310
274
|
function blocked(...reasonCodes) {
|
|
311
|
-
|
|
275
|
+
const normalized = uniqueStrings(reasonCodes);
|
|
276
|
+
return {
|
|
277
|
+
ok: false,
|
|
278
|
+
reasonCodes: normalized,
|
|
279
|
+
policyBlocker: normalized.some((reason) => jsxAttributePolicyBlockers.has(reason))
|
|
280
|
+
};
|
|
312
281
|
}
|
|
313
282
|
|
|
314
283
|
function blockedTag(...reasonCodes) {
|
|
@@ -316,5 +285,30 @@ function blockedTag(...reasonCodes) {
|
|
|
316
285
|
}
|
|
317
286
|
|
|
318
287
|
function isString(value) { return typeof value === 'string'; }
|
|
288
|
+
function sameJsxTagIdentitySequence(leftTags, rightTags) {
|
|
289
|
+
return jsxTagIdentitySequence(leftTags) === jsxTagIdentitySequence(rightTags);
|
|
290
|
+
}
|
|
291
|
+
function jsxTagIdentitySequence(tags = []) {
|
|
292
|
+
return tags.map((tag, index) => {
|
|
293
|
+
const keyAttr = tag.attributes.find((attribute) => attribute.name === 'key');
|
|
294
|
+
return [tag.tagName, stableJsxKeyAttrText(keyAttr) ?? `ordinal:${index + 1}`].join('#');
|
|
295
|
+
}).join('\0');
|
|
296
|
+
}
|
|
297
|
+
function stableJsxKeyAttrText(attribute) {
|
|
298
|
+
if (!attribute) return undefined;
|
|
299
|
+
const match = /^key\s*=\s*(?:"([^"]*)"|'([^']*)')\s*$/.exec(String(attribute.text ?? '').trim());
|
|
300
|
+
if (!match) return undefined;
|
|
301
|
+
return `key:${match[1] ?? match[2] ?? ''}`;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const jsxAttributePolicyBlockers = new Set([
|
|
305
|
+
'jsx-attribute-conflict',
|
|
306
|
+
'jsx-attribute-current-diverged',
|
|
307
|
+
'jsx-attribute-duplicate-name',
|
|
308
|
+
'jsx-attribute-key-identity-changed',
|
|
309
|
+
'jsx-attribute-shape-changed',
|
|
310
|
+
'jsx-attribute-spread-explicit-precedence-unsupported',
|
|
311
|
+
'jsx-child-conditional-expression-unsupported'
|
|
312
|
+
]);
|
|
319
313
|
|
|
320
314
|
export { createJsxAttributeSemanticFallbackResult };
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { uniqueStrings } from './js-ts-safe-merge-context.js';
|
|
2
|
+
|
|
3
|
+
export function parseJsxTags(sourceText) {
|
|
4
|
+
const tags = [];
|
|
5
|
+
const reasonCodes = [];
|
|
6
|
+
const ordinals = new Map();
|
|
7
|
+
let index = 0;
|
|
8
|
+
while (index < sourceText.length) {
|
|
9
|
+
const start = sourceText.indexOf('<', index);
|
|
10
|
+
if (start === -1) break;
|
|
11
|
+
const parsed = parseOpeningTag(sourceText, start);
|
|
12
|
+
if (!parsed) {
|
|
13
|
+
index = start + 1;
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
if (parsed.reasonCodes.length) reasonCodes.push(...parsed.reasonCodes);
|
|
17
|
+
const ordinal = (ordinals.get(parsed.tagName) ?? 0) + 1;
|
|
18
|
+
ordinals.set(parsed.tagName, ordinal);
|
|
19
|
+
tags.push({ ...parsed, key: `${parsed.tagName}#${ordinal}` });
|
|
20
|
+
index = parsed.end;
|
|
21
|
+
}
|
|
22
|
+
return { tags, byKey: new Map(tags.map((tag) => [tag.key, tag])), reasonCodes: uniqueStrings(reasonCodes) };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function attributeMap(tag) {
|
|
26
|
+
const byName = new Map();
|
|
27
|
+
const duplicateNames = [];
|
|
28
|
+
for (const attribute of tag.attributes) {
|
|
29
|
+
if (byName.has(attribute.name)) duplicateNames.push(attribute.name);
|
|
30
|
+
byName.set(attribute.name, attribute);
|
|
31
|
+
}
|
|
32
|
+
return { byName, reasonCodes: duplicateNames.length ? ['jsx-attribute-duplicate-name'] : [] };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function sameAttributeNames(left, right) {
|
|
36
|
+
return left.attributes.map((attr) => attr.name).join('\0') === right.attributes.map((attr) => attr.name).join('\0');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function sameTagText(left, right) {
|
|
40
|
+
return String(left?.text ?? '').trim() === String(right?.text ?? '').trim();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function sameAttrText(left, right) {
|
|
44
|
+
return String(left?.text ?? '').trim() === String(right?.text ?? '').trim();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function isJsxSpreadAttribute(attribute) {
|
|
48
|
+
return attribute?.kind === 'spread' || attribute?.spread === true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function isJsxComponentTag(tagName) {
|
|
52
|
+
const firstSegment = String(tagName ?? '').split(/[.:]/)[0] ?? '';
|
|
53
|
+
return /^[A-Z]/.test(firstSegment);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function jsxContextProviderBoundary(tagName) {
|
|
57
|
+
const segments = String(tagName ?? '').split(/[.:]/).filter(Boolean);
|
|
58
|
+
if (segments.length < 2 || segments[segments.length - 1] !== 'Provider') return undefined;
|
|
59
|
+
return { kind: 'context-provider', contextName: segments.slice(0, -1).join('.') };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function jsxContextProviderAncestorMap(tags, sourceText) {
|
|
63
|
+
const tagsByStart = new Map(tags.map((tag) => [tag.start, tag]));
|
|
64
|
+
const ancestorsByStart = new Map();
|
|
65
|
+
const providerStack = [];
|
|
66
|
+
for (const token of jsxTagTokens(sourceText)) {
|
|
67
|
+
if (token.kind === 'closing') {
|
|
68
|
+
closeContextProviderStack(providerStack, token.tagName);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const tag = tagsByStart.get(token.start);
|
|
72
|
+
if (tag) ancestorsByStart.set(tag.start, providerStack.map((provider) => ({ ...provider })));
|
|
73
|
+
const boundary = jsxContextProviderBoundary(token.tagName);
|
|
74
|
+
if (boundary && !token.selfClosing) {
|
|
75
|
+
providerStack.push({
|
|
76
|
+
tagName: token.tagName,
|
|
77
|
+
contextName: boundary.contextName,
|
|
78
|
+
contextBoundaryKind: boundary.kind,
|
|
79
|
+
start: token.start,
|
|
80
|
+
end: token.end
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return ancestorsByStart;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function closeContextProviderStack(providerStack, tagName) {
|
|
88
|
+
for (let index = providerStack.length - 1; index >= 0; index -= 1) {
|
|
89
|
+
if (providerStack[index].tagName !== tagName) continue;
|
|
90
|
+
providerStack.splice(index);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function jsxTagTokens(sourceText) {
|
|
96
|
+
const tokens = [];
|
|
97
|
+
let index = 0;
|
|
98
|
+
while (index < sourceText.length) {
|
|
99
|
+
const start = sourceText.indexOf('<', index);
|
|
100
|
+
if (start === -1) break;
|
|
101
|
+
if (sourceText[start + 1] === '/') {
|
|
102
|
+
const token = jsxClosingTagToken(sourceText, start);
|
|
103
|
+
if (token) tokens.push(token);
|
|
104
|
+
index = token?.end ?? start + 1;
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const token = jsxOpeningTagToken(sourceText, start);
|
|
108
|
+
if (token) tokens.push(token);
|
|
109
|
+
index = token?.end ?? start + 1;
|
|
110
|
+
}
|
|
111
|
+
return tokens;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function jsxOpeningTagToken(sourceText, start) {
|
|
115
|
+
const parsed = parseOpeningTag(sourceText, start);
|
|
116
|
+
if (!parsed) return undefined;
|
|
117
|
+
return { kind: 'opening', tagName: parsed.tagName, start: parsed.start, end: parsed.end, selfClosing: jsxOpeningTagSelfClosing(sourceText, parsed.end) };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function jsxClosingTagToken(sourceText, start) {
|
|
121
|
+
const afterOpen = start + 2;
|
|
122
|
+
const nameMatch = /^[A-Za-z_$][\w$]*(?:[.:][A-Za-z_$][\w$]*|-[\w$]+)*/.exec(sourceText.slice(afterOpen));
|
|
123
|
+
if (!nameMatch) return undefined;
|
|
124
|
+
const end = sourceText.indexOf('>', afterOpen + nameMatch[0].length);
|
|
125
|
+
if (end === -1) return undefined;
|
|
126
|
+
return { kind: 'closing', tagName: nameMatch[0], start, end: end + 1 };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function jsxOpeningTagSelfClosing(sourceText, end) {
|
|
130
|
+
let cursor = end - 2;
|
|
131
|
+
while (cursor >= 0 && /\s/.test(sourceText[cursor])) cursor -= 1;
|
|
132
|
+
return sourceText[cursor] === '/';
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function parseOpeningTag(sourceText, start) {
|
|
136
|
+
const afterOpen = start + 1;
|
|
137
|
+
if (/[/!?>]/.test(sourceText[afterOpen] ?? '')) return undefined;
|
|
138
|
+
const nameMatch = /^[A-Za-z_$][\w$]*(?:[.:][A-Za-z_$][\w$]*|-[\w$]+)*/.exec(sourceText.slice(afterOpen));
|
|
139
|
+
if (!nameMatch) return undefined;
|
|
140
|
+
const tagName = nameMatch[0];
|
|
141
|
+
const nameEnd = afterOpen + tagName.length;
|
|
142
|
+
const end = openingTagEnd(sourceText, nameEnd);
|
|
143
|
+
if (end === undefined) return undefined;
|
|
144
|
+
const attributes = parseAttributes(sourceText, nameEnd, end - 1);
|
|
145
|
+
return {
|
|
146
|
+
tagName,
|
|
147
|
+
start,
|
|
148
|
+
end,
|
|
149
|
+
text: sourceText.slice(start, end),
|
|
150
|
+
attributes: attributes.values,
|
|
151
|
+
reasonCodes: attributes.reasonCodes
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function parseAttributes(sourceText, start, end) {
|
|
156
|
+
const values = [];
|
|
157
|
+
const reasonCodes = [];
|
|
158
|
+
let cursor = start;
|
|
159
|
+
let spreadOrdinal = 0;
|
|
160
|
+
while (cursor < end) {
|
|
161
|
+
while (cursor < end && /\s/.test(sourceText[cursor])) cursor += 1;
|
|
162
|
+
if (sourceText[cursor] === '/') {
|
|
163
|
+
cursor += 1;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
const attrStart = cursor;
|
|
167
|
+
const spreadEnd = spreadAttributeEnd(sourceText, cursor, end);
|
|
168
|
+
if (spreadEnd !== undefined) {
|
|
169
|
+
spreadOrdinal += 1;
|
|
170
|
+
values.push({
|
|
171
|
+
kind: 'spread',
|
|
172
|
+
spread: true,
|
|
173
|
+
spreadOrdinal,
|
|
174
|
+
name: `...spread#${spreadOrdinal}`,
|
|
175
|
+
start: attrStart,
|
|
176
|
+
end: spreadEnd,
|
|
177
|
+
text: sourceText.slice(attrStart, spreadEnd),
|
|
178
|
+
expressionText: spreadExpressionText(sourceText, attrStart, spreadEnd)
|
|
179
|
+
});
|
|
180
|
+
cursor = spreadEnd;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
const nameMatch = /^[A-Za-z_$][\w$:-]*/.exec(sourceText.slice(cursor, end));
|
|
184
|
+
if (!nameMatch) {
|
|
185
|
+
reasonCodes.push('jsx-attribute-token-unsupported');
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
const name = nameMatch[0];
|
|
189
|
+
cursor += name.length;
|
|
190
|
+
while (cursor < end && /\s/.test(sourceText[cursor])) cursor += 1;
|
|
191
|
+
if (sourceText[cursor] === '=') {
|
|
192
|
+
cursor += 1;
|
|
193
|
+
while (cursor < end && /\s/.test(sourceText[cursor])) cursor += 1;
|
|
194
|
+
cursor = attributeValueEnd(sourceText, cursor, end);
|
|
195
|
+
if (cursor === undefined) return { values, reasonCodes: ['jsx-attribute-value-unterminated'] };
|
|
196
|
+
}
|
|
197
|
+
values.push({ name, start: attrStart, end: cursor, text: sourceText.slice(attrStart, cursor) });
|
|
198
|
+
}
|
|
199
|
+
return { values, reasonCodes: uniqueStrings(reasonCodes) };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function spreadAttributeEnd(sourceText, start, end) {
|
|
203
|
+
if (sourceText[start] !== '{') return undefined;
|
|
204
|
+
let cursor = start + 1;
|
|
205
|
+
while (cursor < end && /\s/.test(sourceText[cursor])) cursor += 1;
|
|
206
|
+
if (sourceText.slice(cursor, cursor + 3) !== '...') return undefined;
|
|
207
|
+
return bracedValueEnd(sourceText, start, end);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function spreadExpressionText(sourceText, start, end) {
|
|
211
|
+
let cursor = start + 1;
|
|
212
|
+
while (cursor < end && /\s/.test(sourceText[cursor])) cursor += 1;
|
|
213
|
+
cursor += 3;
|
|
214
|
+
return sourceText.slice(cursor, Math.max(cursor, end - 1)).trim();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function openingTagEnd(sourceText, start) {
|
|
218
|
+
let quote;
|
|
219
|
+
let escaped = false;
|
|
220
|
+
let braceDepth = 0;
|
|
221
|
+
for (let index = start; index < sourceText.length; index += 1) {
|
|
222
|
+
const char = sourceText[index];
|
|
223
|
+
if (quote) {
|
|
224
|
+
if (escaped) escaped = false;
|
|
225
|
+
else if (char === '\\') escaped = true;
|
|
226
|
+
else if (char === quote) quote = undefined;
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
if (char === '"' || char === '\'' || char === '`') quote = char;
|
|
230
|
+
else if (char === '{') braceDepth += 1;
|
|
231
|
+
else if (char === '}') braceDepth = Math.max(0, braceDepth - 1);
|
|
232
|
+
else if (char === '>' && braceDepth === 0) return index + 1;
|
|
233
|
+
}
|
|
234
|
+
return undefined;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function attributeValueEnd(sourceText, start, end) {
|
|
238
|
+
const first = sourceText[start];
|
|
239
|
+
if (first === '"' || first === '\'') return quotedValueEnd(sourceText, start, end, first);
|
|
240
|
+
if (first === '{') return bracedValueEnd(sourceText, start, end);
|
|
241
|
+
let cursor = start;
|
|
242
|
+
while (cursor < end && !/[\s/]/.test(sourceText[cursor])) cursor += 1;
|
|
243
|
+
return cursor;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function quotedValueEnd(sourceText, start, end, quote) {
|
|
247
|
+
let escaped = false;
|
|
248
|
+
for (let cursor = start + 1; cursor < end; cursor += 1) {
|
|
249
|
+
const char = sourceText[cursor];
|
|
250
|
+
if (escaped) escaped = false;
|
|
251
|
+
else if (char === '\\') escaped = true;
|
|
252
|
+
else if (char === quote) return cursor + 1;
|
|
253
|
+
}
|
|
254
|
+
return undefined;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function bracedValueEnd(sourceText, start, end) {
|
|
258
|
+
let depth = 0;
|
|
259
|
+
let quote;
|
|
260
|
+
let escaped = false;
|
|
261
|
+
for (let cursor = start; cursor < end; cursor += 1) {
|
|
262
|
+
const char = sourceText[cursor];
|
|
263
|
+
if (quote) {
|
|
264
|
+
if (escaped) escaped = false;
|
|
265
|
+
else if (char === '\\') escaped = true;
|
|
266
|
+
else if (char === quote) quote = undefined;
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
if (char === '"' || char === '\'' || char === '`') quote = char;
|
|
270
|
+
else if (char === '{') depth += 1;
|
|
271
|
+
else if (char === '}') {
|
|
272
|
+
depth -= 1;
|
|
273
|
+
if (depth === 0) return cursor + 1;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|