onec-interactive-runtime-core 0.1.19__py3-none-any.whl
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.
- onec_interactive_runtime_core-0.1.19.dist-info/METADATA +12 -0
- onec_interactive_runtime_core-0.1.19.dist-info/RECORD +87 -0
- onec_interactive_runtime_core-0.1.19.dist-info/WHEEL +4 -0
- onec_interactive_runtime_core-0.1.19.dist-info/licenses/COPYRIGHT +9 -0
- onec_interactive_runtime_core-0.1.19.dist-info/licenses/LICENSE +232 -0
- onec_interactive_runtime_core-0.1.19.dist-info/licenses/THIRD_PARTY_NOTICES.txt +32 -0
- onec_runtime/AGENTS.md +7 -0
- onec_runtime/__init__.py +3 -0
- onec_runtime/artifacts.py +59 -0
- onec_runtime/bootstrap.py +310 -0
- onec_runtime/breakpoint_workspace.py +249 -0
- onec_runtime/bsl/__init__.py +139 -0
- onec_runtime/bsl/diagnostics.py +1046 -0
- onec_runtime/bsl/full_ast_worker_projection.py +522 -0
- onec_runtime/bsl/generated_semantic_parser.py +6322 -0
- onec_runtime/bsl/lexer.py +164 -0
- onec_runtime/bsl/module_catalog.py +420 -0
- onec_runtime/bsl/module_delta.py +1079 -0
- onec_runtime/bsl/module_universe.py +1877 -0
- onec_runtime/bsl/notebook_cells.py +232 -0
- onec_runtime/bsl/notebook_method_globals.py +74 -0
- onec_runtime/bsl/notebook_methods.py +175 -0
- onec_runtime/bsl/parser_artifact_identity.py +119 -0
- onec_runtime/bsl/parser_target.py +388 -0
- onec_runtime/bsl/preprocessor.py +16 -0
- onec_runtime/bsl/semantic_lowering.py +1539 -0
- onec_runtime/bsl/source_maps.py +2411 -0
- onec_runtime/bsl/worker_dependency_resolver.py +289 -0
- onec_runtime/bsl/worker_preprocessor.py +247 -0
- onec_runtime/bsl/worker_projection_model.py +137 -0
- onec_runtime/bsl/worker_reload_source_map.py +1697 -0
- onec_runtime/capture.py +113 -0
- onec_runtime/capture_source.py +453 -0
- onec_runtime/compact_table.py +376 -0
- onec_runtime/compact_table_backend.py +500 -0
- onec_runtime/config.py +198 -0
- onec_runtime/configurator_agent.py +520 -0
- onec_runtime/controller_worker.py +400 -0
- onec_runtime/credentials.py +18 -0
- onec_runtime/epf_container.py +196 -0
- onec_runtime/errors.py +205 -0
- onec_runtime/experiment.py +130 -0
- onec_runtime/extension_bundle.py +944 -0
- onec_runtime/extension_lifecycle.py +402 -0
- onec_runtime/extension_state.py +222 -0
- onec_runtime/fault_injection.py +30 -0
- onec_runtime/kernel.py +179 -0
- onec_runtime/lease.py +123 -0
- onec_runtime/observation.py +287 -0
- onec_runtime/performance_profile.py +245 -0
- onec_runtime/privacy.py +263 -0
- onec_runtime/processes.py +265 -0
- onec_runtime/prototype_runtime.py +2644 -0
- onec_runtime/rdbg/__init__.py +1 -0
- onec_runtime/rdbg/models.py +130 -0
- onec_runtime/rdbg/reconnect.py +59 -0
- onec_runtime/rdbg/session.py +913 -0
- onec_runtime/rdbg/transport.py +138 -0
- onec_runtime/rdbg/xml_codec.py +980 -0
- onec_runtime/recovery.py +106 -0
- onec_runtime/recovery_journal.py +79 -0
- onec_runtime/resources/extension/OnecInteractiveRuntime.cfe +0 -0
- onec_runtime/resources/extension/extension-manifest.json +108 -0
- onec_runtime/runtime_api.py +5272 -0
- onec_runtime/runtime_contracts.py +196 -0
- onec_runtime/server_worker.py +2034 -0
- onec_runtime/session.py +2123 -0
- onec_runtime/startup_diagnostics.py +45 -0
- onec_runtime/stop_routing.py +65 -0
- onec_runtime/supervised_processes.py +232 -0
- onec_runtime/supervised_runtime.py +512 -0
- onec_runtime/supervisor.py +363 -0
- onec_runtime/supervisor_model.py +148 -0
- onec_runtime/supervisor_protocol.py +77 -0
- onec_runtime/table_materialization.py +471 -0
- onec_runtime/table_transfer_backend.py +203 -0
- onec_runtime/table_value.py +311 -0
- onec_runtime/toolchain.py +730 -0
- onec_runtime/value_materialization.py +432 -0
- onec_runtime/value_transfer_backend.py +199 -0
- onec_runtime/worker_breakpoints.py +1431 -0
- onec_runtime/worker_epf.py +313 -0
- onec_runtime/worker_epf_template.py +53 -0
- onec_runtime/worker_stage_protocol.py +516 -0
- onec_runtime/worker_universe.py +3772 -0
- onec_runtime_build/__init__.py +1 -0
- onec_runtime_build/parser_target_development.py +116 -0
|
@@ -0,0 +1,1697 @@
|
|
|
1
|
+
"""Single-pass Worker reload insertion materialization and source mapping."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from bisect import bisect_right
|
|
6
|
+
from dataclasses import dataclass, field, replace
|
|
7
|
+
from enum import Enum
|
|
8
|
+
from hashlib import sha256
|
|
9
|
+
from hmac import compare_digest
|
|
10
|
+
import json
|
|
11
|
+
from typing import Callable, Iterable
|
|
12
|
+
|
|
13
|
+
from onec_runtime.bsl.source_maps import (
|
|
14
|
+
MappedOffset,
|
|
15
|
+
MappedSource,
|
|
16
|
+
MappingRelation,
|
|
17
|
+
SourceArtifactKind,
|
|
18
|
+
SourceArtifactRef,
|
|
19
|
+
SourceMap,
|
|
20
|
+
SourceMapSegment,
|
|
21
|
+
SourceSpan,
|
|
22
|
+
SourceUnitRef,
|
|
23
|
+
_NORMALIZED_WORKER_AUTHORITY,
|
|
24
|
+
_source_map_structural_proof,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
WORKER_LINE_ENDING_REGION = "worker_module_line_ending"
|
|
29
|
+
_WORK_OBSERVER: Callable[[str, int], None] | None = None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _observe_work(event: str, amount: int = 1) -> None:
|
|
33
|
+
if _WORK_OBSERVER is not None:
|
|
34
|
+
_WORK_OBSERVER(event, amount)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class _InsertionRelation(Enum):
|
|
38
|
+
DERIVED = "derived"
|
|
39
|
+
SYNTHETIC = "synthetic"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass(frozen=True, slots=True)
|
|
43
|
+
class ReloadInsertion:
|
|
44
|
+
source_offset: int
|
|
45
|
+
generated_length: int
|
|
46
|
+
method_name: str | None
|
|
47
|
+
synthetic_region: str
|
|
48
|
+
_text: str = field(repr=False)
|
|
49
|
+
_relation: _InsertionRelation = field(repr=False)
|
|
50
|
+
_origin: SourceSpan | None = field(repr=False)
|
|
51
|
+
_anchor: SourceSpan = field(repr=False)
|
|
52
|
+
|
|
53
|
+
def __post_init__(self) -> None:
|
|
54
|
+
if type(self.source_offset) is not int or self.source_offset < 0:
|
|
55
|
+
raise ValueError("insertion source offset must be non-negative")
|
|
56
|
+
if (
|
|
57
|
+
type(self.generated_length) is not int
|
|
58
|
+
or self.generated_length != len(self._text)
|
|
59
|
+
or not self._text
|
|
60
|
+
):
|
|
61
|
+
raise ValueError("insertion generated length is invalid")
|
|
62
|
+
if self.method_name is not None and (
|
|
63
|
+
type(self.method_name) is not str or not self.method_name
|
|
64
|
+
):
|
|
65
|
+
raise ValueError("insertion method name is invalid")
|
|
66
|
+
if type(self.synthetic_region) is not str or not self.synthetic_region:
|
|
67
|
+
raise ValueError("insertion synthetic region is invalid")
|
|
68
|
+
if not isinstance(self._relation, _InsertionRelation):
|
|
69
|
+
raise ValueError("insertion relation is invalid")
|
|
70
|
+
if not isinstance(self._anchor, SourceSpan):
|
|
71
|
+
raise ValueError("insertion anchor is invalid")
|
|
72
|
+
if self._relation is _InsertionRelation.DERIVED:
|
|
73
|
+
if not isinstance(self._origin, SourceSpan):
|
|
74
|
+
raise ValueError("derived insertion origin is invalid")
|
|
75
|
+
elif self._origin is not None:
|
|
76
|
+
raise ValueError("synthetic insertion cannot claim an origin")
|
|
77
|
+
if "\r" in self._text or "\x00" in self._text:
|
|
78
|
+
raise ValueError("insertion payload is not normalized")
|
|
79
|
+
|
|
80
|
+
@classmethod
|
|
81
|
+
def derived(
|
|
82
|
+
cls,
|
|
83
|
+
*,
|
|
84
|
+
source_offset: int,
|
|
85
|
+
text: str,
|
|
86
|
+
method_name: str | None,
|
|
87
|
+
synthetic_region: str,
|
|
88
|
+
origin: SourceSpan,
|
|
89
|
+
anchor: SourceSpan,
|
|
90
|
+
) -> "ReloadInsertion":
|
|
91
|
+
return cls(
|
|
92
|
+
source_offset,
|
|
93
|
+
len(text),
|
|
94
|
+
method_name,
|
|
95
|
+
synthetic_region,
|
|
96
|
+
text,
|
|
97
|
+
_InsertionRelation.DERIVED,
|
|
98
|
+
origin,
|
|
99
|
+
anchor,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
@classmethod
|
|
103
|
+
def synthetic(
|
|
104
|
+
cls,
|
|
105
|
+
*,
|
|
106
|
+
source_offset: int,
|
|
107
|
+
text: str,
|
|
108
|
+
method_name: str | None,
|
|
109
|
+
synthetic_region: str,
|
|
110
|
+
anchor: SourceSpan,
|
|
111
|
+
) -> "ReloadInsertion":
|
|
112
|
+
return cls(
|
|
113
|
+
source_offset,
|
|
114
|
+
len(text),
|
|
115
|
+
method_name,
|
|
116
|
+
synthetic_region,
|
|
117
|
+
text,
|
|
118
|
+
_InsertionRelation.SYNTHETIC,
|
|
119
|
+
None,
|
|
120
|
+
anchor,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@dataclass(frozen=True, slots=True)
|
|
125
|
+
class ReloadMapCheckpoint:
|
|
126
|
+
source_offset: int
|
|
127
|
+
generated_offset: int
|
|
128
|
+
inserted_length: int
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@dataclass(frozen=True, slots=True)
|
|
132
|
+
class ReloadMethodBoundary:
|
|
133
|
+
method_name: str
|
|
134
|
+
declaration_start: int
|
|
135
|
+
body_start: int
|
|
136
|
+
method_end: int
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@dataclass(frozen=True, slots=True)
|
|
140
|
+
class ReloadMethodCheckpoint:
|
|
141
|
+
method_name: str
|
|
142
|
+
declaration_source_offset: int
|
|
143
|
+
declaration_generated_offset: int
|
|
144
|
+
body_source_offset: int
|
|
145
|
+
body_generated_offset: int
|
|
146
|
+
end_source_offset: int
|
|
147
|
+
end_generated_offset: int
|
|
148
|
+
|
|
149
|
+
@property
|
|
150
|
+
def declaration_shift(self) -> int:
|
|
151
|
+
return self.declaration_generated_offset - self.declaration_source_offset
|
|
152
|
+
|
|
153
|
+
@property
|
|
154
|
+
def body_shift(self) -> int:
|
|
155
|
+
return self.body_generated_offset - self.body_source_offset
|
|
156
|
+
|
|
157
|
+
@property
|
|
158
|
+
def end_shift(self) -> int:
|
|
159
|
+
return self.end_generated_offset - self.end_source_offset
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
@dataclass(frozen=True, slots=True)
|
|
163
|
+
class _CompactInsertionInterval:
|
|
164
|
+
generated: SourceSpan
|
|
165
|
+
source_offset: int
|
|
166
|
+
method_name: str | None
|
|
167
|
+
relation: MappingRelation
|
|
168
|
+
synthetic_region: str
|
|
169
|
+
origin_ref: SourceUnitRef | None
|
|
170
|
+
origin: SourceSpan | None
|
|
171
|
+
anchor_ref: SourceUnitRef | None
|
|
172
|
+
anchor_span: SourceSpan | None
|
|
173
|
+
source_origin: SourceSpan | None
|
|
174
|
+
source_anchor: SourceSpan
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
@dataclass(frozen=True, slots=True)
|
|
178
|
+
class _CompactReloadBasis:
|
|
179
|
+
parent_artifact: SourceArtifactRef
|
|
180
|
+
parent_source_map: SourceMap
|
|
181
|
+
source_length: int
|
|
182
|
+
intervals: tuple[_CompactInsertionInterval, ...]
|
|
183
|
+
interval_starts: tuple[int, ...]
|
|
184
|
+
checkpoints: tuple[ReloadMapCheckpoint, ...]
|
|
185
|
+
checkpoint_offsets: tuple[int, ...]
|
|
186
|
+
inserted_after: tuple[int, ...]
|
|
187
|
+
line_ending_starts: tuple[int, ...]
|
|
188
|
+
line_ending_widths: bytes
|
|
189
|
+
crlf_lf_offsets: tuple[int, ...]
|
|
190
|
+
method_checkpoints: tuple[ReloadMethodCheckpoint, ...]
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
class CompactReloadSourceMap(SourceMap):
|
|
194
|
+
"""Immutable reload map whose unchanged source ranges remain implicit."""
|
|
195
|
+
|
|
196
|
+
__slots__ = (
|
|
197
|
+
"_compact_generated",
|
|
198
|
+
"_compact_basis",
|
|
199
|
+
"_compact_flattened",
|
|
200
|
+
"_canonical_manifest_bytes",
|
|
201
|
+
"_canonical_sha256",
|
|
202
|
+
"_structural_proof",
|
|
203
|
+
)
|
|
204
|
+
_compact_reload_map = True
|
|
205
|
+
|
|
206
|
+
def __init__(
|
|
207
|
+
self,
|
|
208
|
+
generated: SourceArtifactRef,
|
|
209
|
+
basis: _CompactReloadBasis,
|
|
210
|
+
*,
|
|
211
|
+
flattened: bool,
|
|
212
|
+
) -> None:
|
|
213
|
+
if not isinstance(basis, _CompactReloadBasis) or type(flattened) is not bool:
|
|
214
|
+
raise ValueError("compact reload map basis is invalid")
|
|
215
|
+
_validate_compact_basis(basis, generated)
|
|
216
|
+
object.__setattr__(self, "_compact_generated", generated)
|
|
217
|
+
object.__setattr__(self, "_compact_basis", basis)
|
|
218
|
+
object.__setattr__(self, "_compact_flattened", flattened)
|
|
219
|
+
payload = json.dumps(
|
|
220
|
+
self.to_compact_manifest(),
|
|
221
|
+
ensure_ascii=False,
|
|
222
|
+
sort_keys=True,
|
|
223
|
+
separators=(",", ":"),
|
|
224
|
+
).encode("utf-8")
|
|
225
|
+
object.__setattr__(self, "_canonical_manifest_bytes", payload)
|
|
226
|
+
object.__setattr__(self, "_canonical_sha256", sha256(payload).hexdigest())
|
|
227
|
+
object.__setattr__(
|
|
228
|
+
self,
|
|
229
|
+
"_structural_proof",
|
|
230
|
+
sha256(b"onec-compact-reload-map-v1\x00" + payload).digest(),
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
def __setattr__(self, name: str, value: object) -> None:
|
|
234
|
+
raise AttributeError("CompactReloadSourceMap is immutable")
|
|
235
|
+
|
|
236
|
+
def __delattr__(self, name: str) -> None:
|
|
237
|
+
raise AttributeError("CompactReloadSourceMap is immutable")
|
|
238
|
+
|
|
239
|
+
@property
|
|
240
|
+
def generated(self) -> SourceArtifactRef:
|
|
241
|
+
return self._compact_generated
|
|
242
|
+
|
|
243
|
+
@property
|
|
244
|
+
def segments(self) -> tuple[SourceMapSegment, ...]:
|
|
245
|
+
"""Materialize the legacy representation only for an explicit consumer."""
|
|
246
|
+
return self.materialize_generic().segments
|
|
247
|
+
|
|
248
|
+
@property
|
|
249
|
+
def checkpoints(self) -> tuple[ReloadMapCheckpoint, ...]:
|
|
250
|
+
return self._compact_basis.checkpoints
|
|
251
|
+
|
|
252
|
+
@property
|
|
253
|
+
def compact_interval_count(self) -> int:
|
|
254
|
+
return len(self._compact_basis.intervals)
|
|
255
|
+
|
|
256
|
+
@property
|
|
257
|
+
def method_checkpoints(self) -> tuple[ReloadMethodCheckpoint, ...]:
|
|
258
|
+
return self._compact_basis.method_checkpoints
|
|
259
|
+
|
|
260
|
+
@property
|
|
261
|
+
def source_map_sha256(self) -> str:
|
|
262
|
+
return self._canonical_sha256
|
|
263
|
+
|
|
264
|
+
@property
|
|
265
|
+
def generic_materialized(self) -> bool:
|
|
266
|
+
return False
|
|
267
|
+
|
|
268
|
+
def map_offset(self, offset: int) -> MappedOffset:
|
|
269
|
+
if not self._compact_flattened:
|
|
270
|
+
return self.materialize_generic().map_offset(offset)
|
|
271
|
+
if type(offset) is not int or not 0 <= offset <= self.generated.character_length:
|
|
272
|
+
raise ValueError("offset must be within the generated source")
|
|
273
|
+
interval = self._interval_at(offset)
|
|
274
|
+
if interval is not None:
|
|
275
|
+
return _mapped_compact_interval(interval)
|
|
276
|
+
if offset == self.generated.character_length:
|
|
277
|
+
if offset:
|
|
278
|
+
previous_interval = self._interval_at(offset - 1)
|
|
279
|
+
if previous_interval is not None:
|
|
280
|
+
return _mapped_compact_interval(previous_interval)
|
|
281
|
+
original = self._original_offset_at_generated(offset - 1)
|
|
282
|
+
ending_width = self._line_ending_width(original)
|
|
283
|
+
if ending_width is not None:
|
|
284
|
+
projected = _ParentProjector(
|
|
285
|
+
self._compact_basis.parent_source_map
|
|
286
|
+
).derived(
|
|
287
|
+
SourceSpan(original, original + ending_width),
|
|
288
|
+
SourceSpan(0, 1),
|
|
289
|
+
WORKER_LINE_ENDING_REGION,
|
|
290
|
+
)
|
|
291
|
+
return _mapped_compact_segment(projected)
|
|
292
|
+
return self._compact_basis.parent_source_map.map_offset(
|
|
293
|
+
self._compact_basis.source_length
|
|
294
|
+
)
|
|
295
|
+
original = self._original_offset_at_generated(offset)
|
|
296
|
+
ending_width = self._line_ending_width(original)
|
|
297
|
+
if ending_width is not None:
|
|
298
|
+
projected = _ParentProjector(
|
|
299
|
+
self._compact_basis.parent_source_map
|
|
300
|
+
).derived(
|
|
301
|
+
SourceSpan(original, original + ending_width),
|
|
302
|
+
SourceSpan(0, 1),
|
|
303
|
+
WORKER_LINE_ENDING_REGION,
|
|
304
|
+
)
|
|
305
|
+
return _mapped_compact_segment(projected)
|
|
306
|
+
return self._compact_basis.parent_source_map.map_offset(original)
|
|
307
|
+
|
|
308
|
+
def map_original_offset(self, offset: int) -> int:
|
|
309
|
+
basis = self._compact_basis
|
|
310
|
+
if type(offset) is not int or not 0 <= offset <= basis.source_length:
|
|
311
|
+
raise ValueError("offset must be within the original source")
|
|
312
|
+
checkpoint_index = bisect_right(basis.checkpoint_offsets, offset) - 1
|
|
313
|
+
inserted = (
|
|
314
|
+
0
|
|
315
|
+
if checkpoint_index < 0
|
|
316
|
+
else basis.inserted_after[checkpoint_index]
|
|
317
|
+
)
|
|
318
|
+
removed_crlf = bisect_right(basis.crlf_lf_offsets, offset - 1)
|
|
319
|
+
return offset - removed_crlf + inserted
|
|
320
|
+
|
|
321
|
+
def materialize_generic(self) -> SourceMap:
|
|
322
|
+
return _materialize_compact_generic(self)
|
|
323
|
+
|
|
324
|
+
def to_manifest(self) -> dict[str, object]:
|
|
325
|
+
return self.to_compact_manifest()
|
|
326
|
+
|
|
327
|
+
def to_compact_manifest(self) -> dict[str, object]:
|
|
328
|
+
basis = self._compact_basis
|
|
329
|
+
unit_values = {
|
|
330
|
+
unit
|
|
331
|
+
for interval in basis.intervals
|
|
332
|
+
for unit in (interval.origin_ref, interval.anchor_ref)
|
|
333
|
+
if unit is not None
|
|
334
|
+
}
|
|
335
|
+
for _role, unit, _span in self.compact_visible_spans():
|
|
336
|
+
unit_values.add(unit)
|
|
337
|
+
units = tuple(
|
|
338
|
+
sorted(
|
|
339
|
+
unit_values,
|
|
340
|
+
key=lambda item: (
|
|
341
|
+
item.kind.value,
|
|
342
|
+
item.unit_id,
|
|
343
|
+
item.revision,
|
|
344
|
+
item.source_sha256,
|
|
345
|
+
),
|
|
346
|
+
)
|
|
347
|
+
)
|
|
348
|
+
unit_indices = {unit: index for index, unit in enumerate(units)}
|
|
349
|
+
methods = tuple(
|
|
350
|
+
sorted(
|
|
351
|
+
{
|
|
352
|
+
item.method_name
|
|
353
|
+
for item in basis.intervals
|
|
354
|
+
if item.method_name is not None
|
|
355
|
+
},
|
|
356
|
+
key=str.casefold,
|
|
357
|
+
)
|
|
358
|
+
)
|
|
359
|
+
method_names = tuple(
|
|
360
|
+
sorted(
|
|
361
|
+
{item.method_name for item in basis.method_checkpoints} | set(methods),
|
|
362
|
+
key=str.casefold,
|
|
363
|
+
)
|
|
364
|
+
)
|
|
365
|
+
method_indices = {name: index for index, name in enumerate(method_names)}
|
|
366
|
+
regions = tuple(
|
|
367
|
+
sorted({item.synthetic_region for item in basis.intervals})
|
|
368
|
+
)
|
|
369
|
+
region_indices = {name: index for index, name in enumerate(regions)}
|
|
370
|
+
return {
|
|
371
|
+
"schema": "onec-compact-worker-reload-map-v1",
|
|
372
|
+
"flattened": self._compact_flattened,
|
|
373
|
+
"generated": _artifact_manifest(self.generated),
|
|
374
|
+
"parent_artifact": _artifact_manifest(basis.parent_artifact),
|
|
375
|
+
"parent_map_sha256": basis.parent_source_map.source_map_sha256,
|
|
376
|
+
"source_length": basis.source_length,
|
|
377
|
+
"units": [
|
|
378
|
+
[unit.kind.value, unit.unit_id, unit.revision, unit.source_sha256]
|
|
379
|
+
for unit in units
|
|
380
|
+
],
|
|
381
|
+
"methods": list(method_names),
|
|
382
|
+
"regions": list(regions),
|
|
383
|
+
"line_endings": _encoded_line_endings(
|
|
384
|
+
basis.line_ending_starts,
|
|
385
|
+
basis.line_ending_widths,
|
|
386
|
+
),
|
|
387
|
+
"checkpoints": [
|
|
388
|
+
[item.source_offset, item.generated_offset, item.inserted_length]
|
|
389
|
+
for item in basis.checkpoints
|
|
390
|
+
],
|
|
391
|
+
"intervals": [
|
|
392
|
+
[
|
|
393
|
+
item.generated.start,
|
|
394
|
+
item.generated.end,
|
|
395
|
+
item.source_offset,
|
|
396
|
+
(
|
|
397
|
+
None
|
|
398
|
+
if item.method_name is None
|
|
399
|
+
else method_indices[item.method_name]
|
|
400
|
+
),
|
|
401
|
+
item.relation.value,
|
|
402
|
+
region_indices[item.synthetic_region],
|
|
403
|
+
*_indexed_span(item.origin_ref, item.origin, unit_indices),
|
|
404
|
+
*_indexed_span(item.anchor_ref, item.anchor_span, unit_indices),
|
|
405
|
+
*_plain_span(item.source_origin),
|
|
406
|
+
*_plain_span(item.source_anchor),
|
|
407
|
+
]
|
|
408
|
+
for item in basis.intervals
|
|
409
|
+
],
|
|
410
|
+
"method_checkpoints": [
|
|
411
|
+
[
|
|
412
|
+
method_indices[item.method_name],
|
|
413
|
+
item.declaration_source_offset,
|
|
414
|
+
item.declaration_generated_offset,
|
|
415
|
+
item.body_source_offset,
|
|
416
|
+
item.body_generated_offset,
|
|
417
|
+
item.end_source_offset,
|
|
418
|
+
item.end_generated_offset,
|
|
419
|
+
]
|
|
420
|
+
for item in basis.method_checkpoints
|
|
421
|
+
],
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
def compact_visible_spans(
|
|
425
|
+
self,
|
|
426
|
+
) -> tuple[tuple[str, SourceUnitRef, SourceSpan], ...]:
|
|
427
|
+
records: list[tuple[str, SourceUnitRef, SourceSpan]] = []
|
|
428
|
+
for segment in self._compact_basis.parent_source_map.segments:
|
|
429
|
+
for role, reference, span in (
|
|
430
|
+
("origin", segment.origin_ref, segment.origin),
|
|
431
|
+
("anchor", segment.anchor_ref, segment.anchor_span),
|
|
432
|
+
):
|
|
433
|
+
if isinstance(reference, SourceUnitRef) and span is not None:
|
|
434
|
+
records.append((role, reference, span))
|
|
435
|
+
for interval in self._compact_basis.intervals:
|
|
436
|
+
for role, reference, span in (
|
|
437
|
+
("origin", interval.origin_ref, interval.origin),
|
|
438
|
+
("anchor", interval.anchor_ref, interval.anchor_span),
|
|
439
|
+
):
|
|
440
|
+
if reference is not None and span is not None:
|
|
441
|
+
records.append((role, reference, span))
|
|
442
|
+
return tuple(records)
|
|
443
|
+
|
|
444
|
+
def mapped_spans_for_visible_span(
|
|
445
|
+
self,
|
|
446
|
+
reference: SourceUnitRef,
|
|
447
|
+
requested: SourceSpan,
|
|
448
|
+
) -> tuple[tuple[MappingRelation, SourceSpan], ...]:
|
|
449
|
+
"""Return only generated ranges relevant to one visible source interval."""
|
|
450
|
+
if not isinstance(reference, SourceUnitRef) or not isinstance(
|
|
451
|
+
requested, SourceSpan
|
|
452
|
+
):
|
|
453
|
+
raise TypeError("visible source reference and span are required")
|
|
454
|
+
if not self._compact_flattened:
|
|
455
|
+
raise ValueError("visible span lookup requires a flattened reload map")
|
|
456
|
+
|
|
457
|
+
records: list[tuple[MappingRelation, SourceSpan]] = []
|
|
458
|
+
exact_offsets: set[int] = set()
|
|
459
|
+
for segment in self._compact_basis.parent_source_map.segments:
|
|
460
|
+
if (
|
|
461
|
+
segment.relation is not MappingRelation.EXACT
|
|
462
|
+
or segment.origin_ref != reference
|
|
463
|
+
or segment.origin is None
|
|
464
|
+
):
|
|
465
|
+
continue
|
|
466
|
+
start = max(segment.origin.start, requested.start)
|
|
467
|
+
end = min(segment.origin.end, requested.end)
|
|
468
|
+
if start >= end:
|
|
469
|
+
continue
|
|
470
|
+
for origin_offset in range(start, end):
|
|
471
|
+
parent_offset = (
|
|
472
|
+
segment.generated.start + origin_offset - segment.origin.start
|
|
473
|
+
)
|
|
474
|
+
exact_offsets.add(self.map_original_offset(parent_offset))
|
|
475
|
+
|
|
476
|
+
for generated_offset in sorted(exact_offsets):
|
|
477
|
+
mapped = self.map_offset(generated_offset)
|
|
478
|
+
if (
|
|
479
|
+
mapped.relation is MappingRelation.EXACT
|
|
480
|
+
and mapped.unit == reference
|
|
481
|
+
and mapped.origin_span is not None
|
|
482
|
+
and mapped.origin_span.start < requested.end
|
|
483
|
+
and requested.start < mapped.origin_span.end
|
|
484
|
+
):
|
|
485
|
+
records.append(
|
|
486
|
+
(
|
|
487
|
+
MappingRelation.EXACT,
|
|
488
|
+
SourceSpan(generated_offset, generated_offset + 1),
|
|
489
|
+
)
|
|
490
|
+
)
|
|
491
|
+
|
|
492
|
+
for interval in self._compact_basis.intervals:
|
|
493
|
+
visible_span = (
|
|
494
|
+
interval.origin
|
|
495
|
+
if interval.origin_ref == reference
|
|
496
|
+
else interval.anchor_span
|
|
497
|
+
if interval.anchor_ref == reference
|
|
498
|
+
else None
|
|
499
|
+
)
|
|
500
|
+
if (
|
|
501
|
+
visible_span is not None
|
|
502
|
+
and visible_span.start < requested.end
|
|
503
|
+
and requested.start < visible_span.end
|
|
504
|
+
):
|
|
505
|
+
records.append((interval.relation, interval.generated))
|
|
506
|
+
return tuple(records)
|
|
507
|
+
|
|
508
|
+
def compact_guard(self) -> tuple[int, ...]:
|
|
509
|
+
basis = self._compact_basis
|
|
510
|
+
return (
|
|
511
|
+
id(self),
|
|
512
|
+
id(basis),
|
|
513
|
+
id(basis.intervals),
|
|
514
|
+
id(basis.interval_starts),
|
|
515
|
+
id(basis.checkpoints),
|
|
516
|
+
id(basis.checkpoint_offsets),
|
|
517
|
+
id(basis.inserted_after),
|
|
518
|
+
id(basis.line_ending_starts),
|
|
519
|
+
id(basis.line_ending_widths),
|
|
520
|
+
id(basis.crlf_lf_offsets),
|
|
521
|
+
id(basis.method_checkpoints),
|
|
522
|
+
id(self._canonical_manifest_bytes),
|
|
523
|
+
id(basis.parent_artifact),
|
|
524
|
+
id(basis.parent_source_map),
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
def _validated_compact_structural_proof(self) -> bytes:
|
|
528
|
+
basis = self._compact_basis
|
|
529
|
+
_validate_compact_basis(basis, self.generated)
|
|
530
|
+
actual_parent_proof = _source_map_structural_proof(
|
|
531
|
+
basis.parent_source_map,
|
|
532
|
+
observe=True,
|
|
533
|
+
)
|
|
534
|
+
if not compare_digest(
|
|
535
|
+
basis.parent_source_map._structural_proof,
|
|
536
|
+
actual_parent_proof,
|
|
537
|
+
):
|
|
538
|
+
raise ValueError("compact reload parent map is invalid")
|
|
539
|
+
payload = json.dumps(
|
|
540
|
+
self.to_compact_manifest(),
|
|
541
|
+
ensure_ascii=False,
|
|
542
|
+
sort_keys=True,
|
|
543
|
+
separators=(",", ":"),
|
|
544
|
+
).encode("utf-8")
|
|
545
|
+
proof = sha256(b"onec-compact-reload-map-v1\x00" + payload).digest()
|
|
546
|
+
return proof
|
|
547
|
+
|
|
548
|
+
def _interval_at(self, offset: int) -> _CompactInsertionInterval | None:
|
|
549
|
+
basis = self._compact_basis
|
|
550
|
+
if not basis.intervals:
|
|
551
|
+
return None
|
|
552
|
+
index = bisect_right(basis.interval_starts, offset) - 1
|
|
553
|
+
if index < 0:
|
|
554
|
+
return None
|
|
555
|
+
interval = basis.intervals[index]
|
|
556
|
+
if interval.generated.start <= offset < interval.generated.end:
|
|
557
|
+
return interval
|
|
558
|
+
if offset == self.generated.character_length and interval.generated.end == offset:
|
|
559
|
+
return interval
|
|
560
|
+
return None
|
|
561
|
+
|
|
562
|
+
def _original_offset_at_generated(self, generated: int) -> int:
|
|
563
|
+
low = 0
|
|
564
|
+
high = self._compact_basis.source_length
|
|
565
|
+
while low < high:
|
|
566
|
+
middle = (low + high + 1) // 2
|
|
567
|
+
if self.map_original_offset(middle) <= generated:
|
|
568
|
+
low = middle
|
|
569
|
+
else:
|
|
570
|
+
high = middle - 1
|
|
571
|
+
return low
|
|
572
|
+
|
|
573
|
+
def _line_ending_width(self, source_offset: int) -> int | None:
|
|
574
|
+
basis = self._compact_basis
|
|
575
|
+
index = bisect_right(basis.line_ending_starts, source_offset) - 1
|
|
576
|
+
if index < 0 or basis.line_ending_starts[index] != source_offset:
|
|
577
|
+
return None
|
|
578
|
+
return basis.line_ending_widths[index]
|
|
579
|
+
|
|
580
|
+
def __eq__(self, other: object) -> bool:
|
|
581
|
+
return (
|
|
582
|
+
isinstance(other, CompactReloadSourceMap)
|
|
583
|
+
and self._canonical_manifest_bytes == other._canonical_manifest_bytes
|
|
584
|
+
)
|
|
585
|
+
|
|
586
|
+
def __hash__(self) -> int:
|
|
587
|
+
return hash(self._canonical_sha256)
|
|
588
|
+
|
|
589
|
+
def __repr__(self) -> str:
|
|
590
|
+
return (
|
|
591
|
+
"CompactReloadSourceMap(artifact="
|
|
592
|
+
f"{self.generated.kind.value}:{self.generated.source_sha256}, "
|
|
593
|
+
f"intervals={len(self._compact_basis.intervals)})"
|
|
594
|
+
)
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
class CompactMappedWorkerSource(MappedSource):
|
|
598
|
+
"""Mapped Worker source backed by a compact reload map."""
|
|
599
|
+
|
|
600
|
+
__slots__ = ()
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
def snapshot_compact_mapped_worker_source(
|
|
604
|
+
source: CompactMappedWorkerSource,
|
|
605
|
+
) -> CompactMappedWorkerSource:
|
|
606
|
+
"""Detach the compact map graph without materializing generic segments."""
|
|
607
|
+
|
|
608
|
+
if not isinstance(source, CompactMappedWorkerSource) or not isinstance(
|
|
609
|
+
source.source_map,
|
|
610
|
+
CompactReloadSourceMap,
|
|
611
|
+
):
|
|
612
|
+
raise ValueError("compact Worker source is invalid")
|
|
613
|
+
current = source.source_map
|
|
614
|
+
basis = current._compact_basis
|
|
615
|
+
map_cache: dict[int, SourceMap] = {}
|
|
616
|
+
parent_map = _clone_source_map(basis.parent_source_map, map_cache)
|
|
617
|
+
generated = replace(source.artifact)
|
|
618
|
+
intervals = tuple(
|
|
619
|
+
replace(
|
|
620
|
+
interval,
|
|
621
|
+
generated=replace(interval.generated),
|
|
622
|
+
origin_ref=(
|
|
623
|
+
None if interval.origin_ref is None else replace(interval.origin_ref)
|
|
624
|
+
),
|
|
625
|
+
origin=None if interval.origin is None else replace(interval.origin),
|
|
626
|
+
anchor_ref=(
|
|
627
|
+
None if interval.anchor_ref is None else replace(interval.anchor_ref)
|
|
628
|
+
),
|
|
629
|
+
anchor_span=(
|
|
630
|
+
None if interval.anchor_span is None else replace(interval.anchor_span)
|
|
631
|
+
),
|
|
632
|
+
source_origin=(
|
|
633
|
+
None
|
|
634
|
+
if interval.source_origin is None
|
|
635
|
+
else replace(interval.source_origin)
|
|
636
|
+
),
|
|
637
|
+
source_anchor=replace(interval.source_anchor),
|
|
638
|
+
)
|
|
639
|
+
for interval in basis.intervals
|
|
640
|
+
)
|
|
641
|
+
cloned_basis = _compact_basis(
|
|
642
|
+
replace(basis.parent_artifact),
|
|
643
|
+
parent_map,
|
|
644
|
+
basis.source_length,
|
|
645
|
+
intervals,
|
|
646
|
+
tuple(replace(item) for item in basis.checkpoints),
|
|
647
|
+
basis.line_ending_starts,
|
|
648
|
+
basis.line_ending_widths,
|
|
649
|
+
tuple(replace(item) for item in basis.method_checkpoints),
|
|
650
|
+
)
|
|
651
|
+
flattened = CompactReloadSourceMap(
|
|
652
|
+
generated,
|
|
653
|
+
cloned_basis,
|
|
654
|
+
flattened=True,
|
|
655
|
+
)
|
|
656
|
+
local = CompactReloadSourceMap(
|
|
657
|
+
generated,
|
|
658
|
+
cloned_basis,
|
|
659
|
+
flattened=False,
|
|
660
|
+
)
|
|
661
|
+
lineage_prefix = tuple(
|
|
662
|
+
_clone_source_map(item, map_cache)
|
|
663
|
+
for item in source.lineage[:-1]
|
|
664
|
+
)
|
|
665
|
+
return CompactMappedWorkerSource(
|
|
666
|
+
source.text,
|
|
667
|
+
generated,
|
|
668
|
+
flattened,
|
|
669
|
+
(*lineage_prefix, local),
|
|
670
|
+
local,
|
|
671
|
+
_normalized_worker_authority=_NORMALIZED_WORKER_AUTHORITY,
|
|
672
|
+
)
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
def _clone_source_map(
|
|
676
|
+
source_map: SourceMap,
|
|
677
|
+
cache: dict[int, SourceMap],
|
|
678
|
+
) -> SourceMap:
|
|
679
|
+
existing = cache.get(id(source_map))
|
|
680
|
+
if existing is not None:
|
|
681
|
+
return existing
|
|
682
|
+
cloned = SourceMap(
|
|
683
|
+
replace(source_map.generated),
|
|
684
|
+
tuple(
|
|
685
|
+
replace(
|
|
686
|
+
segment,
|
|
687
|
+
generated=replace(segment.generated),
|
|
688
|
+
origin_ref=(
|
|
689
|
+
None if segment.origin_ref is None else replace(segment.origin_ref)
|
|
690
|
+
),
|
|
691
|
+
origin=None if segment.origin is None else replace(segment.origin),
|
|
692
|
+
anchor_ref=(
|
|
693
|
+
None if segment.anchor_ref is None else replace(segment.anchor_ref)
|
|
694
|
+
),
|
|
695
|
+
anchor_span=(
|
|
696
|
+
None if segment.anchor_span is None else replace(segment.anchor_span)
|
|
697
|
+
),
|
|
698
|
+
)
|
|
699
|
+
for segment in source_map.segments
|
|
700
|
+
),
|
|
701
|
+
)
|
|
702
|
+
cache[id(source_map)] = cloned
|
|
703
|
+
return cloned
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
class _ParentProjector:
|
|
707
|
+
def __init__(self, source_map: SourceMap) -> None:
|
|
708
|
+
self._segments = tuple(
|
|
709
|
+
segment
|
|
710
|
+
for segment in source_map.segments
|
|
711
|
+
if segment.generated.start < segment.generated.end
|
|
712
|
+
)
|
|
713
|
+
self._starts = tuple(segment.generated.start for segment in self._segments)
|
|
714
|
+
self._cursor = 0
|
|
715
|
+
|
|
716
|
+
def exact(self, span: SourceSpan, generated_start: int) -> list[SourceMapSegment]:
|
|
717
|
+
overlapping = self._overlapping_monotonic(span)
|
|
718
|
+
result: list[SourceMapSegment] = []
|
|
719
|
+
for parent in overlapping:
|
|
720
|
+
start = max(parent.generated.start, span.start)
|
|
721
|
+
end = min(parent.generated.end, span.end)
|
|
722
|
+
generated = SourceSpan(
|
|
723
|
+
generated_start + start - span.start,
|
|
724
|
+
generated_start + end - span.start,
|
|
725
|
+
)
|
|
726
|
+
result.append(
|
|
727
|
+
_project_exact_piece(parent, SourceSpan(start, end), generated)
|
|
728
|
+
)
|
|
729
|
+
if not result:
|
|
730
|
+
raise ValueError("source fragment has no visible mapping")
|
|
731
|
+
return result
|
|
732
|
+
|
|
733
|
+
def derived(
|
|
734
|
+
self,
|
|
735
|
+
span: SourceSpan,
|
|
736
|
+
generated: SourceSpan,
|
|
737
|
+
region: str,
|
|
738
|
+
) -> SourceMapSegment:
|
|
739
|
+
overlapping = self._overlapping_monotonic(span)
|
|
740
|
+
synthetic = next(
|
|
741
|
+
(
|
|
742
|
+
segment
|
|
743
|
+
for segment in overlapping
|
|
744
|
+
if segment.relation is MappingRelation.SYNTHETIC
|
|
745
|
+
),
|
|
746
|
+
None,
|
|
747
|
+
)
|
|
748
|
+
if synthetic is not None:
|
|
749
|
+
return SourceMapSegment(
|
|
750
|
+
generated,
|
|
751
|
+
None,
|
|
752
|
+
None,
|
|
753
|
+
MappingRelation.SYNTHETIC,
|
|
754
|
+
synthetic.synthetic_region,
|
|
755
|
+
synthetic.anchor_ref,
|
|
756
|
+
synthetic.anchor_span,
|
|
757
|
+
)
|
|
758
|
+
unit, origin = _anchor_from_segments(overlapping, span)
|
|
759
|
+
if unit is None or origin is None:
|
|
760
|
+
raise ValueError("derived source fragment crosses visible source units")
|
|
761
|
+
return SourceMapSegment(
|
|
762
|
+
generated,
|
|
763
|
+
unit,
|
|
764
|
+
origin,
|
|
765
|
+
MappingRelation.DERIVED,
|
|
766
|
+
region,
|
|
767
|
+
)
|
|
768
|
+
|
|
769
|
+
def anchor(
|
|
770
|
+
self,
|
|
771
|
+
span: SourceSpan,
|
|
772
|
+
) -> tuple[SourceUnitRef | None, SourceSpan | None]:
|
|
773
|
+
if span.start == span.end:
|
|
774
|
+
if not self._segments:
|
|
775
|
+
return None, None
|
|
776
|
+
index = bisect_right(self._starts, span.start) - 1
|
|
777
|
+
if index < 0:
|
|
778
|
+
index = 0
|
|
779
|
+
if index >= len(self._segments):
|
|
780
|
+
index = len(self._segments) - 1
|
|
781
|
+
segment = self._segments[index]
|
|
782
|
+
_observe_work("parent_segment_visit")
|
|
783
|
+
if segment.relation is MappingRelation.SYNTHETIC:
|
|
784
|
+
return (
|
|
785
|
+
segment.anchor_ref
|
|
786
|
+
if isinstance(segment.anchor_ref, SourceUnitRef)
|
|
787
|
+
else None,
|
|
788
|
+
segment.anchor_span,
|
|
789
|
+
)
|
|
790
|
+
if (
|
|
791
|
+
not isinstance(segment.origin_ref, SourceUnitRef)
|
|
792
|
+
or segment.origin is None
|
|
793
|
+
):
|
|
794
|
+
return None, None
|
|
795
|
+
point = (
|
|
796
|
+
segment.origin.start
|
|
797
|
+
+ span.start
|
|
798
|
+
- segment.generated.start
|
|
799
|
+
if segment.relation is MappingRelation.EXACT
|
|
800
|
+
else segment.origin.start
|
|
801
|
+
)
|
|
802
|
+
return segment.origin_ref, SourceSpan(point, point)
|
|
803
|
+
index = max(0, bisect_right(self._starts, span.start) - 1)
|
|
804
|
+
overlapping: list[SourceMapSegment] = []
|
|
805
|
+
while index < len(self._segments):
|
|
806
|
+
segment = self._segments[index]
|
|
807
|
+
_observe_work("parent_segment_visit")
|
|
808
|
+
if segment.generated.start >= span.end:
|
|
809
|
+
break
|
|
810
|
+
if span.start < segment.generated.end:
|
|
811
|
+
overlapping.append(segment)
|
|
812
|
+
index += 1
|
|
813
|
+
return _anchor_from_segments(tuple(overlapping), span)
|
|
814
|
+
|
|
815
|
+
def _overlapping_monotonic(
|
|
816
|
+
self,
|
|
817
|
+
span: SourceSpan,
|
|
818
|
+
) -> tuple[SourceMapSegment, ...]:
|
|
819
|
+
while (
|
|
820
|
+
self._cursor < len(self._segments)
|
|
821
|
+
and self._segments[self._cursor].generated.end <= span.start
|
|
822
|
+
):
|
|
823
|
+
_observe_work("parent_segment_visit")
|
|
824
|
+
self._cursor += 1
|
|
825
|
+
result: list[SourceMapSegment] = []
|
|
826
|
+
scan = self._cursor
|
|
827
|
+
while scan < len(self._segments):
|
|
828
|
+
parent = self._segments[scan]
|
|
829
|
+
_observe_work("parent_segment_visit")
|
|
830
|
+
if parent.generated.start >= span.end:
|
|
831
|
+
break
|
|
832
|
+
if span.start < parent.generated.end:
|
|
833
|
+
result.append(parent)
|
|
834
|
+
scan += 1
|
|
835
|
+
if not result and span.start < span.end:
|
|
836
|
+
raise ValueError("source fragment has no visible mapping")
|
|
837
|
+
return tuple(result)
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
def materialize_worker_reload_source(
|
|
841
|
+
source: MappedSource,
|
|
842
|
+
insertions: Iterable[ReloadInsertion],
|
|
843
|
+
*,
|
|
844
|
+
method_boundaries: Iterable[ReloadMethodBoundary] = (),
|
|
845
|
+
) -> CompactMappedWorkerSource:
|
|
846
|
+
"""Apply reload insertions without expanding unchanged source into segments."""
|
|
847
|
+
|
|
848
|
+
ordered = _validated_reload_insertions(source, insertions)
|
|
849
|
+
boundaries = _validated_method_boundaries(
|
|
850
|
+
source.artifact.character_length,
|
|
851
|
+
method_boundaries,
|
|
852
|
+
)
|
|
853
|
+
line_ending_starts, line_ending_widths = _line_ending_index(source.text)
|
|
854
|
+
fragments: list[str] = []
|
|
855
|
+
intervals: list[_CompactInsertionInterval] = []
|
|
856
|
+
checkpoints: list[ReloadMapCheckpoint] = []
|
|
857
|
+
projector = _ParentProjector(source.source_map)
|
|
858
|
+
generated_cursor = 0
|
|
859
|
+
source_cursor = 0
|
|
860
|
+
index = 0
|
|
861
|
+
while index < len(ordered):
|
|
862
|
+
insertion = ordered[index]
|
|
863
|
+
offset = insertion.source_offset
|
|
864
|
+
if source_cursor < offset:
|
|
865
|
+
normalized = _normalize_reload_fragment(source.text[source_cursor:offset])
|
|
866
|
+
fragments.append(normalized)
|
|
867
|
+
generated_cursor += len(normalized)
|
|
868
|
+
group_start = generated_cursor
|
|
869
|
+
inserted_length = 0
|
|
870
|
+
while index < len(ordered) and ordered[index].source_offset == offset:
|
|
871
|
+
insertion = ordered[index]
|
|
872
|
+
generated = SourceSpan(
|
|
873
|
+
generated_cursor,
|
|
874
|
+
generated_cursor + insertion.generated_length,
|
|
875
|
+
)
|
|
876
|
+
fragments.append(insertion._text)
|
|
877
|
+
if insertion._relation is _InsertionRelation.DERIVED:
|
|
878
|
+
assert insertion._origin is not None
|
|
879
|
+
origin_ref, origin = projector.anchor(insertion._origin)
|
|
880
|
+
if origin_ref is None or origin is None:
|
|
881
|
+
raise ValueError("derived insertion has no visible origin")
|
|
882
|
+
relation = MappingRelation.DERIVED
|
|
883
|
+
else:
|
|
884
|
+
origin_ref = None
|
|
885
|
+
origin = None
|
|
886
|
+
relation = MappingRelation.SYNTHETIC
|
|
887
|
+
anchor_ref, anchor = projector.anchor(insertion._anchor)
|
|
888
|
+
intervals.append(
|
|
889
|
+
_CompactInsertionInterval(
|
|
890
|
+
generated,
|
|
891
|
+
offset,
|
|
892
|
+
insertion.method_name,
|
|
893
|
+
relation,
|
|
894
|
+
insertion.synthetic_region,
|
|
895
|
+
origin_ref,
|
|
896
|
+
origin,
|
|
897
|
+
anchor_ref,
|
|
898
|
+
anchor,
|
|
899
|
+
insertion._origin,
|
|
900
|
+
insertion._anchor,
|
|
901
|
+
)
|
|
902
|
+
)
|
|
903
|
+
generated_cursor = generated.end
|
|
904
|
+
inserted_length += insertion.generated_length
|
|
905
|
+
index += 1
|
|
906
|
+
checkpoints.append(
|
|
907
|
+
ReloadMapCheckpoint(offset, group_start, inserted_length)
|
|
908
|
+
)
|
|
909
|
+
source_cursor = offset
|
|
910
|
+
if source_cursor < len(source.text):
|
|
911
|
+
normalized = _normalize_reload_fragment(source.text[source_cursor:])
|
|
912
|
+
fragments.append(normalized)
|
|
913
|
+
generated_cursor += len(normalized)
|
|
914
|
+
|
|
915
|
+
text = "".join(fragments)
|
|
916
|
+
if not text.strip():
|
|
917
|
+
raise ValueError("Worker source is empty")
|
|
918
|
+
digest = sha256(text.encode("utf-8")).hexdigest()
|
|
919
|
+
artifact = SourceArtifactRef(
|
|
920
|
+
SourceArtifactKind.WORKER_MODULE,
|
|
921
|
+
digest,
|
|
922
|
+
len(text),
|
|
923
|
+
"lf" if "\n" in text else "none",
|
|
924
|
+
)
|
|
925
|
+
checkpoint_tuple = tuple(checkpoints)
|
|
926
|
+
interval_tuple = tuple(intervals)
|
|
927
|
+
basis = _compact_basis(
|
|
928
|
+
source.artifact,
|
|
929
|
+
source.source_map,
|
|
930
|
+
len(source.text),
|
|
931
|
+
interval_tuple,
|
|
932
|
+
checkpoint_tuple,
|
|
933
|
+
line_ending_starts,
|
|
934
|
+
line_ending_widths,
|
|
935
|
+
_reload_method_checkpoints(
|
|
936
|
+
boundaries,
|
|
937
|
+
checkpoint_tuple,
|
|
938
|
+
line_ending_starts,
|
|
939
|
+
line_ending_widths,
|
|
940
|
+
),
|
|
941
|
+
)
|
|
942
|
+
flattened = CompactReloadSourceMap(
|
|
943
|
+
artifact,
|
|
944
|
+
basis,
|
|
945
|
+
flattened=True,
|
|
946
|
+
)
|
|
947
|
+
local = CompactReloadSourceMap(
|
|
948
|
+
artifact,
|
|
949
|
+
basis,
|
|
950
|
+
flattened=False,
|
|
951
|
+
)
|
|
952
|
+
return CompactMappedWorkerSource(
|
|
953
|
+
text,
|
|
954
|
+
artifact,
|
|
955
|
+
flattened,
|
|
956
|
+
(*source.lineage, local),
|
|
957
|
+
local,
|
|
958
|
+
_normalized_worker_authority=_NORMALIZED_WORKER_AUTHORITY,
|
|
959
|
+
)
|
|
960
|
+
|
|
961
|
+
|
|
962
|
+
def materialize_worker_reload_source_oracle(
|
|
963
|
+
source: MappedSource,
|
|
964
|
+
insertions: Iterable[ReloadInsertion],
|
|
965
|
+
) -> MappedSource:
|
|
966
|
+
"""Apply insertions and newline normalization directly to a WORKER_MODULE."""
|
|
967
|
+
|
|
968
|
+
ordered = _validated_reload_insertions(source, insertions)
|
|
969
|
+
|
|
970
|
+
fragments: list[str] = []
|
|
971
|
+
local_segments: list[SourceMapSegment] = []
|
|
972
|
+
flattened_segments: list[SourceMapSegment] = []
|
|
973
|
+
projector = _ParentProjector(source.source_map)
|
|
974
|
+
anchor_cache: dict[SourceSpan, tuple[SourceUnitRef | None, SourceSpan | None]] = {}
|
|
975
|
+
generated_cursor = 0
|
|
976
|
+
|
|
977
|
+
def mapped_anchor(
|
|
978
|
+
span: SourceSpan,
|
|
979
|
+
) -> tuple[SourceUnitRef | None, SourceSpan | None]:
|
|
980
|
+
mapped = anchor_cache.get(span)
|
|
981
|
+
if mapped is None:
|
|
982
|
+
mapped = projector.anchor(span)
|
|
983
|
+
anchor_cache[span] = mapped
|
|
984
|
+
return mapped
|
|
985
|
+
|
|
986
|
+
def append_original(span: SourceSpan) -> None:
|
|
987
|
+
nonlocal generated_cursor
|
|
988
|
+
cursor = span.start
|
|
989
|
+
while cursor < span.end:
|
|
990
|
+
carriage = source.text.find("\r", cursor, span.end)
|
|
991
|
+
exact_end = span.end if carriage < 0 else carriage
|
|
992
|
+
if cursor < exact_end:
|
|
993
|
+
text = source.text[cursor:exact_end]
|
|
994
|
+
generated = SourceSpan(generated_cursor, generated_cursor + len(text))
|
|
995
|
+
fragments.append(text)
|
|
996
|
+
local_segments.append(
|
|
997
|
+
SourceMapSegment(
|
|
998
|
+
generated,
|
|
999
|
+
source.artifact,
|
|
1000
|
+
SourceSpan(cursor, exact_end),
|
|
1001
|
+
MappingRelation.EXACT,
|
|
1002
|
+
)
|
|
1003
|
+
)
|
|
1004
|
+
flattened_segments.extend(
|
|
1005
|
+
projector.exact(SourceSpan(cursor, exact_end), generated_cursor)
|
|
1006
|
+
)
|
|
1007
|
+
generated_cursor += len(text)
|
|
1008
|
+
if carriage < 0:
|
|
1009
|
+
break
|
|
1010
|
+
ending = (
|
|
1011
|
+
carriage + 2
|
|
1012
|
+
if carriage + 1 < span.end and source.text[carriage + 1] == "\n"
|
|
1013
|
+
else carriage + 1
|
|
1014
|
+
)
|
|
1015
|
+
generated = SourceSpan(generated_cursor, generated_cursor + 1)
|
|
1016
|
+
origin = SourceSpan(carriage, ending)
|
|
1017
|
+
fragments.append("\n")
|
|
1018
|
+
local_segments.append(
|
|
1019
|
+
SourceMapSegment(
|
|
1020
|
+
generated,
|
|
1021
|
+
source.artifact,
|
|
1022
|
+
origin,
|
|
1023
|
+
MappingRelation.DERIVED,
|
|
1024
|
+
WORKER_LINE_ENDING_REGION,
|
|
1025
|
+
)
|
|
1026
|
+
)
|
|
1027
|
+
flattened_segments.append(
|
|
1028
|
+
projector.derived(
|
|
1029
|
+
origin,
|
|
1030
|
+
generated,
|
|
1031
|
+
WORKER_LINE_ENDING_REGION,
|
|
1032
|
+
)
|
|
1033
|
+
)
|
|
1034
|
+
generated_cursor += 1
|
|
1035
|
+
cursor = ending
|
|
1036
|
+
|
|
1037
|
+
def append_insertion(insertion: ReloadInsertion) -> None:
|
|
1038
|
+
nonlocal generated_cursor
|
|
1039
|
+
generated = SourceSpan(
|
|
1040
|
+
generated_cursor,
|
|
1041
|
+
generated_cursor + insertion.generated_length,
|
|
1042
|
+
)
|
|
1043
|
+
fragments.append(insertion._text)
|
|
1044
|
+
anchor_unit, anchor_span = mapped_anchor(insertion._anchor)
|
|
1045
|
+
if insertion._relation is _InsertionRelation.SYNTHETIC:
|
|
1046
|
+
local_segments.append(
|
|
1047
|
+
SourceMapSegment(
|
|
1048
|
+
generated,
|
|
1049
|
+
None,
|
|
1050
|
+
None,
|
|
1051
|
+
MappingRelation.SYNTHETIC,
|
|
1052
|
+
insertion.synthetic_region,
|
|
1053
|
+
source.artifact,
|
|
1054
|
+
insertion._anchor,
|
|
1055
|
+
)
|
|
1056
|
+
)
|
|
1057
|
+
flattened_segments.append(
|
|
1058
|
+
SourceMapSegment(
|
|
1059
|
+
generated,
|
|
1060
|
+
None,
|
|
1061
|
+
None,
|
|
1062
|
+
MappingRelation.SYNTHETIC,
|
|
1063
|
+
insertion.synthetic_region,
|
|
1064
|
+
anchor_unit,
|
|
1065
|
+
anchor_span,
|
|
1066
|
+
)
|
|
1067
|
+
)
|
|
1068
|
+
else:
|
|
1069
|
+
assert insertion._origin is not None
|
|
1070
|
+
origin_unit, origin_span = mapped_anchor(insertion._origin)
|
|
1071
|
+
if origin_unit is None or origin_span is None:
|
|
1072
|
+
raise ValueError("derived insertion has no visible origin")
|
|
1073
|
+
local_segments.append(
|
|
1074
|
+
SourceMapSegment(
|
|
1075
|
+
generated,
|
|
1076
|
+
source.artifact,
|
|
1077
|
+
insertion._origin,
|
|
1078
|
+
MappingRelation.DERIVED,
|
|
1079
|
+
insertion.synthetic_region,
|
|
1080
|
+
source.artifact,
|
|
1081
|
+
insertion._anchor,
|
|
1082
|
+
)
|
|
1083
|
+
)
|
|
1084
|
+
flattened_segments.append(
|
|
1085
|
+
SourceMapSegment(
|
|
1086
|
+
generated,
|
|
1087
|
+
origin_unit,
|
|
1088
|
+
origin_span,
|
|
1089
|
+
MappingRelation.DERIVED,
|
|
1090
|
+
insertion.synthetic_region,
|
|
1091
|
+
anchor_unit,
|
|
1092
|
+
anchor_span,
|
|
1093
|
+
)
|
|
1094
|
+
)
|
|
1095
|
+
generated_cursor = generated.end
|
|
1096
|
+
|
|
1097
|
+
source_cursor = 0
|
|
1098
|
+
for insertion in ordered:
|
|
1099
|
+
if source_cursor < insertion.source_offset:
|
|
1100
|
+
append_original(SourceSpan(source_cursor, insertion.source_offset))
|
|
1101
|
+
append_insertion(insertion)
|
|
1102
|
+
source_cursor = insertion.source_offset
|
|
1103
|
+
if source_cursor < len(source.text):
|
|
1104
|
+
append_original(SourceSpan(source_cursor, len(source.text)))
|
|
1105
|
+
|
|
1106
|
+
text = "".join(fragments)
|
|
1107
|
+
if not text.strip():
|
|
1108
|
+
raise ValueError("Worker source is empty")
|
|
1109
|
+
digest = sha256(text.encode("utf-8")).hexdigest()
|
|
1110
|
+
artifact = SourceArtifactRef(
|
|
1111
|
+
SourceArtifactKind.WORKER_MODULE,
|
|
1112
|
+
digest,
|
|
1113
|
+
len(text),
|
|
1114
|
+
"lf" if "\n" in text else "none",
|
|
1115
|
+
)
|
|
1116
|
+
local = SourceMap(artifact, tuple(local_segments))
|
|
1117
|
+
flattened = SourceMap(artifact, tuple(flattened_segments))
|
|
1118
|
+
return MappedSource(
|
|
1119
|
+
text,
|
|
1120
|
+
artifact,
|
|
1121
|
+
flattened,
|
|
1122
|
+
(*source.lineage, local),
|
|
1123
|
+
local,
|
|
1124
|
+
_normalized_worker_authority=_NORMALIZED_WORKER_AUTHORITY,
|
|
1125
|
+
)
|
|
1126
|
+
|
|
1127
|
+
|
|
1128
|
+
def _validated_reload_insertions(
|
|
1129
|
+
source: MappedSource,
|
|
1130
|
+
insertions: Iterable[ReloadInsertion],
|
|
1131
|
+
) -> tuple[ReloadInsertion, ...]:
|
|
1132
|
+
if not isinstance(source, MappedSource):
|
|
1133
|
+
raise ValueError("Worker reload source must be a MappedSource")
|
|
1134
|
+
try:
|
|
1135
|
+
supplied = tuple(insertions)
|
|
1136
|
+
except TypeError as error:
|
|
1137
|
+
raise ValueError("Worker reload insertions are invalid") from error
|
|
1138
|
+
if any(not isinstance(item, ReloadInsertion) for item in supplied):
|
|
1139
|
+
raise ValueError("Worker reload insertions are invalid")
|
|
1140
|
+
ordered = tuple(
|
|
1141
|
+
item
|
|
1142
|
+
for _, item in sorted(
|
|
1143
|
+
enumerate(supplied),
|
|
1144
|
+
key=lambda pair: (pair[1].source_offset, pair[0]),
|
|
1145
|
+
)
|
|
1146
|
+
)
|
|
1147
|
+
if any(item.source_offset > len(source.text) for item in ordered):
|
|
1148
|
+
raise ValueError("Worker reload insertion is outside source")
|
|
1149
|
+
if any(
|
|
1150
|
+
item.source_offset > 0
|
|
1151
|
+
and item.source_offset < len(source.text)
|
|
1152
|
+
and source.text[item.source_offset - 1 : item.source_offset + 1] == "\r\n"
|
|
1153
|
+
for item in ordered
|
|
1154
|
+
):
|
|
1155
|
+
raise ValueError("Worker reload insertion splits a CRLF sequence")
|
|
1156
|
+
if "\x00" in source.text:
|
|
1157
|
+
raise ValueError("Worker source contains a NUL character")
|
|
1158
|
+
return ordered
|
|
1159
|
+
|
|
1160
|
+
|
|
1161
|
+
def _normalize_reload_fragment(text: str) -> str:
|
|
1162
|
+
return text.replace("\r\n", "\n").replace("\r", "\n")
|
|
1163
|
+
|
|
1164
|
+
|
|
1165
|
+
def _validated_method_boundaries(
|
|
1166
|
+
source_length: int,
|
|
1167
|
+
boundaries: Iterable[ReloadMethodBoundary],
|
|
1168
|
+
) -> tuple[ReloadMethodBoundary, ...]:
|
|
1169
|
+
try:
|
|
1170
|
+
supplied = tuple(boundaries)
|
|
1171
|
+
except TypeError as error:
|
|
1172
|
+
raise ValueError("Worker reload method boundaries are invalid") from error
|
|
1173
|
+
if any(not isinstance(item, ReloadMethodBoundary) for item in supplied):
|
|
1174
|
+
raise ValueError("Worker reload method boundaries are invalid")
|
|
1175
|
+
ordered = tuple(
|
|
1176
|
+
sorted(supplied, key=lambda item: (item.declaration_start, item.method_name.casefold()))
|
|
1177
|
+
)
|
|
1178
|
+
names: set[str] = set()
|
|
1179
|
+
previous_end = 0
|
|
1180
|
+
for item in ordered:
|
|
1181
|
+
normalized = item.method_name.casefold()
|
|
1182
|
+
if (
|
|
1183
|
+
not item.method_name
|
|
1184
|
+
or normalized in names
|
|
1185
|
+
or not (
|
|
1186
|
+
0 <= item.declaration_start <= item.body_start <= item.method_end <= source_length
|
|
1187
|
+
)
|
|
1188
|
+
or item.declaration_start < previous_end
|
|
1189
|
+
):
|
|
1190
|
+
raise ValueError("Worker reload method boundaries are invalid")
|
|
1191
|
+
names.add(normalized)
|
|
1192
|
+
previous_end = item.method_end
|
|
1193
|
+
return ordered
|
|
1194
|
+
|
|
1195
|
+
|
|
1196
|
+
def _line_ending_index(source: str) -> tuple[tuple[int, ...], bytes]:
|
|
1197
|
+
starts: list[int] = []
|
|
1198
|
+
widths = bytearray()
|
|
1199
|
+
scan = 0
|
|
1200
|
+
while True:
|
|
1201
|
+
carriage = source.find("\r", scan)
|
|
1202
|
+
if carriage < 0:
|
|
1203
|
+
break
|
|
1204
|
+
width = 2 if source.startswith("\r\n", carriage) else 1
|
|
1205
|
+
starts.append(carriage)
|
|
1206
|
+
widths.append(width)
|
|
1207
|
+
scan = carriage + width
|
|
1208
|
+
return tuple(starts), bytes(widths)
|
|
1209
|
+
|
|
1210
|
+
|
|
1211
|
+
def _compact_basis(
|
|
1212
|
+
parent_artifact: SourceArtifactRef,
|
|
1213
|
+
parent_source_map: SourceMap,
|
|
1214
|
+
source_length: int,
|
|
1215
|
+
intervals: tuple[_CompactInsertionInterval, ...],
|
|
1216
|
+
checkpoints: tuple[ReloadMapCheckpoint, ...],
|
|
1217
|
+
line_ending_starts: tuple[int, ...],
|
|
1218
|
+
line_ending_widths: bytes,
|
|
1219
|
+
method_checkpoints: tuple[ReloadMethodCheckpoint, ...],
|
|
1220
|
+
) -> _CompactReloadBasis:
|
|
1221
|
+
cumulative = 0
|
|
1222
|
+
inserted_after: list[int] = []
|
|
1223
|
+
for item in checkpoints:
|
|
1224
|
+
cumulative += item.inserted_length
|
|
1225
|
+
inserted_after.append(cumulative)
|
|
1226
|
+
inserted_after_tuple = tuple(inserted_after)
|
|
1227
|
+
return _CompactReloadBasis(
|
|
1228
|
+
parent_artifact,
|
|
1229
|
+
parent_source_map,
|
|
1230
|
+
source_length,
|
|
1231
|
+
intervals,
|
|
1232
|
+
tuple(item.generated.start for item in intervals),
|
|
1233
|
+
checkpoints,
|
|
1234
|
+
tuple(item.source_offset for item in checkpoints),
|
|
1235
|
+
inserted_after_tuple,
|
|
1236
|
+
line_ending_starts,
|
|
1237
|
+
line_ending_widths,
|
|
1238
|
+
tuple(
|
|
1239
|
+
start + 1
|
|
1240
|
+
for start, width in zip(
|
|
1241
|
+
line_ending_starts,
|
|
1242
|
+
line_ending_widths,
|
|
1243
|
+
strict=True,
|
|
1244
|
+
)
|
|
1245
|
+
if width == 2
|
|
1246
|
+
),
|
|
1247
|
+
method_checkpoints,
|
|
1248
|
+
)
|
|
1249
|
+
|
|
1250
|
+
|
|
1251
|
+
def _reload_method_checkpoints(
|
|
1252
|
+
boundaries: tuple[ReloadMethodBoundary, ...],
|
|
1253
|
+
checkpoints: tuple[ReloadMapCheckpoint, ...],
|
|
1254
|
+
line_ending_starts: tuple[int, ...],
|
|
1255
|
+
line_ending_widths: bytes,
|
|
1256
|
+
) -> tuple[ReloadMethodCheckpoint, ...]:
|
|
1257
|
+
checkpoint_offsets = tuple(item.source_offset for item in checkpoints)
|
|
1258
|
+
cumulative = 0
|
|
1259
|
+
inserted_after: list[int] = []
|
|
1260
|
+
for item in checkpoints:
|
|
1261
|
+
cumulative += item.inserted_length
|
|
1262
|
+
inserted_after.append(cumulative)
|
|
1263
|
+
inserted_after_tuple = tuple(inserted_after)
|
|
1264
|
+
crlf_lf_offsets = tuple(
|
|
1265
|
+
start + 1
|
|
1266
|
+
for start, width in zip(
|
|
1267
|
+
line_ending_starts,
|
|
1268
|
+
line_ending_widths,
|
|
1269
|
+
strict=True,
|
|
1270
|
+
)
|
|
1271
|
+
if width == 2
|
|
1272
|
+
)
|
|
1273
|
+
return tuple(
|
|
1274
|
+
ReloadMethodCheckpoint(
|
|
1275
|
+
item.method_name,
|
|
1276
|
+
item.declaration_start,
|
|
1277
|
+
_original_to_generated(
|
|
1278
|
+
item.declaration_start,
|
|
1279
|
+
checkpoint_offsets,
|
|
1280
|
+
inserted_after_tuple,
|
|
1281
|
+
crlf_lf_offsets,
|
|
1282
|
+
),
|
|
1283
|
+
item.body_start,
|
|
1284
|
+
_original_to_generated(
|
|
1285
|
+
item.body_start,
|
|
1286
|
+
checkpoint_offsets,
|
|
1287
|
+
inserted_after_tuple,
|
|
1288
|
+
crlf_lf_offsets,
|
|
1289
|
+
),
|
|
1290
|
+
item.method_end,
|
|
1291
|
+
_original_to_generated(
|
|
1292
|
+
item.method_end,
|
|
1293
|
+
checkpoint_offsets,
|
|
1294
|
+
inserted_after_tuple,
|
|
1295
|
+
crlf_lf_offsets,
|
|
1296
|
+
),
|
|
1297
|
+
)
|
|
1298
|
+
for item in boundaries
|
|
1299
|
+
)
|
|
1300
|
+
|
|
1301
|
+
|
|
1302
|
+
def _original_to_generated(
|
|
1303
|
+
source_offset: int,
|
|
1304
|
+
checkpoint_offsets: tuple[int, ...],
|
|
1305
|
+
inserted_after: tuple[int, ...],
|
|
1306
|
+
crlf_lf_offsets: tuple[int, ...],
|
|
1307
|
+
) -> int:
|
|
1308
|
+
checkpoint_index = bisect_right(checkpoint_offsets, source_offset) - 1
|
|
1309
|
+
inserted = 0 if checkpoint_index < 0 else inserted_after[checkpoint_index]
|
|
1310
|
+
removed = bisect_right(crlf_lf_offsets, source_offset - 1)
|
|
1311
|
+
return source_offset - removed + inserted
|
|
1312
|
+
|
|
1313
|
+
|
|
1314
|
+
def _validate_compact_basis(
|
|
1315
|
+
basis: _CompactReloadBasis,
|
|
1316
|
+
generated: SourceArtifactRef,
|
|
1317
|
+
) -> None:
|
|
1318
|
+
if (
|
|
1319
|
+
not isinstance(basis.parent_artifact, SourceArtifactRef)
|
|
1320
|
+
or not isinstance(basis.parent_source_map, SourceMap)
|
|
1321
|
+
or basis.parent_source_map.generated != basis.parent_artifact
|
|
1322
|
+
or type(basis.source_length) is not int
|
|
1323
|
+
or basis.source_length != basis.parent_artifact.character_length
|
|
1324
|
+
or basis.interval_starts
|
|
1325
|
+
!= tuple(item.generated.start for item in basis.intervals)
|
|
1326
|
+
or basis.checkpoint_offsets
|
|
1327
|
+
!= tuple(item.source_offset for item in basis.checkpoints)
|
|
1328
|
+
or len(basis.line_ending_starts) != len(basis.line_ending_widths)
|
|
1329
|
+
):
|
|
1330
|
+
raise ValueError("compact reload map basis is invalid")
|
|
1331
|
+
cumulative = 0
|
|
1332
|
+
expected_inserted_after: list[int] = []
|
|
1333
|
+
for item in basis.checkpoints:
|
|
1334
|
+
cumulative += item.inserted_length
|
|
1335
|
+
expected_inserted_after.append(cumulative)
|
|
1336
|
+
if basis.inserted_after != tuple(expected_inserted_after):
|
|
1337
|
+
raise ValueError("compact reload map basis is invalid")
|
|
1338
|
+
previous_end = -1
|
|
1339
|
+
for start, width in zip(
|
|
1340
|
+
basis.line_ending_starts,
|
|
1341
|
+
basis.line_ending_widths,
|
|
1342
|
+
strict=True,
|
|
1343
|
+
):
|
|
1344
|
+
if width not in (1, 2) or start <= previous_end or start + width > basis.source_length:
|
|
1345
|
+
raise ValueError("compact reload line endings are invalid")
|
|
1346
|
+
previous_end = start + width - 1
|
|
1347
|
+
expected_crlf = tuple(
|
|
1348
|
+
start + 1
|
|
1349
|
+
for start, width in zip(
|
|
1350
|
+
basis.line_ending_starts,
|
|
1351
|
+
basis.line_ending_widths,
|
|
1352
|
+
strict=True,
|
|
1353
|
+
)
|
|
1354
|
+
if width == 2
|
|
1355
|
+
)
|
|
1356
|
+
if basis.crlf_lf_offsets != expected_crlf:
|
|
1357
|
+
raise ValueError("compact reload line endings are invalid")
|
|
1358
|
+
expected_length = basis.source_length - len(expected_crlf) + cumulative
|
|
1359
|
+
if expected_length != generated.character_length:
|
|
1360
|
+
raise ValueError("compact reload generated length is invalid")
|
|
1361
|
+
if any(
|
|
1362
|
+
item.generated.end > generated.character_length
|
|
1363
|
+
or item.source_offset > basis.source_length
|
|
1364
|
+
or item.source_anchor.end > basis.source_length
|
|
1365
|
+
or (
|
|
1366
|
+
item.source_origin is not None
|
|
1367
|
+
and item.source_origin.end > basis.source_length
|
|
1368
|
+
)
|
|
1369
|
+
for item in basis.intervals
|
|
1370
|
+
):
|
|
1371
|
+
raise ValueError("compact reload interval is invalid")
|
|
1372
|
+
names: set[str] = set()
|
|
1373
|
+
for item in basis.method_checkpoints:
|
|
1374
|
+
normalized = item.method_name.casefold()
|
|
1375
|
+
if (
|
|
1376
|
+
not item.method_name
|
|
1377
|
+
or normalized in names
|
|
1378
|
+
or not (
|
|
1379
|
+
0
|
|
1380
|
+
<= item.declaration_source_offset
|
|
1381
|
+
<= item.body_source_offset
|
|
1382
|
+
<= item.end_source_offset
|
|
1383
|
+
<= basis.source_length
|
|
1384
|
+
)
|
|
1385
|
+
or item.declaration_generated_offset
|
|
1386
|
+
!= _original_to_generated(
|
|
1387
|
+
item.declaration_source_offset,
|
|
1388
|
+
basis.checkpoint_offsets,
|
|
1389
|
+
basis.inserted_after,
|
|
1390
|
+
basis.crlf_lf_offsets,
|
|
1391
|
+
)
|
|
1392
|
+
or item.body_generated_offset
|
|
1393
|
+
!= _original_to_generated(
|
|
1394
|
+
item.body_source_offset,
|
|
1395
|
+
basis.checkpoint_offsets,
|
|
1396
|
+
basis.inserted_after,
|
|
1397
|
+
basis.crlf_lf_offsets,
|
|
1398
|
+
)
|
|
1399
|
+
or item.end_generated_offset
|
|
1400
|
+
!= _original_to_generated(
|
|
1401
|
+
item.end_source_offset,
|
|
1402
|
+
basis.checkpoint_offsets,
|
|
1403
|
+
basis.inserted_after,
|
|
1404
|
+
basis.crlf_lf_offsets,
|
|
1405
|
+
)
|
|
1406
|
+
):
|
|
1407
|
+
raise ValueError("compact reload method checkpoints are invalid")
|
|
1408
|
+
names.add(normalized)
|
|
1409
|
+
|
|
1410
|
+
|
|
1411
|
+
def _project_exact_piece(
|
|
1412
|
+
parent: SourceMapSegment,
|
|
1413
|
+
parent_piece: SourceSpan,
|
|
1414
|
+
generated: SourceSpan,
|
|
1415
|
+
) -> SourceMapSegment:
|
|
1416
|
+
if parent.relation is MappingRelation.SYNTHETIC:
|
|
1417
|
+
return SourceMapSegment(
|
|
1418
|
+
generated,
|
|
1419
|
+
None,
|
|
1420
|
+
None,
|
|
1421
|
+
MappingRelation.SYNTHETIC,
|
|
1422
|
+
parent.synthetic_region,
|
|
1423
|
+
parent.anchor_ref,
|
|
1424
|
+
parent.anchor_span,
|
|
1425
|
+
)
|
|
1426
|
+
assert parent.origin_ref is not None and parent.origin is not None
|
|
1427
|
+
if parent.relation is MappingRelation.EXACT:
|
|
1428
|
+
origin = SourceSpan(
|
|
1429
|
+
parent.origin.start + parent_piece.start - parent.generated.start,
|
|
1430
|
+
parent.origin.start + parent_piece.end - parent.generated.start,
|
|
1431
|
+
)
|
|
1432
|
+
else:
|
|
1433
|
+
origin = parent.origin
|
|
1434
|
+
return SourceMapSegment(
|
|
1435
|
+
generated,
|
|
1436
|
+
parent.origin_ref,
|
|
1437
|
+
origin,
|
|
1438
|
+
parent.relation,
|
|
1439
|
+
parent.synthetic_region,
|
|
1440
|
+
parent.anchor_ref,
|
|
1441
|
+
parent.anchor_span,
|
|
1442
|
+
)
|
|
1443
|
+
|
|
1444
|
+
|
|
1445
|
+
def _anchor_from_segments(
|
|
1446
|
+
segments: tuple[SourceMapSegment, ...],
|
|
1447
|
+
span: SourceSpan,
|
|
1448
|
+
) -> tuple[SourceUnitRef | None, SourceSpan | None]:
|
|
1449
|
+
candidates: list[tuple[SourceUnitRef, SourceSpan]] = []
|
|
1450
|
+
for segment in segments:
|
|
1451
|
+
start = max(segment.generated.start, span.start)
|
|
1452
|
+
end = min(segment.generated.end, span.end)
|
|
1453
|
+
if start < end:
|
|
1454
|
+
if (
|
|
1455
|
+
segment.relation is MappingRelation.EXACT
|
|
1456
|
+
and isinstance(segment.origin_ref, SourceUnitRef)
|
|
1457
|
+
and segment.origin is not None
|
|
1458
|
+
):
|
|
1459
|
+
candidates.append(
|
|
1460
|
+
(
|
|
1461
|
+
segment.origin_ref,
|
|
1462
|
+
SourceSpan(
|
|
1463
|
+
segment.origin.start + start - segment.generated.start,
|
|
1464
|
+
segment.origin.start + end - segment.generated.start,
|
|
1465
|
+
),
|
|
1466
|
+
)
|
|
1467
|
+
)
|
|
1468
|
+
elif (
|
|
1469
|
+
segment.relation is MappingRelation.DERIVED
|
|
1470
|
+
and isinstance(segment.origin_ref, SourceUnitRef)
|
|
1471
|
+
and segment.origin is not None
|
|
1472
|
+
):
|
|
1473
|
+
candidates.append((segment.origin_ref, segment.origin))
|
|
1474
|
+
elif (
|
|
1475
|
+
isinstance(segment.anchor_ref, SourceUnitRef)
|
|
1476
|
+
and segment.anchor_span is not None
|
|
1477
|
+
):
|
|
1478
|
+
candidates.append((segment.anchor_ref, segment.anchor_span))
|
|
1479
|
+
if not candidates or any(unit != candidates[0][0] for unit, _ in candidates[1:]):
|
|
1480
|
+
return None, None
|
|
1481
|
+
return candidates[0][0], SourceSpan(
|
|
1482
|
+
min(candidate.start for _, candidate in candidates),
|
|
1483
|
+
max(candidate.end for _, candidate in candidates),
|
|
1484
|
+
)
|
|
1485
|
+
|
|
1486
|
+
|
|
1487
|
+
def _mapped_compact_interval(interval: _CompactInsertionInterval) -> MappedOffset:
|
|
1488
|
+
if interval.relation is MappingRelation.SYNTHETIC:
|
|
1489
|
+
return MappedOffset(
|
|
1490
|
+
MappingRelation.SYNTHETIC,
|
|
1491
|
+
synthetic_region=interval.synthetic_region,
|
|
1492
|
+
anchor_unit=interval.anchor_ref,
|
|
1493
|
+
anchor_span=interval.anchor_span,
|
|
1494
|
+
)
|
|
1495
|
+
return MappedOffset(
|
|
1496
|
+
MappingRelation.DERIVED,
|
|
1497
|
+
interval.origin_ref,
|
|
1498
|
+
interval.origin,
|
|
1499
|
+
anchor_unit=interval.anchor_ref,
|
|
1500
|
+
anchor_span=interval.anchor_span,
|
|
1501
|
+
)
|
|
1502
|
+
|
|
1503
|
+
|
|
1504
|
+
def _mapped_compact_segment(segment: SourceMapSegment) -> MappedOffset:
|
|
1505
|
+
if segment.relation is MappingRelation.SYNTHETIC:
|
|
1506
|
+
return MappedOffset(
|
|
1507
|
+
MappingRelation.SYNTHETIC,
|
|
1508
|
+
synthetic_region=segment.synthetic_region,
|
|
1509
|
+
anchor_unit=(
|
|
1510
|
+
segment.anchor_ref
|
|
1511
|
+
if isinstance(segment.anchor_ref, SourceUnitRef)
|
|
1512
|
+
else None
|
|
1513
|
+
),
|
|
1514
|
+
anchor_span=segment.anchor_span,
|
|
1515
|
+
)
|
|
1516
|
+
return MappedOffset(
|
|
1517
|
+
segment.relation,
|
|
1518
|
+
segment.origin_ref if isinstance(segment.origin_ref, SourceUnitRef) else None,
|
|
1519
|
+
segment.origin,
|
|
1520
|
+
anchor_unit=(
|
|
1521
|
+
segment.anchor_ref if isinstance(segment.anchor_ref, SourceUnitRef) else None
|
|
1522
|
+
),
|
|
1523
|
+
anchor_span=segment.anchor_span,
|
|
1524
|
+
)
|
|
1525
|
+
|
|
1526
|
+
|
|
1527
|
+
def _materialize_compact_generic(source_map: CompactReloadSourceMap) -> SourceMap:
|
|
1528
|
+
basis = source_map._compact_basis
|
|
1529
|
+
local_segments: list[SourceMapSegment] = []
|
|
1530
|
+
flattened_segments: list[SourceMapSegment] = []
|
|
1531
|
+
projector = _ParentProjector(basis.parent_source_map)
|
|
1532
|
+
generated_cursor = 0
|
|
1533
|
+
source_cursor = 0
|
|
1534
|
+
|
|
1535
|
+
def append_original(end: int) -> None:
|
|
1536
|
+
nonlocal generated_cursor, source_cursor
|
|
1537
|
+
ending_index = bisect_right(basis.line_ending_starts, source_cursor - 1)
|
|
1538
|
+
while (
|
|
1539
|
+
ending_index < len(basis.line_ending_starts)
|
|
1540
|
+
and basis.line_ending_starts[ending_index] < end
|
|
1541
|
+
):
|
|
1542
|
+
ending_start = basis.line_ending_starts[ending_index]
|
|
1543
|
+
if source_cursor < ending_start:
|
|
1544
|
+
generated = SourceSpan(
|
|
1545
|
+
generated_cursor,
|
|
1546
|
+
generated_cursor + ending_start - source_cursor,
|
|
1547
|
+
)
|
|
1548
|
+
original = SourceSpan(source_cursor, ending_start)
|
|
1549
|
+
local_segments.append(
|
|
1550
|
+
SourceMapSegment(
|
|
1551
|
+
generated,
|
|
1552
|
+
basis.parent_artifact,
|
|
1553
|
+
original,
|
|
1554
|
+
MappingRelation.EXACT,
|
|
1555
|
+
)
|
|
1556
|
+
)
|
|
1557
|
+
flattened_segments.extend(projector.exact(original, generated_cursor))
|
|
1558
|
+
generated_cursor = generated.end
|
|
1559
|
+
width = basis.line_ending_widths[ending_index]
|
|
1560
|
+
ending_end = ending_start + width
|
|
1561
|
+
generated = SourceSpan(generated_cursor, generated_cursor + 1)
|
|
1562
|
+
original = SourceSpan(ending_start, ending_end)
|
|
1563
|
+
local_segments.append(
|
|
1564
|
+
SourceMapSegment(
|
|
1565
|
+
generated,
|
|
1566
|
+
basis.parent_artifact,
|
|
1567
|
+
original,
|
|
1568
|
+
MappingRelation.DERIVED,
|
|
1569
|
+
WORKER_LINE_ENDING_REGION,
|
|
1570
|
+
)
|
|
1571
|
+
)
|
|
1572
|
+
flattened_segments.append(
|
|
1573
|
+
projector.derived(original, generated, WORKER_LINE_ENDING_REGION)
|
|
1574
|
+
)
|
|
1575
|
+
generated_cursor = generated.end
|
|
1576
|
+
source_cursor = ending_end
|
|
1577
|
+
ending_index += 1
|
|
1578
|
+
if source_cursor < end:
|
|
1579
|
+
generated = SourceSpan(
|
|
1580
|
+
generated_cursor,
|
|
1581
|
+
generated_cursor + end - source_cursor,
|
|
1582
|
+
)
|
|
1583
|
+
original = SourceSpan(source_cursor, end)
|
|
1584
|
+
local_segments.append(
|
|
1585
|
+
SourceMapSegment(
|
|
1586
|
+
generated,
|
|
1587
|
+
basis.parent_artifact,
|
|
1588
|
+
original,
|
|
1589
|
+
MappingRelation.EXACT,
|
|
1590
|
+
)
|
|
1591
|
+
)
|
|
1592
|
+
flattened_segments.extend(projector.exact(original, generated_cursor))
|
|
1593
|
+
generated_cursor = generated.end
|
|
1594
|
+
source_cursor = end
|
|
1595
|
+
|
|
1596
|
+
for interval in basis.intervals:
|
|
1597
|
+
if source_cursor < interval.source_offset:
|
|
1598
|
+
append_original(interval.source_offset)
|
|
1599
|
+
if generated_cursor != interval.generated.start:
|
|
1600
|
+
raise ValueError("compact reload interval ordering is invalid")
|
|
1601
|
+
if interval.relation is MappingRelation.SYNTHETIC:
|
|
1602
|
+
local_segments.append(
|
|
1603
|
+
SourceMapSegment(
|
|
1604
|
+
interval.generated,
|
|
1605
|
+
None,
|
|
1606
|
+
None,
|
|
1607
|
+
MappingRelation.SYNTHETIC,
|
|
1608
|
+
interval.synthetic_region,
|
|
1609
|
+
basis.parent_artifact,
|
|
1610
|
+
interval.source_anchor,
|
|
1611
|
+
)
|
|
1612
|
+
)
|
|
1613
|
+
else:
|
|
1614
|
+
if interval.source_origin is None:
|
|
1615
|
+
raise ValueError("compact reload derived interval is invalid")
|
|
1616
|
+
local_segments.append(
|
|
1617
|
+
SourceMapSegment(
|
|
1618
|
+
interval.generated,
|
|
1619
|
+
basis.parent_artifact,
|
|
1620
|
+
interval.source_origin,
|
|
1621
|
+
MappingRelation.DERIVED,
|
|
1622
|
+
interval.synthetic_region,
|
|
1623
|
+
basis.parent_artifact,
|
|
1624
|
+
interval.source_anchor,
|
|
1625
|
+
)
|
|
1626
|
+
)
|
|
1627
|
+
flattened_segments.append(
|
|
1628
|
+
SourceMapSegment(
|
|
1629
|
+
interval.generated,
|
|
1630
|
+
interval.origin_ref,
|
|
1631
|
+
interval.origin,
|
|
1632
|
+
interval.relation,
|
|
1633
|
+
interval.synthetic_region,
|
|
1634
|
+
interval.anchor_ref,
|
|
1635
|
+
interval.anchor_span,
|
|
1636
|
+
)
|
|
1637
|
+
)
|
|
1638
|
+
generated_cursor = interval.generated.end
|
|
1639
|
+
source_cursor = interval.source_offset
|
|
1640
|
+
if source_cursor < basis.source_length:
|
|
1641
|
+
append_original(basis.source_length)
|
|
1642
|
+
segments = flattened_segments if source_map._compact_flattened else local_segments
|
|
1643
|
+
return SourceMap(source_map.generated, tuple(segments))
|
|
1644
|
+
|
|
1645
|
+
|
|
1646
|
+
def _artifact_manifest(artifact: SourceArtifactRef) -> list[object]:
|
|
1647
|
+
return [
|
|
1648
|
+
artifact.kind.value,
|
|
1649
|
+
artifact.source_sha256,
|
|
1650
|
+
artifact.character_length,
|
|
1651
|
+
artifact.line_ending_kind,
|
|
1652
|
+
artifact.lowering_semantic_version,
|
|
1653
|
+
artifact.wrapper_semantic_version,
|
|
1654
|
+
artifact.mode,
|
|
1655
|
+
artifact.worker_generation,
|
|
1656
|
+
artifact.worker_manifest_sha256,
|
|
1657
|
+
artifact.export_catalog_sha256,
|
|
1658
|
+
]
|
|
1659
|
+
|
|
1660
|
+
|
|
1661
|
+
def _indexed_span(
|
|
1662
|
+
unit: SourceUnitRef | None,
|
|
1663
|
+
span: SourceSpan | None,
|
|
1664
|
+
unit_indices: dict[SourceUnitRef, int],
|
|
1665
|
+
) -> tuple[int | None, int | None, int | None]:
|
|
1666
|
+
if unit is None or span is None:
|
|
1667
|
+
return None, None, None
|
|
1668
|
+
return unit_indices[unit], span.start, span.end
|
|
1669
|
+
|
|
1670
|
+
|
|
1671
|
+
def _plain_span(span: SourceSpan | None) -> tuple[int | None, int | None]:
|
|
1672
|
+
if span is None:
|
|
1673
|
+
return None, None
|
|
1674
|
+
return span.start, span.end
|
|
1675
|
+
|
|
1676
|
+
|
|
1677
|
+
def _encoded_line_endings(starts: tuple[int, ...], widths: bytes) -> list[int]:
|
|
1678
|
+
previous = 0
|
|
1679
|
+
result: list[int] = []
|
|
1680
|
+
for start, width in zip(starts, widths, strict=True):
|
|
1681
|
+
result.append(((start - previous) << 1) | (width - 1))
|
|
1682
|
+
previous = start
|
|
1683
|
+
return result
|
|
1684
|
+
|
|
1685
|
+
|
|
1686
|
+
__all__ = [
|
|
1687
|
+
"CompactMappedWorkerSource",
|
|
1688
|
+
"CompactReloadSourceMap",
|
|
1689
|
+
"ReloadInsertion",
|
|
1690
|
+
"ReloadMapCheckpoint",
|
|
1691
|
+
"ReloadMethodBoundary",
|
|
1692
|
+
"ReloadMethodCheckpoint",
|
|
1693
|
+
"WORKER_LINE_ENDING_REGION",
|
|
1694
|
+
"materialize_worker_reload_source",
|
|
1695
|
+
"materialize_worker_reload_source_oracle",
|
|
1696
|
+
"snapshot_compact_mapped_worker_source",
|
|
1697
|
+
]
|