@variance-authority/core 0.1.0

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.
Files changed (260) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/LICENSE +21 -0
  3. package/README.md +169 -0
  4. package/dist/artifact.d.ts +47 -0
  5. package/dist/artifact.js +2 -0
  6. package/dist/artifact.js.map +1 -0
  7. package/dist/attribute/because.d.ts +43 -0
  8. package/dist/attribute/because.js +64 -0
  9. package/dist/attribute/because.js.map +1 -0
  10. package/dist/attribute/boundary.d.ts +191 -0
  11. package/dist/attribute/boundary.js +328 -0
  12. package/dist/attribute/boundary.js.map +1 -0
  13. package/dist/attribute/call-site.d.ts +96 -0
  14. package/dist/attribute/call-site.js +183 -0
  15. package/dist/attribute/call-site.js.map +1 -0
  16. package/dist/attribute/component-hash.d.ts +188 -0
  17. package/dist/attribute/component-hash.js +312 -0
  18. package/dist/attribute/component-hash.js.map +1 -0
  19. package/dist/attribute/composition-fixture.d.ts +18 -0
  20. package/dist/attribute/composition-fixture.js +53 -0
  21. package/dist/attribute/composition-fixture.js.map +1 -0
  22. package/dist/attribute/composition.d.ts +182 -0
  23. package/dist/attribute/composition.js +169 -0
  24. package/dist/attribute/composition.js.map +1 -0
  25. package/dist/attribute/control.d.ts +43 -0
  26. package/dist/attribute/control.js +54 -0
  27. package/dist/attribute/control.js.map +1 -0
  28. package/dist/attribute/coverage.d.ts +99 -0
  29. package/dist/attribute/coverage.js +86 -0
  30. package/dist/attribute/coverage.js.map +1 -0
  31. package/dist/attribute/divergence.d.ts +102 -0
  32. package/dist/attribute/divergence.js +152 -0
  33. package/dist/attribute/divergence.js.map +1 -0
  34. package/dist/attribute/index.d.ts +43 -0
  35. package/dist/attribute/index.js +29 -0
  36. package/dist/attribute/index.js.map +1 -0
  37. package/dist/attribute/instability.d.ts +89 -0
  38. package/dist/attribute/instability.js +183 -0
  39. package/dist/attribute/instability.js.map +1 -0
  40. package/dist/attribute/instances.d.ts +145 -0
  41. package/dist/attribute/instances.js +140 -0
  42. package/dist/attribute/instances.js.map +1 -0
  43. package/dist/attribute/locate.d.ts +22 -0
  44. package/dist/attribute/locate.js +100 -0
  45. package/dist/attribute/locate.js.map +1 -0
  46. package/dist/attribute/mask.d.ts +156 -0
  47. package/dist/attribute/mask.js +201 -0
  48. package/dist/attribute/mask.js.map +1 -0
  49. package/dist/attribute/movement.d.ts +211 -0
  50. package/dist/attribute/movement.js +181 -0
  51. package/dist/attribute/movement.js.map +1 -0
  52. package/dist/attribute/region.d.ts +188 -0
  53. package/dist/attribute/region.js +144 -0
  54. package/dist/attribute/region.js.map +1 -0
  55. package/dist/attribute/source-map.d.ts +98 -0
  56. package/dist/attribute/source-map.js +264 -0
  57. package/dist/attribute/source-map.js.map +1 -0
  58. package/dist/attribute/source.d.ts +77 -0
  59. package/dist/attribute/source.js +95 -0
  60. package/dist/attribute/source.js.map +1 -0
  61. package/dist/attribute/stack.d.ts +80 -0
  62. package/dist/attribute/stack.js +108 -0
  63. package/dist/attribute/stack.js.map +1 -0
  64. package/dist/compare/band.d.ts +85 -0
  65. package/dist/compare/band.js +70 -0
  66. package/dist/compare/band.js.map +1 -0
  67. package/dist/compare/cascade.d.ts +45 -0
  68. package/dist/compare/cascade.js +71 -0
  69. package/dist/compare/cascade.js.map +1 -0
  70. package/dist/compare/derive.d.ts +78 -0
  71. package/dist/compare/derive.js +39 -0
  72. package/dist/compare/derive.js.map +1 -0
  73. package/dist/compare/diff/attribution.d.ts +23 -0
  74. package/dist/compare/diff/attribution.js +244 -0
  75. package/dist/compare/diff/attribution.js.map +1 -0
  76. package/dist/compare/diff/compare-nodes.d.ts +15 -0
  77. package/dist/compare/diff/compare-nodes.js +227 -0
  78. package/dist/compare/diff/compare-nodes.js.map +1 -0
  79. package/dist/compare/diff/components.d.ts +20 -0
  80. package/dist/compare/diff/components.js +76 -0
  81. package/dist/compare/diff/components.js.map +1 -0
  82. package/dist/compare/diff/delta.d.ts +165 -0
  83. package/dist/compare/diff/delta.js +12 -0
  84. package/dist/compare/diff/delta.js.map +1 -0
  85. package/dist/compare/diff/index.d.ts +69 -0
  86. package/dist/compare/diff/index.js +101 -0
  87. package/dist/compare/diff/index.js.map +1 -0
  88. package/dist/compare/diff/match.d.ts +37 -0
  89. package/dist/compare/diff/match.js +167 -0
  90. package/dist/compare/diff/match.js.map +1 -0
  91. package/dist/compare/explain.d.ts +23 -0
  92. package/dist/compare/explain.js +190 -0
  93. package/dist/compare/explain.js.map +1 -0
  94. package/dist/compare/holding-diff.d.ts +25 -0
  95. package/dist/compare/holding-diff.js +74 -0
  96. package/dist/compare/holding-diff.js.map +1 -0
  97. package/dist/compare/impact.d.ts +56 -0
  98. package/dist/compare/impact.js +124 -0
  99. package/dist/compare/impact.js.map +1 -0
  100. package/dist/compare/index.d.ts +30 -0
  101. package/dist/compare/index.js +22 -0
  102. package/dist/compare/index.js.map +1 -0
  103. package/dist/compare/instance.d.ts +30 -0
  104. package/dist/compare/instance.js +145 -0
  105. package/dist/compare/instance.js.map +1 -0
  106. package/dist/compare/observability.d.ts +49 -0
  107. package/dist/compare/observability.js +57 -0
  108. package/dist/compare/observability.js.map +1 -0
  109. package/dist/compare/parting.d.ts +179 -0
  110. package/dist/compare/parting.js +244 -0
  111. package/dist/compare/parting.js.map +1 -0
  112. package/dist/compare/slice.d.ts +74 -0
  113. package/dist/compare/slice.js +79 -0
  114. package/dist/compare/slice.js.map +1 -0
  115. package/dist/compare/value.d.ts +60 -0
  116. package/dist/compare/value.js +111 -0
  117. package/dist/compare/value.js.map +1 -0
  118. package/dist/format/accessibility.d.ts +27 -0
  119. package/dist/format/accessibility.js +17 -0
  120. package/dist/format/accessibility.js.map +1 -0
  121. package/dist/format/canonical.d.ts +38 -0
  122. package/dist/format/canonical.js +65 -0
  123. package/dist/format/canonical.js.map +1 -0
  124. package/dist/format/capture.d.ts +212 -0
  125. package/dist/format/capture.js +2 -0
  126. package/dist/format/capture.js.map +1 -0
  127. package/dist/format/document.d.ts +279 -0
  128. package/dist/format/document.js +65 -0
  129. package/dist/format/document.js.map +1 -0
  130. package/dist/format/environment.d.ts +120 -0
  131. package/dist/format/environment.js +53 -0
  132. package/dist/format/environment.js.map +1 -0
  133. package/dist/format/hash.d.ts +45 -0
  134. package/dist/format/hash.js +41 -0
  135. package/dist/format/hash.js.map +1 -0
  136. package/dist/format/holding.d.ts +134 -0
  137. package/dist/format/holding.js +2 -0
  138. package/dist/format/holding.js.map +1 -0
  139. package/dist/format/index.d.ts +39 -0
  140. package/dist/format/index.js +25 -0
  141. package/dist/format/index.js.map +1 -0
  142. package/dist/format/intervention.d.ts +87 -0
  143. package/dist/format/intervention.js +11 -0
  144. package/dist/format/intervention.js.map +1 -0
  145. package/dist/format/profile.d.ts +59 -0
  146. package/dist/format/profile.js +66 -0
  147. package/dist/format/profile.js.map +1 -0
  148. package/dist/format/provenance.d.ts +179 -0
  149. package/dist/format/provenance.js +222 -0
  150. package/dist/format/provenance.js.map +1 -0
  151. package/dist/format/sha256.d.ts +34 -0
  152. package/dist/format/sha256.js +152 -0
  153. package/dist/format/sha256.js.map +1 -0
  154. package/dist/format/snapshot.d.ts +263 -0
  155. package/dist/format/snapshot.js +2 -0
  156. package/dist/format/snapshot.js.map +1 -0
  157. package/dist/format/stabilize.d.ts +190 -0
  158. package/dist/format/stabilize.js +333 -0
  159. package/dist/format/stabilize.js.map +1 -0
  160. package/dist/format/tier.d.ts +19 -0
  161. package/dist/format/tier.js +11 -0
  162. package/dist/format/tier.js.map +1 -0
  163. package/dist/format/value.d.ts +115 -0
  164. package/dist/format/value.js +182 -0
  165. package/dist/format/value.js.map +1 -0
  166. package/dist/format/wiring.d.ts +115 -0
  167. package/dist/format/wiring.js +60 -0
  168. package/dist/format/wiring.js.map +1 -0
  169. package/dist/index.d.ts +35 -0
  170. package/dist/index.js +35 -0
  171. package/dist/index.js.map +1 -0
  172. package/dist/judge/docket.d.ts +85 -0
  173. package/dist/judge/docket.js +162 -0
  174. package/dist/judge/docket.js.map +1 -0
  175. package/dist/judge/fingerprint.d.ts +53 -0
  176. package/dist/judge/fingerprint.js +144 -0
  177. package/dist/judge/fingerprint.js.map +1 -0
  178. package/dist/judge/ignore.d.ts +206 -0
  179. package/dist/judge/ignore.js +237 -0
  180. package/dist/judge/ignore.js.map +1 -0
  181. package/dist/judge/index.d.ts +44 -0
  182. package/dist/judge/index.js +34 -0
  183. package/dist/judge/index.js.map +1 -0
  184. package/dist/judge/inspect.d.ts +148 -0
  185. package/dist/judge/inspect.js +208 -0
  186. package/dist/judge/inspect.js.map +1 -0
  187. package/dist/judge/intent.d.ts +146 -0
  188. package/dist/judge/intent.js +150 -0
  189. package/dist/judge/intent.js.map +1 -0
  190. package/dist/judge/locale.d.ts +111 -0
  191. package/dist/judge/locale.js +247 -0
  192. package/dist/judge/locale.js.map +1 -0
  193. package/dist/judge/scope.d.ts +41 -0
  194. package/dist/judge/scope.js +47 -0
  195. package/dist/judge/scope.js.map +1 -0
  196. package/dist/judge/sensitivity.d.ts +202 -0
  197. package/dist/judge/sensitivity.js +152 -0
  198. package/dist/judge/sensitivity.js.map +1 -0
  199. package/dist/judge/trail.d.ts +122 -0
  200. package/dist/judge/trail.js +96 -0
  201. package/dist/judge/trail.js.map +1 -0
  202. package/dist/judge/verdict.d.ts +39 -0
  203. package/dist/judge/verdict.js +32 -0
  204. package/dist/judge/verdict.js.map +1 -0
  205. package/dist/plan/index.d.ts +12 -0
  206. package/dist/plan/index.js +11 -0
  207. package/dist/plan/index.js.map +1 -0
  208. package/dist/plan/tool.d.ts +85 -0
  209. package/dist/plan/tool.js +87 -0
  210. package/dist/plan/tool.js.map +1 -0
  211. package/dist/relate/graph.d.ts +190 -0
  212. package/dist/relate/graph.js +234 -0
  213. package/dist/relate/graph.js.map +1 -0
  214. package/dist/relate/index.d.ts +16 -0
  215. package/dist/relate/index.js +16 -0
  216. package/dist/relate/index.js.map +1 -0
  217. package/dist/relate/merkle.d.ts +110 -0
  218. package/dist/relate/merkle.js +246 -0
  219. package/dist/relate/merkle.js.map +1 -0
  220. package/dist/relate/reach.d.ts +65 -0
  221. package/dist/relate/reach.js +111 -0
  222. package/dist/relate/reach.js.map +1 -0
  223. package/dist/relate/records.d.ts +129 -0
  224. package/dist/relate/records.js +112 -0
  225. package/dist/relate/records.js.map +1 -0
  226. package/dist/rules/index.d.ts +19 -0
  227. package/dist/rules/index.js +17 -0
  228. package/dist/rules/index.js.map +1 -0
  229. package/dist/rules/normalize/alias.d.ts +50 -0
  230. package/dist/rules/normalize/alias.js +111 -0
  231. package/dist/rules/normalize/alias.js.map +1 -0
  232. package/dist/rules/normalize/cascade.d.ts +85 -0
  233. package/dist/rules/normalize/cascade.js +324 -0
  234. package/dist/rules/normalize/cascade.js.map +1 -0
  235. package/dist/rules/normalize/color.d.ts +30 -0
  236. package/dist/rules/normalize/color.js +185 -0
  237. package/dist/rules/normalize/color.js.map +1 -0
  238. package/dist/rules/normalize/fixture.d.ts +83 -0
  239. package/dist/rules/normalize/fixture.js +74 -0
  240. package/dist/rules/normalize/fixture.js.map +1 -0
  241. package/dist/rules/normalize/index.d.ts +39 -0
  242. package/dist/rules/normalize/index.js +268 -0
  243. package/dist/rules/normalize/index.js.map +1 -0
  244. package/dist/rules/normalize/project.d.ts +42 -0
  245. package/dist/rules/normalize/project.js +83 -0
  246. package/dist/rules/normalize/project.js.map +1 -0
  247. package/dist/rules/normalize/shorthand.d.ts +38 -0
  248. package/dist/rules/normalize/shorthand.js +388 -0
  249. package/dist/rules/normalize/shorthand.js.map +1 -0
  250. package/dist/rules/normalize/value.d.ts +23 -0
  251. package/dist/rules/normalize/value.js +162 -0
  252. package/dist/rules/normalize/value.js.map +1 -0
  253. package/dist/rules/normalize/wrapper.d.ts +16 -0
  254. package/dist/rules/normalize/wrapper.js +137 -0
  255. package/dist/rules/normalize/wrapper.js.map +1 -0
  256. package/dist/rules/ruleset.d.ts +93 -0
  257. package/dist/rules/ruleset.js +175 -0
  258. package/dist/rules/ruleset.js.map +1 -0
  259. package/mark.svg +30 -0
  260. package/package.json +69 -0
@@ -0,0 +1,264 @@
1
+ /**
2
+ * A generated position, mapped back to the source somebody wrote.
3
+ *
4
+ * Every build in ordinary use already ships this. A dev server emits it inline
5
+ * on each module it transforms; a production bundler writes it beside the
6
+ * bundle. It is the same argument the rest of provenance keeps making — the
7
+ * information is not missing from the build, only from the hop that would carry
8
+ * it — and it is what makes a browser stack frame usable: a frame says
9
+ * `/src/probe.jsx:23:26` about a file the browser was served, and the file the
10
+ * reviewer has to open is line 21 of the file they wrote.
11
+ *
12
+ * **Written out rather than installed.** `core` has no third-party dependencies
13
+ * (ADR-0013) and a source map is a documented format with one interesting part,
14
+ * so decoding it here costs less than the rule it would break. What is
15
+ * deliberately *not* implemented is left as a refusal rather than a wrong
16
+ * answer: an index map's sections are resolved, and a map whose version this
17
+ * does not recognise returns nothing at all.
18
+ */
19
+ /** Base64 VLQ, the one encoding a source map has that JSON does not. */
20
+ const DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
21
+ const VALUE_OF = new Int8Array(128).fill(-1);
22
+ for (let i = 0; i < DIGITS.length; i += 1)
23
+ VALUE_OF[DIGITS.charCodeAt(i)] = i;
24
+ function decodeMappings(mappings, sourceCount) {
25
+ const lines = [];
26
+ let sourceIndex = 0;
27
+ let originalLine = 0;
28
+ let originalColumn = 0;
29
+ for (const encoded of mappings.split(';')) {
30
+ const segments = [];
31
+ let generatedColumn = 0;
32
+ if (encoded !== '') {
33
+ for (const field of encoded.split(',')) {
34
+ const values = decodeVlq(field);
35
+ // A one-field segment says "generated code with no origin" — a bundler's
36
+ // own prelude, a helper it injected. It advances the column and maps
37
+ // nowhere, so recording it would let a lookup land on it and answer with
38
+ // whatever the previous segment's source was.
39
+ if (values.length < 4) {
40
+ if (values.length > 0)
41
+ generatedColumn += values[0];
42
+ continue;
43
+ }
44
+ generatedColumn += values[0];
45
+ sourceIndex += values[1];
46
+ originalLine += values[2];
47
+ originalColumn += values[3];
48
+ if (sourceIndex >= 0 && sourceIndex < sourceCount) {
49
+ segments.push({ generatedColumn, sourceIndex, originalLine, originalColumn });
50
+ }
51
+ }
52
+ }
53
+ // The format does not promise ordered columns, and the lookup is a binary
54
+ // search that assumes them. Sorting once here is cheaper than a scan per
55
+ // frame, and every map met so far was already in order.
56
+ segments.sort((a, b) => a.generatedColumn - b.generatedColumn);
57
+ lines.push(segments);
58
+ }
59
+ return lines;
60
+ }
61
+ function decodeVlq(field) {
62
+ const values = [];
63
+ let value = 0;
64
+ let shift = 0;
65
+ for (let i = 0; i < field.length; i += 1) {
66
+ const code = field.charCodeAt(i);
67
+ const digit = code < 128 ? VALUE_OF[code] : -1;
68
+ if (digit < 0)
69
+ return values; // Not a source map. Stop rather than invent.
70
+ const more = (digit & 32) !== 0;
71
+ value += (digit & 31) << shift;
72
+ if (more) {
73
+ shift += 5;
74
+ continue;
75
+ }
76
+ const negative = (value & 1) === 1;
77
+ const magnitude = value >>> 1;
78
+ values.push(negative ? (magnitude === 0 ? -0x80000000 : -magnitude) : magnitude);
79
+ value = 0;
80
+ shift = 0;
81
+ }
82
+ return values;
83
+ }
84
+ function resolveSources(raw) {
85
+ if (!Array.isArray(raw.sources))
86
+ return null;
87
+ const root = typeof raw.sourceRoot === 'string' ? raw.sourceRoot.replace(/\/+$/, '') : '';
88
+ return raw.sources.map((source) => {
89
+ if (typeof source !== 'string')
90
+ return '';
91
+ if (root === '' || source === '' || /^[a-z][a-z0-9+.-]*:/i.test(source))
92
+ return source;
93
+ return source.startsWith('/') ? `${root}${source}` : `${root}/${source}`;
94
+ });
95
+ }
96
+ /**
97
+ * Parse a source map, or decide this is not one.
98
+ *
99
+ * Returns a list because an index map is several maps at several offsets, and
100
+ * flattening them here means the lookup does not have to know which kind it was
101
+ * handed. An ordinary map is a list of one.
102
+ *
103
+ * Every refusal is silent and total. The caller is resolving a stack frame for a
104
+ * report, and a map that does not parse means one node reports no location —
105
+ * which is a state the whole provenance path already treats as normal.
106
+ */
107
+ export function parseSourceMap(text) {
108
+ let raw;
109
+ try {
110
+ raw = JSON.parse(text);
111
+ }
112
+ catch {
113
+ return [];
114
+ }
115
+ if (raw === null || typeof raw !== 'object')
116
+ return [];
117
+ if (raw.version !== undefined && raw.version !== 3)
118
+ return [];
119
+ if (Array.isArray(raw.sections)) {
120
+ return raw.sections.flatMap((section) => {
121
+ if (section === null || typeof section !== 'object')
122
+ return [];
123
+ const { offset, map } = section;
124
+ if (offset === null || typeof offset !== 'object')
125
+ return [];
126
+ if (map === null || typeof map !== 'object')
127
+ return [];
128
+ const { line, column } = offset;
129
+ if (typeof line !== 'number' || typeof column !== 'number')
130
+ return [];
131
+ return parseSourceMap(JSON.stringify(map)).map((parsed) => ({
132
+ ...parsed,
133
+ offset: { line, column },
134
+ }));
135
+ });
136
+ }
137
+ const sources = resolveSources(raw);
138
+ if (sources === null || typeof raw.mappings !== 'string')
139
+ return [];
140
+ return [
141
+ {
142
+ sources,
143
+ lines: decodeMappings(raw.mappings, sources.length),
144
+ offset: { line: 0, column: 0 },
145
+ },
146
+ ];
147
+ }
148
+ /**
149
+ * The source position a generated position came from, or nothing.
150
+ *
151
+ * `line` and `column` are 1-based on the way in and on the way out, because both
152
+ * ends of this are 1-based: a browser's stack frame counts from one, and so does
153
+ * every editor a reviewer opens the answer in. The wire format counts from zero
154
+ * and that stays inside this file.
155
+ *
156
+ * A position between two mappings resolves to the earlier one — which is the
157
+ * standard reading, and the right one: generated code that maps nowhere belongs
158
+ * to the last construct that did.
159
+ */
160
+ export function originalPositionFor(maps, line, column) {
161
+ for (const map of sectionsFor(maps, line, column)) {
162
+ // A section's own coordinates are relative to where it was placed. Only the
163
+ // first generated line of a section is column-shifted; every line after it
164
+ // starts at zero, the same way a paragraph only indents its first line.
165
+ const localLine = line - map.offset.line;
166
+ const localColumn = localLine === 1 ? column - map.offset.column : column;
167
+ const segments = map.lines[localLine - 1];
168
+ if (segments === undefined || segments.length === 0)
169
+ continue;
170
+ const found = segmentAt(segments, localColumn - 1);
171
+ if (found === undefined)
172
+ continue;
173
+ const source = map.sources[found.sourceIndex];
174
+ if (source === undefined || source === '')
175
+ continue;
176
+ return { source, line: found.originalLine + 1, column: found.originalColumn + 1 };
177
+ }
178
+ return null;
179
+ }
180
+ /**
181
+ * The sections a position could be in, innermost placement first.
182
+ *
183
+ * An ordinary map is one section at the origin and this is the identity. For an
184
+ * index map the sections partition the generated file, so the answer is the last
185
+ * one that starts at or before the position — searched in reverse for exactly
186
+ * that reason.
187
+ */
188
+ function sectionsFor(maps, line, column) {
189
+ if (maps.length <= 1)
190
+ return maps;
191
+ const candidates = maps.filter((map) => map.offset.line < line || (map.offset.line === line - 1 && map.offset.column < column));
192
+ return candidates.length === 0 ? [] : [candidates[candidates.length - 1]];
193
+ }
194
+ function segmentAt(segments, column) {
195
+ let low = 0;
196
+ let high = segments.length - 1;
197
+ let found;
198
+ while (low <= high) {
199
+ const middle = (low + high) >> 1;
200
+ const segment = segments[middle];
201
+ if (segment.generatedColumn <= column) {
202
+ found = segment;
203
+ low = middle + 1;
204
+ }
205
+ else {
206
+ high = middle - 1;
207
+ }
208
+ }
209
+ // Before the first mapping on the line. The line is still attributable — the
210
+ // first construct on it is what generated code at column 0 belongs to.
211
+ return found ?? segments[0];
212
+ }
213
+ /**
214
+ * The map a served module points at, as a URL or as the map itself.
215
+ *
216
+ * Two forms, and a build uses whichever suits it: a dev server inlines the map
217
+ * as a `data:` URI because it is transforming one module in memory, and a
218
+ * production bundler writes a sibling `.map` because inlining megabytes into
219
+ * every response is not free.
220
+ *
221
+ * Read from the end of the file. The comment is a trailing annotation by
222
+ * construction, and a bundle that merely *mentions* the token — this file does,
223
+ * a few lines up — would otherwise hand back its own prose.
224
+ */
225
+ export function sourceMappingUrlOf(code) {
226
+ const found = [...code.matchAll(/^[/*]{2,}[#@]\s*sourceMappingURL=(\S+)\s*(?:\*\/)?$/gm)];
227
+ const last = found[found.length - 1];
228
+ return last === undefined ? null : last[1];
229
+ }
230
+ /**
231
+ * The JSON of a `data:` source-map URL, when that is what it is.
232
+ *
233
+ * Base64 is what every bundler writes; the spec permits percent-encoding, and
234
+ * `decodeURIComponent` is what reads it. Both are handled because handling the
235
+ * second costs one branch.
236
+ */
237
+ export function inlineSourceMapOf(url) {
238
+ const match = /^data:application\/json[^,]*,(.*)$/s.exec(url);
239
+ if (match === null)
240
+ return null;
241
+ const payload = match[1];
242
+ if (!/;base64/i.test(url)) {
243
+ try {
244
+ return decodeURIComponent(payload);
245
+ }
246
+ catch {
247
+ return null;
248
+ }
249
+ }
250
+ try {
251
+ // `atob` in a browser, `Buffer` in Node — this package may not assume either,
252
+ // so it uses whichever the host actually has.
253
+ const decode = globalThis.atob;
254
+ if (decode !== undefined)
255
+ return decode(payload);
256
+ const buffer = globalThis
257
+ .Buffer;
258
+ return buffer === undefined ? null : buffer.from(payload, 'base64').toString('utf8');
259
+ }
260
+ catch {
261
+ return null;
262
+ }
263
+ }
264
+ //# sourceMappingURL=source-map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-map.js","sourceRoot":"","sources":["../../src/attribute/source-map.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A generated position, mapped back to the source somebody wrote.\n *\n * Every build in ordinary use already ships this. A dev server emits it inline\n * on each module it transforms; a production bundler writes it beside the\n * bundle. It is the same argument the rest of provenance keeps making — the\n * information is not missing from the build, only from the hop that would carry\n * it — and it is what makes a browser stack frame usable: a frame says\n * `/src/probe.jsx:23:26` about a file the browser was served, and the file the\n * reviewer has to open is line 21 of the file they wrote.\n *\n * **Written out rather than installed.** `core` has no third-party dependencies\n * (ADR-0013) and a source map is a documented format with one interesting part,\n * so decoding it here costs less than the rule it would break. What is\n * deliberately *not* implemented is left as a refusal rather than a wrong\n * answer: an index map's sections are resolved, and a map whose version this\n * does not recognise returns nothing at all.\n */\n\n/** Base64 VLQ, the one encoding a source map has that JSON does not. */\nconst DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\nconst VALUE_OF = new Int8Array(128).fill(-1);\nfor (let i = 0; i < DIGITS.length; i += 1) VALUE_OF[DIGITS.charCodeAt(i)] = i;\n\n/**\n * One decoded mapping: where a generated column came from.\n *\n * Column-only because the generated *line* is the index of the array this sits\n * in — that is how the `;`-separated wire format is shaped, and keeping it that\n * way is what makes the lookup a binary search rather than a scan.\n */\ninterface Segment {\n readonly generatedColumn: number;\n readonly sourceIndex: number;\n readonly originalLine: number;\n readonly originalColumn: number;\n}\n\nexport interface SourceMap {\n /** Source paths as the map states them, already resolved against `sourceRoot`. */\n readonly sources: readonly string[];\n /** Segments per generated line, `[0]` being generated line 1. */\n readonly lines: readonly (readonly Segment[])[];\n /** Non-zero only for a section of an index map. */\n readonly offset: { readonly line: number; readonly column: number };\n}\n\nexport interface OriginalPosition {\n /** The source path, exactly as the map spells it. */\n readonly source: string;\n /** 1-based, matching how a stack frame and an editor both count. */\n readonly line: number;\n /** 1-based, for the same reason. The wire format is 0-based; this is not. */\n readonly column: number;\n}\n\n/**\n * The shape a map arrives in, before anything has been checked about it.\n *\n * Deliberately loose. This is parsed from whatever a dev server served, which\n * on a bad day is an HTML error page, and every field is therefore treated as\n * absent until it proves otherwise.\n */\ninterface RawMap {\n readonly version?: unknown;\n readonly sources?: unknown;\n readonly sourceRoot?: unknown;\n readonly mappings?: unknown;\n readonly sections?: unknown;\n}\n\nfunction decodeMappings(mappings: string, sourceCount: number): Segment[][] {\n const lines: Segment[][] = [];\n\n let sourceIndex = 0;\n let originalLine = 0;\n let originalColumn = 0;\n\n for (const encoded of mappings.split(';')) {\n const segments: Segment[] = [];\n let generatedColumn = 0;\n\n if (encoded !== '') {\n for (const field of encoded.split(',')) {\n const values = decodeVlq(field);\n\n // A one-field segment says \"generated code with no origin\" — a bundler's\n // own prelude, a helper it injected. It advances the column and maps\n // nowhere, so recording it would let a lookup land on it and answer with\n // whatever the previous segment's source was.\n if (values.length < 4) {\n if (values.length > 0) generatedColumn += values[0]!;\n continue;\n }\n\n generatedColumn += values[0]!;\n sourceIndex += values[1]!;\n originalLine += values[2]!;\n originalColumn += values[3]!;\n\n if (sourceIndex >= 0 && sourceIndex < sourceCount) {\n segments.push({ generatedColumn, sourceIndex, originalLine, originalColumn });\n }\n }\n }\n\n // The format does not promise ordered columns, and the lookup is a binary\n // search that assumes them. Sorting once here is cheaper than a scan per\n // frame, and every map met so far was already in order.\n segments.sort((a, b) => a.generatedColumn - b.generatedColumn);\n lines.push(segments);\n }\n\n return lines;\n}\n\nfunction decodeVlq(field: string): number[] {\n const values: number[] = [];\n\n let value = 0;\n let shift = 0;\n\n for (let i = 0; i < field.length; i += 1) {\n const code = field.charCodeAt(i);\n const digit = code < 128 ? VALUE_OF[code]! : -1;\n if (digit < 0) return values; // Not a source map. Stop rather than invent.\n\n const more = (digit & 32) !== 0;\n value += (digit & 31) << shift;\n\n if (more) {\n shift += 5;\n continue;\n }\n\n const negative = (value & 1) === 1;\n const magnitude = value >>> 1;\n values.push(negative ? (magnitude === 0 ? -0x80000000 : -magnitude) : magnitude);\n\n value = 0;\n shift = 0;\n }\n\n return values;\n}\n\nfunction resolveSources(raw: RawMap): string[] | null {\n if (!Array.isArray(raw.sources)) return null;\n\n const root = typeof raw.sourceRoot === 'string' ? raw.sourceRoot.replace(/\\/+$/, '') : '';\n\n return raw.sources.map((source) => {\n if (typeof source !== 'string') return '';\n if (root === '' || source === '' || /^[a-z][a-z0-9+.-]*:/i.test(source)) return source;\n return source.startsWith('/') ? `${root}${source}` : `${root}/${source}`;\n });\n}\n\n/**\n * Parse a source map, or decide this is not one.\n *\n * Returns a list because an index map is several maps at several offsets, and\n * flattening them here means the lookup does not have to know which kind it was\n * handed. An ordinary map is a list of one.\n *\n * Every refusal is silent and total. The caller is resolving a stack frame for a\n * report, and a map that does not parse means one node reports no location —\n * which is a state the whole provenance path already treats as normal.\n */\nexport function parseSourceMap(text: string): SourceMap[] {\n let raw: RawMap;\n try {\n raw = JSON.parse(text) as RawMap;\n } catch {\n return [];\n }\n\n if (raw === null || typeof raw !== 'object') return [];\n if (raw.version !== undefined && raw.version !== 3) return [];\n\n if (Array.isArray(raw.sections)) {\n return raw.sections.flatMap((section) => {\n if (section === null || typeof section !== 'object') return [];\n\n const { offset, map } = section as { offset?: unknown; map?: unknown };\n if (offset === null || typeof offset !== 'object') return [];\n if (map === null || typeof map !== 'object') return [];\n\n const { line, column } = offset as { line?: unknown; column?: unknown };\n if (typeof line !== 'number' || typeof column !== 'number') return [];\n\n return parseSourceMap(JSON.stringify(map)).map((parsed) => ({\n ...parsed,\n offset: { line, column },\n }));\n });\n }\n\n const sources = resolveSources(raw);\n if (sources === null || typeof raw.mappings !== 'string') return [];\n\n return [\n {\n sources,\n lines: decodeMappings(raw.mappings, sources.length),\n offset: { line: 0, column: 0 },\n },\n ];\n}\n\n/**\n * The source position a generated position came from, or nothing.\n *\n * `line` and `column` are 1-based on the way in and on the way out, because both\n * ends of this are 1-based: a browser's stack frame counts from one, and so does\n * every editor a reviewer opens the answer in. The wire format counts from zero\n * and that stays inside this file.\n *\n * A position between two mappings resolves to the earlier one — which is the\n * standard reading, and the right one: generated code that maps nowhere belongs\n * to the last construct that did.\n */\nexport function originalPositionFor(\n maps: readonly SourceMap[],\n line: number,\n column: number,\n): OriginalPosition | null {\n for (const map of sectionsFor(maps, line, column)) {\n // A section's own coordinates are relative to where it was placed. Only the\n // first generated line of a section is column-shifted; every line after it\n // starts at zero, the same way a paragraph only indents its first line.\n const localLine = line - map.offset.line;\n const localColumn = localLine === 1 ? column - map.offset.column : column;\n\n const segments = map.lines[localLine - 1];\n if (segments === undefined || segments.length === 0) continue;\n\n const found = segmentAt(segments, localColumn - 1);\n if (found === undefined) continue;\n\n const source = map.sources[found.sourceIndex];\n if (source === undefined || source === '') continue;\n\n return { source, line: found.originalLine + 1, column: found.originalColumn + 1 };\n }\n\n return null;\n}\n\n/**\n * The sections a position could be in, innermost placement first.\n *\n * An ordinary map is one section at the origin and this is the identity. For an\n * index map the sections partition the generated file, so the answer is the last\n * one that starts at or before the position — searched in reverse for exactly\n * that reason.\n */\nfunction sectionsFor(\n maps: readonly SourceMap[],\n line: number,\n column: number,\n): readonly SourceMap[] {\n if (maps.length <= 1) return maps;\n\n const candidates = maps.filter(\n (map) =>\n map.offset.line < line || (map.offset.line === line - 1 && map.offset.column < column),\n );\n\n return candidates.length === 0 ? [] : [candidates[candidates.length - 1]!];\n}\n\nfunction segmentAt(segments: readonly Segment[], column: number): Segment | undefined {\n let low = 0;\n let high = segments.length - 1;\n let found: Segment | undefined;\n\n while (low <= high) {\n const middle = (low + high) >> 1;\n const segment = segments[middle]!;\n\n if (segment.generatedColumn <= column) {\n found = segment;\n low = middle + 1;\n } else {\n high = middle - 1;\n }\n }\n\n // Before the first mapping on the line. The line is still attributable — the\n // first construct on it is what generated code at column 0 belongs to.\n return found ?? segments[0];\n}\n\n/**\n * The map a served module points at, as a URL or as the map itself.\n *\n * Two forms, and a build uses whichever suits it: a dev server inlines the map\n * as a `data:` URI because it is transforming one module in memory, and a\n * production bundler writes a sibling `.map` because inlining megabytes into\n * every response is not free.\n *\n * Read from the end of the file. The comment is a trailing annotation by\n * construction, and a bundle that merely *mentions* the token — this file does,\n * a few lines up — would otherwise hand back its own prose.\n */\nexport function sourceMappingUrlOf(code: string): string | null {\n const found = [...code.matchAll(/^[/*]{2,}[#@]\\s*sourceMappingURL=(\\S+)\\s*(?:\\*\\/)?$/gm)];\n const last = found[found.length - 1];\n return last === undefined ? null : last[1]!;\n}\n\n/**\n * The JSON of a `data:` source-map URL, when that is what it is.\n *\n * Base64 is what every bundler writes; the spec permits percent-encoding, and\n * `decodeURIComponent` is what reads it. Both are handled because handling the\n * second costs one branch.\n */\nexport function inlineSourceMapOf(url: string): string | null {\n const match = /^data:application\\/json[^,]*,(.*)$/s.exec(url);\n if (match === null) return null;\n\n const payload = match[1]!;\n if (!/;base64/i.test(url)) {\n try {\n return decodeURIComponent(payload);\n } catch {\n return null;\n }\n }\n\n try {\n // `atob` in a browser, `Buffer` in Node — this package may not assume either,\n // so it uses whichever the host actually has.\n const decode = (globalThis as { atob?: (input: string) => string }).atob;\n if (decode !== undefined) return decode(payload);\n\n const buffer = (globalThis as { Buffer?: { from(s: string, e: string): { toString(e: string): string } } })\n .Buffer;\n return buffer === undefined ? null : buffer.from(payload, 'base64').toString('utf8');\n } catch {\n return null;\n }\n}\n"]}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Connecting a change to a file.
3
+ *
4
+ * A report that says `Button` is one step short of useful. An agent asked to fix
5
+ * it still has to find `Button`, and a reviewer still has to guess whether the
6
+ * `Button` in question is the design-system one or the local one in checkout.
7
+ * The last hop — **which file** — is what turns a finding into an edit.
8
+ *
9
+ * There are two mechanisms, and this file is the second one.
10
+ *
11
+ * The first is exact. Spec §6.1 assumes the build tells us: every JSX transform
12
+ * already computes each element's file, line and column, and
13
+ * `@variance-authority/jsx-source` is the `jsxImportSource` setting that keeps
14
+ * that location as far as the fiber — React 19 drops it otherwise, on every path.
15
+ * When it is on, a finding names the element's own line and this index is not
16
+ * consulted.
17
+ *
18
+ * The second is this one, and it is what a repository that has changed nothing
19
+ * gets. Attribution names *components*, so a **component → file** index answers
20
+ * the question attribution asks. It is built by reading source rather than by
21
+ * configuring a build, and it answers with where a component is *declared* —
22
+ * coarser than a call site, and enough to open the right file.
23
+ *
24
+ * The index is plain data. `core` performs no I/O (ADR-0006), so building one is
25
+ * a caller's job; resolving against one is here.
26
+ */
27
+ export interface SourceRef {
28
+ /** Repository-relative, so a report is portable between machines and CI. */
29
+ readonly file: string;
30
+ readonly line: number;
31
+ /** How the declaration was recognised. Carried so a bad match is debuggable. */
32
+ readonly via: 'function' | 'const' | 'class' | 'declared';
33
+ }
34
+ /**
35
+ * Component name → where it is declared.
36
+ *
37
+ * A name may map to several files. That is not an error to be resolved by
38
+ * picking one: two components genuinely can share a name, and silently choosing
39
+ * the first would send an agent to edit the wrong file with full confidence.
40
+ * Ambiguity is reported (ADR-0003's rule for overlapping projections, applied to
41
+ * source).
42
+ */
43
+ export type SourceIndex = Readonly<Record<string, readonly SourceRef[]>>;
44
+ export interface Resolution {
45
+ readonly name: string;
46
+ readonly refs: readonly SourceRef[];
47
+ /** `true` when more than one file declares this name. */
48
+ readonly ambiguous: boolean;
49
+ }
50
+ export declare function resolveSource(name: string, index: SourceIndex): Resolution | null;
51
+ /**
52
+ * `file:line`, or a disambiguating list when a name is declared more than once.
53
+ *
54
+ * Formatted as `path:line` because that is the form an editor, a terminal, and
55
+ * every agent harness already know how to open.
56
+ */
57
+ export declare function formatSource(resolution: Resolution): string;
58
+ /**
59
+ * Extract component declarations from one file's source.
60
+ *
61
+ * A regex scan, and the limits are worth stating rather than discovering. It
62
+ * finds exported and local declarations in the three shapes React components are
63
+ * written in, and it will miss a component produced by a factory, assigned
64
+ * dynamically, or re-exported under another name. It can also match a function
65
+ * that merely looks like a component — capitalised, declared at top level — and
66
+ * name a non-component in a report.
67
+ *
68
+ * Both failures are survivable in a way a wrong file path would not be: a miss
69
+ * degrades the report to the component name, which is what it said before, and a
70
+ * false positive can only appear if attribution already named that identifier.
71
+ * Parsing properly is the right answer eventually; it is not worth a parser
72
+ * dependency to find out whether the link is useful.
73
+ */
74
+ export declare function indexSource(file: string, contents: string): SourceIndex;
75
+ /** Merge per-file indexes. A name declared in several files keeps every ref. */
76
+ export declare function mergeSourceIndexes(indexes: readonly SourceIndex[]): SourceIndex;
77
+ //# sourceMappingURL=source.d.ts.map
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Connecting a change to a file.
3
+ *
4
+ * A report that says `Button` is one step short of useful. An agent asked to fix
5
+ * it still has to find `Button`, and a reviewer still has to guess whether the
6
+ * `Button` in question is the design-system one or the local one in checkout.
7
+ * The last hop — **which file** — is what turns a finding into an edit.
8
+ *
9
+ * There are two mechanisms, and this file is the second one.
10
+ *
11
+ * The first is exact. Spec §6.1 assumes the build tells us: every JSX transform
12
+ * already computes each element's file, line and column, and
13
+ * `@variance-authority/jsx-source` is the `jsxImportSource` setting that keeps
14
+ * that location as far as the fiber — React 19 drops it otherwise, on every path.
15
+ * When it is on, a finding names the element's own line and this index is not
16
+ * consulted.
17
+ *
18
+ * The second is this one, and it is what a repository that has changed nothing
19
+ * gets. Attribution names *components*, so a **component → file** index answers
20
+ * the question attribution asks. It is built by reading source rather than by
21
+ * configuring a build, and it answers with where a component is *declared* —
22
+ * coarser than a call site, and enough to open the right file.
23
+ *
24
+ * The index is plain data. `core` performs no I/O (ADR-0006), so building one is
25
+ * a caller's job; resolving against one is here.
26
+ */
27
+ export function resolveSource(name, index) {
28
+ const refs = index[name];
29
+ if (refs === undefined || refs.length === 0)
30
+ return null;
31
+ return { name, refs, ambiguous: refs.length > 1 };
32
+ }
33
+ /**
34
+ * `file:line`, or a disambiguating list when a name is declared more than once.
35
+ *
36
+ * Formatted as `path:line` because that is the form an editor, a terminal, and
37
+ * every agent harness already know how to open.
38
+ */
39
+ export function formatSource(resolution) {
40
+ const [first] = resolution.refs;
41
+ if (first === undefined)
42
+ return resolution.name;
43
+ const primary = `${first.file}:${first.line}`;
44
+ if (!resolution.ambiguous)
45
+ return primary;
46
+ const others = resolution.refs.slice(1).map((ref) => `${ref.file}:${ref.line}`);
47
+ return `${primary} (ambiguous — also ${others.join(', ')})`;
48
+ }
49
+ /**
50
+ * Extract component declarations from one file's source.
51
+ *
52
+ * A regex scan, and the limits are worth stating rather than discovering. It
53
+ * finds exported and local declarations in the three shapes React components are
54
+ * written in, and it will miss a component produced by a factory, assigned
55
+ * dynamically, or re-exported under another name. It can also match a function
56
+ * that merely looks like a component — capitalised, declared at top level — and
57
+ * name a non-component in a report.
58
+ *
59
+ * Both failures are survivable in a way a wrong file path would not be: a miss
60
+ * degrades the report to the component name, which is what it said before, and a
61
+ * false positive can only appear if attribution already named that identifier.
62
+ * Parsing properly is the right answer eventually; it is not worth a parser
63
+ * dependency to find out whether the link is useful.
64
+ */
65
+ export function indexSource(file, contents) {
66
+ const found = {};
67
+ const lines = contents.split('\n');
68
+ const patterns = [
69
+ { re: /^\s*(?:export\s+)?(?:default\s+)?function\s+([A-Z][A-Za-z0-9_]*)/, via: 'function' },
70
+ { re: /^\s*(?:export\s+)?(?:const|let)\s+([A-Z][A-Za-z0-9_]*)\s*[:=]/, via: 'const' },
71
+ { re: /^\s*(?:export\s+)?(?:default\s+)?class\s+([A-Z][A-Za-z0-9_]*)/, via: 'class' },
72
+ ];
73
+ for (const [index, line] of lines.entries()) {
74
+ for (const { re, via } of patterns) {
75
+ const match = re.exec(line);
76
+ if (!match)
77
+ continue;
78
+ const name = match[1];
79
+ (found[name] ??= []).push({ file, line: index + 1, via });
80
+ break;
81
+ }
82
+ }
83
+ return found;
84
+ }
85
+ /** Merge per-file indexes. A name declared in several files keeps every ref. */
86
+ export function mergeSourceIndexes(indexes) {
87
+ const merged = {};
88
+ for (const index of indexes) {
89
+ for (const [name, refs] of Object.entries(index)) {
90
+ (merged[name] ??= []).push(...refs);
91
+ }
92
+ }
93
+ return merged;
94
+ }
95
+ //# sourceMappingURL=source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../../src/attribute/source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AA4BH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,KAAkB;IAC5D,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IACzB,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;AACpD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,UAAsB;IACjD,MAAM,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC;IAChC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,UAAU,CAAC,IAAI,CAAC;IAEhD,MAAM,OAAO,GAAG,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;IAC9C,IAAI,CAAC,UAAU,CAAC,SAAS;QAAE,OAAO,OAAO,CAAC;IAE1C,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IAChF,OAAO,GAAG,OAAO,sBAAsB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,QAAgB;IACxD,MAAM,KAAK,GAAgC,EAAE,CAAC;IAC9C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEnC,MAAM,QAAQ,GAAuE;QACnF,EAAE,EAAE,EAAE,kEAAkE,EAAE,GAAG,EAAE,UAAU,EAAE;QAC3F,EAAE,EAAE,EAAE,+DAA+D,EAAE,GAAG,EAAE,OAAO,EAAE;QACrF,EAAE,EAAE,EAAE,+DAA+D,EAAE,GAAG,EAAE,OAAO,EAAE;KACtF,CAAC;IAEF,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5C,KAAK,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,CAAC,KAAK;gBAAE,SAAS;YAErB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;YACvB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;YAC1D,MAAM;QACR,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,kBAAkB,CAAC,OAA+B;IAChE,MAAM,MAAM,GAAgC,EAAE,CAAC;IAE/C,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACjD,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["/**\n * Connecting a change to a file.\n *\n * A report that says `Button` is one step short of useful. An agent asked to fix\n * it still has to find `Button`, and a reviewer still has to guess whether the\n * `Button` in question is the design-system one or the local one in checkout.\n * The last hop — **which file** — is what turns a finding into an edit.\n *\n * There are two mechanisms, and this file is the second one.\n *\n * The first is exact. Spec §6.1 assumes the build tells us: every JSX transform\n * already computes each element's file, line and column, and\n * `@variance-authority/jsx-source` is the `jsxImportSource` setting that keeps\n * that location as far as the fiber — React 19 drops it otherwise, on every path.\n * When it is on, a finding names the element's own line and this index is not\n * consulted.\n *\n * The second is this one, and it is what a repository that has changed nothing\n * gets. Attribution names *components*, so a **component → file** index answers\n * the question attribution asks. It is built by reading source rather than by\n * configuring a build, and it answers with where a component is *declared* —\n * coarser than a call site, and enough to open the right file.\n *\n * The index is plain data. `core` performs no I/O (ADR-0006), so building one is\n * a caller's job; resolving against one is here.\n */\n\nexport interface SourceRef {\n /** Repository-relative, so a report is portable between machines and CI. */\n readonly file: string;\n readonly line: number;\n /** How the declaration was recognised. Carried so a bad match is debuggable. */\n readonly via: 'function' | 'const' | 'class' | 'declared';\n}\n\n/**\n * Component name → where it is declared.\n *\n * A name may map to several files. That is not an error to be resolved by\n * picking one: two components genuinely can share a name, and silently choosing\n * the first would send an agent to edit the wrong file with full confidence.\n * Ambiguity is reported (ADR-0003's rule for overlapping projections, applied to\n * source).\n */\nexport type SourceIndex = Readonly<Record<string, readonly SourceRef[]>>;\n\nexport interface Resolution {\n readonly name: string;\n readonly refs: readonly SourceRef[];\n /** `true` when more than one file declares this name. */\n readonly ambiguous: boolean;\n}\n\nexport function resolveSource(name: string, index: SourceIndex): Resolution | null {\n const refs = index[name];\n if (refs === undefined || refs.length === 0) return null;\n\n return { name, refs, ambiguous: refs.length > 1 };\n}\n\n/**\n * `file:line`, or a disambiguating list when a name is declared more than once.\n *\n * Formatted as `path:line` because that is the form an editor, a terminal, and\n * every agent harness already know how to open.\n */\nexport function formatSource(resolution: Resolution): string {\n const [first] = resolution.refs;\n if (first === undefined) return resolution.name;\n\n const primary = `${first.file}:${first.line}`;\n if (!resolution.ambiguous) return primary;\n\n const others = resolution.refs.slice(1).map((ref) => `${ref.file}:${ref.line}`);\n return `${primary} (ambiguous — also ${others.join(', ')})`;\n}\n\n/**\n * Extract component declarations from one file's source.\n *\n * A regex scan, and the limits are worth stating rather than discovering. It\n * finds exported and local declarations in the three shapes React components are\n * written in, and it will miss a component produced by a factory, assigned\n * dynamically, or re-exported under another name. It can also match a function\n * that merely looks like a component — capitalised, declared at top level — and\n * name a non-component in a report.\n *\n * Both failures are survivable in a way a wrong file path would not be: a miss\n * degrades the report to the component name, which is what it said before, and a\n * false positive can only appear if attribution already named that identifier.\n * Parsing properly is the right answer eventually; it is not worth a parser\n * dependency to find out whether the link is useful.\n */\nexport function indexSource(file: string, contents: string): SourceIndex {\n const found: Record<string, SourceRef[]> = {};\n const lines = contents.split('\\n');\n\n const patterns: readonly { readonly re: RegExp; readonly via: SourceRef['via'] }[] = [\n { re: /^\\s*(?:export\\s+)?(?:default\\s+)?function\\s+([A-Z][A-Za-z0-9_]*)/, via: 'function' },\n { re: /^\\s*(?:export\\s+)?(?:const|let)\\s+([A-Z][A-Za-z0-9_]*)\\s*[:=]/, via: 'const' },\n { re: /^\\s*(?:export\\s+)?(?:default\\s+)?class\\s+([A-Z][A-Za-z0-9_]*)/, via: 'class' },\n ];\n\n for (const [index, line] of lines.entries()) {\n for (const { re, via } of patterns) {\n const match = re.exec(line);\n if (!match) continue;\n\n const name = match[1]!;\n (found[name] ??= []).push({ file, line: index + 1, via });\n break;\n }\n }\n\n return found;\n}\n\n/** Merge per-file indexes. A name declared in several files keeps every ref. */\nexport function mergeSourceIndexes(indexes: readonly SourceIndex[]): SourceIndex {\n const merged: Record<string, SourceRef[]> = {};\n\n for (const index of indexes) {\n for (const [name, refs] of Object.entries(index)) {\n (merged[name] ??= []).push(...refs);\n }\n }\n\n return merged;\n}\n"]}
@@ -0,0 +1,80 @@
1
+ import type { SourceLocation, StackFrame } from '../format/provenance.js';
2
+ import type { OriginalPosition } from './source-map.js';
3
+ /**
4
+ * Reading a call site out of a stack, and deciding which frame is the author.
5
+ *
6
+ * React 19 constructs an `Error` inside its own `jsx`/`jsxDEV` and keeps it on
7
+ * every fiber. That error is a complete answer to "which line wrote this
8
+ * element" that no build has to opt into: the runtime that captured it is frame
9
+ * zero, and whoever called it is frame one. Nothing is configured, nothing is
10
+ * installed, and the location is present in any build where React is the
11
+ * development build — which is every dev server, every Vitest run and every Jest
12
+ * run, because all three are what "not production" means.
13
+ *
14
+ * Two jobs live here and they are separable on purpose. Parsing a stack is a
15
+ * fact about a JavaScript engine. Choosing *which* frame is the author is a
16
+ * policy, and it is the part with a defensible rule rather than a heuristic:
17
+ * the author is the first frame that maps back to code the project wrote. A
18
+ * custom JSX runtime — Emotion, theme-ui — sits between React and the author and
19
+ * is skipped not because it is on a list but because it resolves into
20
+ * `node_modules`.
21
+ */
22
+ /**
23
+ * A frame is a wire value, not a local one: the page reads it, the collector
24
+ * resolves it, and it travels between them on `Provenance`. It is declared where
25
+ * the rest of provenance is declared, and re-exported here because this is the
26
+ * group that does something with it.
27
+ */
28
+ export type { StackFrame };
29
+ /**
30
+ * The frames of a stack, in order, outermost call last.
31
+ *
32
+ * The message line is dropped, and so is any line neither engine format
33
+ * recognises — a stack is diagnostic output rather than a data format, and a
34
+ * frame that cannot be read is one fewer candidate rather than a failure.
35
+ *
36
+ * `eval` frames are deliberately not unwrapped. V8 writes them as
37
+ * `at eval (eval at fn (http://host/a.js:1:1), <anonymous>:2:3)`, where two
38
+ * positions are present and the inner one is meaningless outside the eval.
39
+ * Taking the outer one would name the line that *called* `eval` as the line that
40
+ * wrote the element, which is a confident wrong answer.
41
+ */
42
+ export declare function parseStackFrames(stack: string): StackFrame[];
43
+ /**
44
+ * Whether a path belongs to a dependency rather than to the project.
45
+ *
46
+ * Three spellings of the same fact, because three build tools spell it
47
+ * differently: the directory itself, Vite's prebundled dependency cache, and the
48
+ * `webpack-internal:` scheme wrapping the same directory. The test runs against
49
+ * both the served URL — which saves fetching a map for a megabyte of vendor
50
+ * code — and against the path the map resolves to, which is what actually
51
+ * decides it.
52
+ *
53
+ * A dependency that *is* the subject cannot be attributed by this, and that is
54
+ * the intended reading: a project reviewing its own components wants the line in
55
+ * its own repository, and the line inside `react-dom` that rendered it is never
56
+ * the answer to "what changed".
57
+ */
58
+ export declare function isVendorPath(path: string): boolean;
59
+ /**
60
+ * The location that wrote this element, chosen from its stack.
61
+ *
62
+ * The rule is one sentence: **the first frame that resolves to a file the
63
+ * project wrote.** Frame zero is always React's own runtime, because React is
64
+ * what constructed the error. Frame one is the author in an ordinary build and
65
+ * is a custom JSX runtime in a build that has one — and this does not need to
66
+ * know which, because Emotion resolves into `node_modules` and the component
67
+ * does not.
68
+ *
69
+ * That is the same answer the recorded-symbol path gives, arrived at from the
70
+ * other side. Where `jsx-source` is installed it wins, because it is exact
71
+ * without a map; this is what a project that installed nothing still gets.
72
+ *
73
+ * `originalFor` is supplied rather than performed because resolving a frame
74
+ * means fetching the module the browser was served, and this package may not
75
+ * assume a network (ADR-0013). The caller owns the fetch, the cache, and the
76
+ * decision about how long to wait; this owns which frame to ask about and when
77
+ * to stop asking.
78
+ */
79
+ export declare function writerLocationOf(frames: readonly StackFrame[], originalFor: (frame: StackFrame) => OriginalPosition | null): SourceLocation | null;
80
+ //# sourceMappingURL=stack.d.ts.map