@react-x11/components 0.8.0 → 0.9.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 (323) hide show
  1. package/README.md +95 -34
  2. package/dist/charts/node.d.ts +1 -1
  3. package/dist/charts/node.d.ts.map +1 -1
  4. package/dist/charts/node.js +6 -2
  5. package/dist/charts/node.js.map +1 -1
  6. package/dist/embed/client.d.ts +48 -3
  7. package/dist/embed/client.d.ts.map +1 -1
  8. package/dist/embed/client.js +79 -5
  9. package/dist/embed/client.js.map +1 -1
  10. package/dist/embed/index.d.ts +1 -1
  11. package/dist/embed/index.d.ts.map +1 -1
  12. package/dist/embed/index.js +1 -1
  13. package/dist/embed/index.js.map +1 -1
  14. package/dist/html/node.d.ts +3 -1
  15. package/dist/html/node.d.ts.map +1 -1
  16. package/dist/html/node.js +7 -5
  17. package/dist/html/node.js.map +1 -1
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +1 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/{markdown → internal/markdown}/ast.d.ts +12 -0
  23. package/dist/internal/markdown/ast.d.ts.map +1 -0
  24. package/dist/internal/markdown/ast.js +22 -0
  25. package/dist/internal/markdown/ast.js.map +1 -0
  26. package/dist/internal/markdown/parse.d.ts.map +1 -0
  27. package/dist/{markdown → internal/markdown}/parse.js +112 -22
  28. package/dist/internal/markdown/parse.js.map +1 -0
  29. package/dist/internal/markdown/stringify.d.ts +4 -0
  30. package/dist/internal/markdown/stringify.d.ts.map +1 -0
  31. package/dist/internal/markdown/stringify.js +684 -0
  32. package/dist/internal/markdown/stringify.js.map +1 -0
  33. package/dist/internal/markdown/tags.d.ts.map +1 -0
  34. package/dist/internal/markdown/tags.js.map +1 -0
  35. package/dist/internal/scroll.d.ts +3 -2
  36. package/dist/internal/scroll.d.ts.map +1 -1
  37. package/dist/internal/scroll.js +1 -0
  38. package/dist/internal/scroll.js.map +1 -1
  39. package/dist/maps/anchors.d.ts +98 -0
  40. package/dist/maps/anchors.d.ts.map +1 -0
  41. package/dist/maps/anchors.js +531 -0
  42. package/dist/maps/anchors.js.map +1 -0
  43. package/dist/maps/controller.d.ts +283 -0
  44. package/dist/maps/controller.d.ts.map +1 -0
  45. package/dist/maps/controller.js +743 -0
  46. package/dist/maps/controller.js.map +1 -0
  47. package/dist/maps/gl/buckets.d.ts +95 -0
  48. package/dist/maps/gl/buckets.d.ts.map +1 -0
  49. package/dist/maps/gl/buckets.js +362 -0
  50. package/dist/maps/gl/buckets.js.map +1 -0
  51. package/dist/maps/gl/build-worker.d.ts +13 -0
  52. package/dist/maps/gl/build-worker.d.ts.map +1 -0
  53. package/dist/maps/gl/build-worker.js +44 -0
  54. package/dist/maps/gl/build-worker.js.map +1 -0
  55. package/dist/maps/gl/color.d.ts +8 -0
  56. package/dist/maps/gl/color.d.ts.map +1 -0
  57. package/dist/maps/gl/color.js +57 -0
  58. package/dist/maps/gl/color.js.map +1 -0
  59. package/dist/maps/gl/cover.d.ts +51 -0
  60. package/dist/maps/gl/cover.d.ts.map +1 -0
  61. package/dist/maps/gl/cover.js +124 -0
  62. package/dist/maps/gl/cover.js.map +1 -0
  63. package/dist/maps/gl/index.d.ts +3 -0
  64. package/dist/maps/gl/index.d.ts.map +1 -0
  65. package/dist/maps/gl/index.js +20 -0
  66. package/dist/maps/gl/index.js.map +1 -0
  67. package/dist/maps/gl/markers.d.ts +28 -0
  68. package/dist/maps/gl/markers.d.ts.map +1 -0
  69. package/dist/maps/gl/markers.js +60 -0
  70. package/dist/maps/gl/markers.js.map +1 -0
  71. package/dist/maps/gl/overlays.d.ts +68 -0
  72. package/dist/maps/gl/overlays.d.ts.map +1 -0
  73. package/dist/maps/gl/overlays.js +300 -0
  74. package/dist/maps/gl/overlays.js.map +1 -0
  75. package/dist/maps/gl/pane.d.ts +12 -0
  76. package/dist/maps/gl/pane.d.ts.map +1 -0
  77. package/dist/maps/gl/pane.js +37 -0
  78. package/dist/maps/gl/pane.js.map +1 -0
  79. package/dist/maps/gl/placement.d.ts +111 -0
  80. package/dist/maps/gl/placement.d.ts.map +1 -0
  81. package/dist/maps/gl/placement.js +567 -0
  82. package/dist/maps/gl/placement.js.map +1 -0
  83. package/dist/maps/gl/renderer.d.ts +352 -0
  84. package/dist/maps/gl/renderer.d.ts.map +1 -0
  85. package/dist/maps/gl/renderer.js +1127 -0
  86. package/dist/maps/gl/renderer.js.map +1 -0
  87. package/dist/maps/gl/shaders.d.ts +120 -0
  88. package/dist/maps/gl/shaders.d.ts.map +1 -0
  89. package/dist/maps/gl/shaders.js +451 -0
  90. package/dist/maps/gl/shaders.js.map +1 -0
  91. package/dist/maps/gl/store.d.ts +115 -0
  92. package/dist/maps/gl/store.d.ts.map +1 -0
  93. package/dist/maps/gl/store.js +469 -0
  94. package/dist/maps/gl/store.js.map +1 -0
  95. package/dist/maps/gl/text.d.ts +154 -0
  96. package/dist/maps/gl/text.d.ts.map +1 -0
  97. package/dist/maps/gl/text.js +382 -0
  98. package/dist/maps/gl/text.js.map +1 -0
  99. package/dist/maps/gl/view.d.ts +54 -0
  100. package/dist/maps/gl/view.d.ts.map +1 -0
  101. package/dist/maps/gl/view.js +974 -0
  102. package/dist/maps/gl/view.js.map +1 -0
  103. package/dist/maps/index.d.ts +1 -1
  104. package/dist/maps/index.d.ts.map +1 -1
  105. package/dist/maps/index.js +216 -52
  106. package/dist/maps/index.js.map +1 -1
  107. package/dist/maps/labels.d.ts +37 -16
  108. package/dist/maps/labels.d.ts.map +1 -1
  109. package/dist/maps/labels.js +188 -119
  110. package/dist/maps/labels.js.map +1 -1
  111. package/dist/maps/node.d.ts +162 -56
  112. package/dist/maps/node.d.ts.map +1 -1
  113. package/dist/maps/node.js +607 -515
  114. package/dist/maps/node.js.map +1 -1
  115. package/dist/maps/overlay.d.ts +72 -9
  116. package/dist/maps/overlay.d.ts.map +1 -1
  117. package/dist/maps/overlay.js +108 -28
  118. package/dist/maps/overlay.js.map +1 -1
  119. package/dist/maps/paint.d.ts +3 -0
  120. package/dist/maps/paint.d.ts.map +1 -1
  121. package/dist/maps/paint.js.map +1 -1
  122. package/dist/maps/proj.d.ts +14 -0
  123. package/dist/maps/proj.d.ts.map +1 -1
  124. package/dist/maps/proj.js +28 -0
  125. package/dist/maps/proj.js.map +1 -1
  126. package/dist/maps/renderer.d.ts +69 -0
  127. package/dist/maps/renderer.d.ts.map +1 -0
  128. package/dist/maps/renderer.js +66 -0
  129. package/dist/maps/renderer.js.map +1 -0
  130. package/dist/maps/sources.d.ts +25 -3
  131. package/dist/maps/sources.d.ts.map +1 -1
  132. package/dist/maps/sources.js +17 -0
  133. package/dist/maps/sources.js.map +1 -1
  134. package/dist/maps/theme.d.ts +19 -0
  135. package/dist/maps/theme.d.ts.map +1 -0
  136. package/dist/maps/theme.js +44 -0
  137. package/dist/maps/theme.js.map +1 -0
  138. package/dist/maps/tiles.d.ts +117 -17
  139. package/dist/maps/tiles.d.ts.map +1 -1
  140. package/dist/maps/tiles.js +163 -30
  141. package/dist/maps/tiles.js.map +1 -1
  142. package/dist/maps/types.d.ts +188 -20
  143. package/dist/maps/types.d.ts.map +1 -1
  144. package/dist/markdown/expressions.d.ts +1 -1
  145. package/dist/markdown/expressions.d.ts.map +1 -1
  146. package/dist/markdown/expressions.js.map +1 -1
  147. package/dist/markdown/index.d.ts +7 -6
  148. package/dist/markdown/index.d.ts.map +1 -1
  149. package/dist/markdown/index.js +9 -7
  150. package/dist/markdown/index.js.map +1 -1
  151. package/dist/markdown/spans.d.ts +1 -1
  152. package/dist/markdown/spans.d.ts.map +1 -1
  153. package/dist/media-player/index.d.ts +11 -3
  154. package/dist/media-player/index.d.ts.map +1 -1
  155. package/dist/media-player/index.js +13 -2
  156. package/dist/media-player/index.js.map +1 -1
  157. package/dist/rich-text-editor/clipboard.d.ts +23 -0
  158. package/dist/rich-text-editor/clipboard.d.ts.map +1 -0
  159. package/dist/rich-text-editor/clipboard.js +307 -0
  160. package/dist/rich-text-editor/clipboard.js.map +1 -0
  161. package/dist/rich-text-editor/collab.d.ts +32 -0
  162. package/dist/rich-text-editor/collab.d.ts.map +1 -0
  163. package/dist/rich-text-editor/collab.js +55 -0
  164. package/dist/rich-text-editor/collab.js.map +1 -0
  165. package/dist/rich-text-editor/commands.d.ts +50 -0
  166. package/dist/rich-text-editor/commands.d.ts.map +1 -0
  167. package/dist/rich-text-editor/commands.js +376 -0
  168. package/dist/rich-text-editor/commands.js.map +1 -0
  169. package/dist/rich-text-editor/drag.d.ts +68 -0
  170. package/dist/rich-text-editor/drag.d.ts.map +1 -0
  171. package/dist/rich-text-editor/drag.js +148 -0
  172. package/dist/rich-text-editor/drag.js.map +1 -0
  173. package/dist/rich-text-editor/html.d.ts +145 -0
  174. package/dist/rich-text-editor/html.d.ts.map +1 -0
  175. package/dist/rich-text-editor/html.js +516 -0
  176. package/dist/rich-text-editor/html.js.map +1 -0
  177. package/dist/rich-text-editor/index.d.ts +263 -0
  178. package/dist/rich-text-editor/index.d.ts.map +1 -0
  179. package/dist/rich-text-editor/index.js +822 -0
  180. package/dist/rich-text-editor/index.js.map +1 -0
  181. package/dist/rich-text-editor/inline.d.ts +94 -0
  182. package/dist/rich-text-editor/inline.d.ts.map +1 -0
  183. package/dist/rich-text-editor/inline.js +252 -0
  184. package/dist/rich-text-editor/inline.js.map +1 -0
  185. package/dist/rich-text-editor/keymap.d.ts +71 -0
  186. package/dist/rich-text-editor/keymap.d.ts.map +1 -0
  187. package/dist/rich-text-editor/keymap.js +393 -0
  188. package/dist/rich-text-editor/keymap.js.map +1 -0
  189. package/dist/rich-text-editor/keys.d.ts +29 -0
  190. package/dist/rich-text-editor/keys.d.ts.map +1 -0
  191. package/dist/rich-text-editor/keys.js +93 -0
  192. package/dist/rich-text-editor/keys.js.map +1 -0
  193. package/dist/rich-text-editor/look.d.ts +71 -0
  194. package/dist/rich-text-editor/look.d.ts.map +1 -0
  195. package/dist/rich-text-editor/look.js +342 -0
  196. package/dist/rich-text-editor/look.js.map +1 -0
  197. package/dist/rich-text-editor/markdown.d.ts +18 -0
  198. package/dist/rich-text-editor/markdown.d.ts.map +1 -0
  199. package/dist/rich-text-editor/markdown.js +496 -0
  200. package/dist/rich-text-editor/markdown.js.map +1 -0
  201. package/dist/rich-text-editor/nodes.d.ts +135 -0
  202. package/dist/rich-text-editor/nodes.d.ts.map +1 -0
  203. package/dist/rich-text-editor/nodes.js +397 -0
  204. package/dist/rich-text-editor/nodes.js.map +1 -0
  205. package/dist/rich-text-editor/render.d.ts +68 -0
  206. package/dist/rich-text-editor/render.d.ts.map +1 -0
  207. package/dist/rich-text-editor/render.js +500 -0
  208. package/dist/rich-text-editor/render.js.map +1 -0
  209. package/dist/rich-text-editor/schema.d.ts +16 -0
  210. package/dist/rich-text-editor/schema.d.ts.map +1 -0
  211. package/dist/rich-text-editor/schema.js +386 -0
  212. package/dist/rich-text-editor/schema.js.map +1 -0
  213. package/dist/rich-text-editor/store.d.ts +11 -0
  214. package/dist/rich-text-editor/store.d.ts.map +1 -0
  215. package/dist/rich-text-editor/store.js +43 -0
  216. package/dist/rich-text-editor/store.js.map +1 -0
  217. package/dist/rich-text-editor/suggest.d.ts +127 -0
  218. package/dist/rich-text-editor/suggest.d.ts.map +1 -0
  219. package/dist/rich-text-editor/suggest.js +0 -0
  220. package/dist/rich-text-editor/suggest.js.map +1 -0
  221. package/dist/rich-text-editor/tables.d.ts +41 -0
  222. package/dist/rich-text-editor/tables.d.ts.map +1 -0
  223. package/dist/rich-text-editor/tables.js +204 -0
  224. package/dist/rich-text-editor/tables.js.map +1 -0
  225. package/dist/rich-text-editor/toolbar.d.ts +58 -0
  226. package/dist/rich-text-editor/toolbar.d.ts.map +1 -0
  227. package/dist/rich-text-editor/toolbar.js +548 -0
  228. package/dist/rich-text-editor/toolbar.js.map +1 -0
  229. package/dist/rich-text-editor/view.d.ts +368 -0
  230. package/dist/rich-text-editor/view.d.ts.map +1 -0
  231. package/dist/rich-text-editor/view.js +1968 -0
  232. package/dist/rich-text-editor/view.js.map +1 -0
  233. package/dist/rich-text-editor/virtual.d.ts +54 -0
  234. package/dist/rich-text-editor/virtual.d.ts.map +1 -0
  235. package/dist/rich-text-editor/virtual.js +262 -0
  236. package/dist/rich-text-editor/virtual.js.map +1 -0
  237. package/dist/richtext/node.d.ts +25 -2
  238. package/dist/richtext/node.d.ts.map +1 -1
  239. package/dist/richtext/node.js +46 -24
  240. package/dist/richtext/node.js.map +1 -1
  241. package/dist/terminal/backends.d.ts +4 -1
  242. package/dist/terminal/backends.d.ts.map +1 -1
  243. package/dist/terminal/backends.js.map +1 -1
  244. package/dist/terminal/index.d.ts +18 -7
  245. package/dist/terminal/index.d.ts.map +1 -1
  246. package/dist/terminal/index.js +28 -11
  247. package/dist/terminal/index.js.map +1 -1
  248. package/package.json +23 -4
  249. package/src/charts/node.ts +6 -2
  250. package/src/embed/client.ts +102 -8
  251. package/src/embed/index.ts +2 -0
  252. package/src/html/node.ts +7 -5
  253. package/src/index.ts +2 -0
  254. package/src/{markdown → internal/markdown}/ast.ts +24 -7
  255. package/src/{markdown → internal/markdown}/parse.ts +134 -24
  256. package/src/internal/markdown/stringify.ts +772 -0
  257. package/src/internal/scroll.ts +5 -3
  258. package/src/maps/anchors.ts +607 -0
  259. package/src/maps/controller.ts +999 -0
  260. package/src/maps/gl/buckets.ts +457 -0
  261. package/src/maps/gl/build-worker.ts +55 -0
  262. package/src/maps/gl/color.ts +62 -0
  263. package/src/maps/gl/cover.ts +170 -0
  264. package/src/maps/gl/index.ts +23 -0
  265. package/src/maps/gl/markers.ts +83 -0
  266. package/src/maps/gl/overlays.ts +379 -0
  267. package/src/maps/gl/pane.ts +42 -0
  268. package/src/maps/gl/placement.ts +816 -0
  269. package/src/maps/gl/renderer.ts +1576 -0
  270. package/src/maps/gl/shaders.ts +486 -0
  271. package/src/maps/gl/store.ts +566 -0
  272. package/src/maps/gl/text.ts +495 -0
  273. package/src/maps/gl/view.ts +1224 -0
  274. package/src/maps/index.ts +270 -81
  275. package/src/maps/labels.ts +214 -121
  276. package/src/maps/node.ts +763 -629
  277. package/src/maps/overlay.ts +148 -43
  278. package/src/maps/paint.ts +3 -0
  279. package/src/maps/proj.ts +31 -0
  280. package/src/maps/renderer.ts +155 -0
  281. package/src/maps/sources.ts +38 -3
  282. package/src/maps/theme.ts +51 -0
  283. package/src/maps/tiles.ts +191 -33
  284. package/src/maps/types.ts +188 -20
  285. package/src/markdown/expressions.ts +5 -1
  286. package/src/markdown/index.ts +14 -11
  287. package/src/markdown/spans.ts +1 -1
  288. package/src/media-player/index.ts +18 -4
  289. package/src/rich-text-editor/clipboard.ts +439 -0
  290. package/src/rich-text-editor/collab.ts +91 -0
  291. package/src/rich-text-editor/commands.ts +448 -0
  292. package/src/rich-text-editor/dom-globals.d.ts +23 -0
  293. package/src/rich-text-editor/drag.ts +211 -0
  294. package/src/rich-text-editor/html.ts +619 -0
  295. package/src/rich-text-editor/index.ts +1331 -0
  296. package/src/rich-text-editor/inline.ts +345 -0
  297. package/src/rich-text-editor/keymap.ts +510 -0
  298. package/src/rich-text-editor/keys.ts +119 -0
  299. package/src/rich-text-editor/look.ts +427 -0
  300. package/src/rich-text-editor/markdown.ts +653 -0
  301. package/src/rich-text-editor/nodes.ts +497 -0
  302. package/src/rich-text-editor/render.ts +800 -0
  303. package/src/rich-text-editor/schema.ts +431 -0
  304. package/src/rich-text-editor/store.ts +39 -0
  305. package/src/rich-text-editor/suggest.ts +597 -0
  306. package/src/rich-text-editor/tables.ts +272 -0
  307. package/src/rich-text-editor/toolbar.ts +724 -0
  308. package/src/rich-text-editor/view.ts +2287 -0
  309. package/src/rich-text-editor/virtual.ts +347 -0
  310. package/src/richtext/node.ts +59 -30
  311. package/src/terminal/backends.ts +4 -1
  312. package/src/terminal/index.ts +43 -15
  313. package/dist/markdown/ast.d.ts.map +0 -1
  314. package/dist/markdown/ast.js +0 -17
  315. package/dist/markdown/ast.js.map +0 -1
  316. package/dist/markdown/parse.d.ts.map +0 -1
  317. package/dist/markdown/parse.js.map +0 -1
  318. package/dist/markdown/tags.d.ts.map +0 -1
  319. package/dist/markdown/tags.js.map +0 -1
  320. /package/dist/{markdown → internal/markdown}/parse.d.ts +0 -0
  321. /package/dist/{markdown → internal/markdown}/tags.d.ts +0 -0
  322. /package/dist/{markdown → internal/markdown}/tags.js +0 -0
  323. /package/src/{markdown → internal/markdown}/tags.ts +0 -0
package/src/maps/tiles.ts CHANGED
@@ -18,6 +18,14 @@
18
18
  // scaled. Only an integer zoom change, a style change or a display-scale
19
19
  // change invalidates one.
20
20
  //
21
+ // Both are filed under the **source object**, not under its `id`. An id is
22
+ // only what a source is called, and two providers can share one — a source
23
+ // without one is named for its slot in `sources`, and `osmRasterSource` is
24
+ // `osm-raster` whichever server it points at — so filing by id handed a map
25
+ // switched to another provider the old one's tiles wherever it had them,
26
+ // until eviction got round to them. Filed by object, a new provider starts
27
+ // empty, and an old one keeps its tiles for when it comes back.
28
+ //
21
29
  // The surface is the expensive half — on the corpus in `scripts/bench/`, a
22
30
  // dense city tile is 50-140 ms to rasterize and about 0.05 ms to composite
23
31
  // — so the cache's job is to make sure that cost is paid once per tile per
@@ -80,6 +88,14 @@ export interface TileRender {
80
88
  zoom: number;
81
89
  /** The cache generation it was drawn under. */
82
90
  generation: number;
91
+ /**
92
+ * Whether its pixels depend on the style. A vector tile's do — they are
93
+ * the style, rasterized — and a raster tile's do not: they are the
94
+ * provider's image, uploaded as it arrived. So an unstyled rendering
95
+ * belongs to every generation, and a restyle neither redraws it nor stops
96
+ * showing it.
97
+ */
98
+ styled: boolean;
83
99
  /** The next style run to draw, or `-1` when it is finished. */
84
100
  progress: number;
85
101
  /** …and how far into that run's active layers, because a run is not a
@@ -97,6 +113,12 @@ export interface TileRender {
97
113
  */
98
114
  export interface TileDataEntry {
99
115
  readonly key: string;
116
+ /** Who answers for it — and so which provider the bytes came from,
117
+ * since tiles are filed under the source object. */
118
+ readonly source: MapSource;
119
+ /** What that source is called: the `sourceId` its `load` requests carry
120
+ * and `onError` reports. */
121
+ readonly sourceId: string;
100
122
  readonly tile: TileId;
101
123
  status: TileStatus;
102
124
  error: unknown;
@@ -141,7 +163,15 @@ export class CachedTile {
141
163
  * keeps being composited until it is ready to be replaced.
142
164
  */
143
165
  shown: TileRender | null = null;
144
- /** The rendering being drawn, or null when there is nothing to draw. */
166
+ /**
167
+ * The rendering being drawn, or null when there is nothing to draw.
168
+ *
169
+ * Finished ones do not usually stay: a draft is {@link TileCache.promote}d
170
+ * in the frame it is done. The exception is a restyle, which holds the
171
+ * previous style's whole picture up until the view is redrawn — so there
172
+ * a finished draft waits here until {@link TileCache.swap} puts every one
173
+ * on screen at once.
174
+ */
145
175
  drawing: TileRender | null = null;
146
176
  /** Frame counter of the last frame that wanted it — what eviction sorts
147
177
  * on. */
@@ -207,6 +237,10 @@ export class TileCache {
207
237
  private readonly _entries = new Map<string, CachedTile>();
208
238
  /** The source's own tiles, shared by every rendering that draws one. */
209
239
  private readonly _data = new Map<string, TileDataEntry>();
240
+ /** The key prefix of each source object — per object and not per id,
241
+ * for the reason at the top of this file. */
242
+ private readonly _prefixes = new WeakMap<MapSource, string>();
243
+ private _prefixCount = 0;
210
244
  private readonly _options: TileCacheOptions;
211
245
  private _frame = 0;
212
246
  private _surfaceBytes = 0;
@@ -227,7 +261,16 @@ export class TileCache {
227
261
  return this._generation;
228
262
  }
229
263
 
230
- /** Every rendered surface is stale — a new style, a new display scale. */
264
+ /**
265
+ * Every styled surface is stale: a new style, or `refresh()` after an
266
+ * edit to one. The data behind them stays, and so does a raster tile's
267
+ * rendering, which no style drew (see {@link TileRender.styled}).
268
+ *
269
+ * A new display scale needs none of this, because a rendering's size is
270
+ * already part of what makes it valid. And nothing on screen is thrown
271
+ * away here: each picture stays until its replacement is finished —
272
+ * {@link promote} for one tile, {@link swap} for the whole view at once.
273
+ */
231
274
  invalidateStyle(): void {
232
275
  this._generation++;
233
276
  }
@@ -241,21 +284,31 @@ export class TileCache {
241
284
  return this._entries.size;
242
285
  }
243
286
 
244
- key(sourceId: string, tile: TileId): string {
245
- return `${sourceId}:${tileKey(tile)}`;
287
+ /** What a source's tile is filed under: a prefix of the source object's
288
+ * own, then `z/x/y`. The id is in the prefix only so that a key reads
289
+ * well in a debugger; two objects with one id get two prefixes. */
290
+ key(source: MapSource, tile: TileId): string {
291
+ let prefix = this._prefixes.get(source);
292
+ if (prefix === undefined) {
293
+ prefix = `${source.id ?? 'source'}#${++this._prefixCount}`;
294
+ this._prefixes.set(source, prefix);
295
+ }
296
+ return `${prefix}:${tileKey(tile)}`;
246
297
  }
247
298
 
248
- peek(sourceId: string, tile: TileId): CachedTile | undefined {
249
- return this._entries.get(this.key(sourceId, tile));
299
+ peek(source: MapSource, tile: TileId): CachedTile | undefined {
300
+ return this._entries.get(this.key(source, tile));
250
301
  }
251
302
 
252
303
  /**
253
304
  * The entry for a tile the cover asked for, and the data behind it,
254
305
  * asking the source for that data if nothing has yet.
255
306
  *
256
- * `dataTile` is the tile whose bytes serve this one — itself, until the
257
- * cover goes deeper than the source cuts. Marks both used by the current
258
- * frame, which is what keeps them out of the next eviction.
307
+ * Filed under `source`; `sourceId` is only what it is called. `dataTile`
308
+ * is the tile whose bytes serve this one — itself, until the cover goes
309
+ * deeper than the source cuts. Marks both used by the current frame,
310
+ * which is what keeps them out of the next eviction — and a load still
311
+ * in flight from being cancelled by {@link sweep}.
259
312
  */
260
313
  want(
261
314
  source: MapSource,
@@ -265,7 +318,7 @@ export class TileCache {
265
318
  sub: { x: number; y: number; span: number } = { x: 0, y: 0, span: 1 },
266
319
  ): CachedTile {
267
320
  const data = this._wantData(source, sourceId, dataTile);
268
- const key = this.key(sourceId, tile);
321
+ const key = this.key(source, tile);
269
322
  let entry = this._entries.get(key);
270
323
  if (!entry) {
271
324
  entry = new CachedTile(key, sourceId, tile, data, sub);
@@ -280,11 +333,13 @@ export class TileCache {
280
333
  sourceId: string,
281
334
  tile: TileId,
282
335
  ): TileDataEntry {
283
- const key = this.key(sourceId, tile);
336
+ const key = this.key(source, tile);
284
337
  let data = this._data.get(key);
285
338
  if (!data) {
286
339
  data = {
287
340
  key,
341
+ source,
342
+ sourceId,
288
343
  tile,
289
344
  status: 'idle',
290
345
  error: null,
@@ -299,23 +354,19 @@ export class TileCache {
299
354
  }
300
355
  data.lastUsed = this._frame;
301
356
  if (data.status === 'idle') {
302
- this._load(source, sourceId, data);
357
+ this._load(data);
303
358
  } else if (data.status === 'error' && Date.now() >= data.retryAt) {
304
359
  // A failed tile is retried, but on a backoff rather than on every
305
360
  // frame. Without it a source that is down — or an application whose
306
361
  // `load` throws on the first call, which is how this was found — is
307
362
  // asked for every visible tile sixty times a second, which is a
308
363
  // retry storm pointed at somebody else's servers.
309
- this._load(source, sourceId, data);
364
+ this._load(data);
310
365
  }
311
366
  return data;
312
367
  }
313
368
 
314
- private _load(
315
- source: MapSource,
316
- sourceId: string,
317
- entry: TileDataEntry,
318
- ): void {
369
+ private _load(entry: TileDataEntry): void {
319
370
  entry.status = 'loading';
320
371
  entry.error = null;
321
372
  // A **real** `AbortController` where the runtime has one. A look-alike
@@ -365,7 +416,11 @@ export class TileCache {
365
416
  };
366
417
  let result: TileData | Promise<TileData>;
367
418
  try {
368
- result = source.load({ ...entry.tile, sourceId, signal });
419
+ result = entry.source.load({
420
+ ...entry.tile,
421
+ sourceId: entry.sourceId,
422
+ signal,
423
+ });
369
424
  } catch (error) {
370
425
  settle(() => fail(error));
371
426
  return;
@@ -408,20 +463,24 @@ export class TileCache {
408
463
  * under the fine one until it arrives — which is the difference between a
409
464
  * map that fills in and a map that flashes empty. Bounded, because
410
465
  * scaling one tile over sixteen screenfuls is worse than the hole.
466
+ *
467
+ * With a `generation`, only a picture drawn in it counts: a map showing
468
+ * one style must not cover a hole with a tile drawn in another.
411
469
  */
412
470
  ancestorWithSurface(
413
- sourceId: string,
471
+ source: MapSource,
414
472
  tile: TileId,
415
473
  levels = 5,
474
+ generation?: number,
416
475
  ): CachedTile | null {
417
476
  let z = tile.z - 1;
418
477
  let x = tile.x >> 1;
419
478
  let y = tile.y >> 1;
420
479
  for (let up = 0; up < levels && z >= 0; up++, z--, x >>= 1, y >>= 1) {
421
- const entry = this._entries.get(this.key(sourceId, { z, x, y }));
480
+ const entry = this._entries.get(this.key(source, { z, x, y }));
422
481
  // `shown` is finished by construction, so an ancestor is never a
423
482
  // half-drawn picture.
424
- if (entry?.shown) {
483
+ if (entry?.shown && drawnFor(entry.shown, generation)) {
425
484
  // Stamped, because for as long as it is covering a hole it is on
426
485
  // screen — and an unstamped entry is the *first* thing eviction
427
486
  // takes, which would drop the only picture the map is showing.
@@ -445,11 +504,14 @@ export class TileCache {
445
504
  * `depth` is how many levels down to look, and it is small on purpose: a
446
505
  * level down is 4 tiles, two is 16, and beyond that the pieces are too
447
506
  * small to be worth the composites.
507
+ *
508
+ * `generation` as for {@link ancestorWithSurface}.
448
509
  */
449
510
  descendantsWithSurface(
450
- sourceId: string,
511
+ source: MapSource,
451
512
  tile: TileId,
452
513
  depth = 2,
514
+ generation?: number,
453
515
  ): { entry: CachedTile; x: number; y: number; span: number }[] {
454
516
  for (let down = 1; down <= depth; down++) {
455
517
  const span = 1 << down;
@@ -458,13 +520,13 @@ export class TileCache {
458
520
  for (let dy = 0; dy < span; dy++) {
459
521
  for (let dx = 0; dx < span; dx++) {
460
522
  const entry = this._entries.get(
461
- this.key(sourceId, {
523
+ this.key(source, {
462
524
  z: tile.z + down,
463
525
  x: (tile.x << down) + dx,
464
526
  y: (tile.y << down) + dy,
465
527
  }),
466
528
  );
467
- if (entry?.shown) {
529
+ if (entry?.shown && drawnFor(entry.shown, generation)) {
468
530
  entry.lastUsed = this._frame;
469
531
  found.push({ entry, x: dx, y: dy, span });
470
532
  }
@@ -493,12 +555,19 @@ export class TileCache {
493
555
  * the tile is blank for the several frames it takes to redraw, which
494
556
  * above a source's `maxZoom` happens at every integer zoom — the same
495
557
  * z14 tile serves 15, 16, 17 and on.
558
+ *
559
+ * A draft that is finished but not yet promoted — a restyle holding the
560
+ * old style up until the whole view is ready — matches like any other and
561
+ * comes back as it is, so it is not drawn twice.
496
562
  */
497
563
  beginRender(
498
564
  entry: CachedTile,
499
565
  size: number,
500
566
  zoom: number,
501
567
  make: SurfaceFactory,
568
+ /** False for a raster tile, whose pixels are the provider's and no
569
+ * style's — see {@link TileRender.styled}. */
570
+ styled = true,
502
571
  ): TileRender | null {
503
572
  if (this._matches(entry.shown, size, zoom)) return null;
504
573
  if (this._matches(entry.drawing, size, zoom)) return entry.drawing;
@@ -515,6 +584,7 @@ export class TileCache {
515
584
  size,
516
585
  zoom,
517
586
  generation: this._generation,
587
+ styled,
518
588
  progress: 0,
519
589
  progressLayer: 0,
520
590
  };
@@ -530,7 +600,7 @@ export class TileCache {
530
600
  render !== null &&
531
601
  render.size === size &&
532
602
  render.zoom === zoom &&
533
- render.generation === this._generation
603
+ drawnFor(render, this._generation)
534
604
  );
535
605
  }
536
606
 
@@ -545,6 +615,33 @@ export class TileCache {
545
615
  return true;
546
616
  }
547
617
 
618
+ /**
619
+ * Put the current generation on screen in one go: every finished draft
620
+ * becomes its tile's picture, and every picture and draft of an earlier
621
+ * generation is released — apart from a raster tile's, which no style
622
+ * drew.
623
+ *
624
+ * The other half of a restyle. While the element holds the previous style
625
+ * up it does not {@link promote}, so finished drafts wait in `drawing`,
626
+ * and this is the frame they all land in. What is released is more than
627
+ * what they replace: a tile off screen still holds whatever it was last
628
+ * drawn in, which is now a picture of a style the map has left — never
629
+ * composited again, and otherwise kept until eviction got round to it.
630
+ */
631
+ swap(): void {
632
+ for (const entry of this._entries.values()) {
633
+ if (entry.drawing && !drawnFor(entry.drawing, this._generation)) {
634
+ this._release(entry.drawing);
635
+ entry.drawing = null;
636
+ }
637
+ if (this.promote(entry)) continue;
638
+ if (entry.shown && !drawnFor(entry.shown, this._generation)) {
639
+ this._release(entry.shown);
640
+ entry.shown = null;
641
+ }
642
+ }
643
+ }
644
+
548
645
  /** Note where a tile's rasterization stopped: at run `run`, having
549
646
  * finished `layer` of its active layers (`-1` for all of them). */
550
647
  advance(
@@ -558,14 +655,18 @@ export class TileCache {
558
655
  }
559
656
 
560
657
  /**
561
- * Drop what is no longer worth keeping.
658
+ * Drop what is no longer worth keeping. Called once a frame, after every
659
+ * tile the frame still needs has been through {@link want}.
562
660
  *
563
- * Surfaces go first and by least-recently-wanted, because they are two
661
+ * A load the frame did not want is cancelled outright (see
662
+ * `_cancelUnwanted`). What has arrived is kept on budgets instead:
663
+ * surfaces first and by least-recently-wanted, because they are two
564
664
  * orders of magnitude larger than the data behind them and much cheaper
565
- * to lose: a dropped surface is one re-rasterization, a dropped tile is a
566
- * network request.
665
+ * to lose — a dropped surface is one re-rasterization, a dropped tile is
666
+ * a network request.
567
667
  */
568
668
  sweep(): void {
669
+ this._cancelUnwanted();
569
670
  if (
570
671
  this._surfaceBytes >
571
672
  (this._options.surfaceBudget ?? DEFAULT_SURFACE_BUDGET)
@@ -605,6 +706,45 @@ export class TileCache {
605
706
  }
606
707
  }
607
708
 
709
+ /**
710
+ * Cancel every load the frame just drawn did not ask for.
711
+ *
712
+ * A tile panned or zoomed out of the cover — or every tile of a source
713
+ * taken out of `sources` — would otherwise load to the end: a request
714
+ * nobody is waiting for, then a full-pane repaint when it lands, because
715
+ * a landing tile is an `onChange`. The cover is padded, so a tile just off
716
+ * screen is still wanted and keeps loading. That is also the contract on
717
+ * the element: it wants the whole cover on every frame, clipped and
718
+ * mid-gesture ones included, or what it skipped is aborted here and
719
+ * fetched again.
720
+ *
721
+ * Only loads: data that has arrived stays on the budgets above, and is
722
+ * what makes panning back, or switching back to a provider, free.
723
+ *
724
+ * And forgotten rather than parked. An aborted load never settles
725
+ * (`settle` ignores it), so an entry left in `_data` would say `'loading'`
726
+ * forever and never be asked for again; its renderings go with it, since
727
+ * each reads through to the same entry for life, and none has a surface to
728
+ * lose. The next frame that wants the tile starts over, with a new request
729
+ * and a new signal.
730
+ */
731
+ private _cancelUnwanted(): void {
732
+ let unwanted: Set<TileDataEntry> | null = null;
733
+ for (const data of this._data.values()) {
734
+ if (data.status === 'loading' && data.lastUsed < this._frame) {
735
+ (unwanted ??= new Set<TileDataEntry>()).add(data);
736
+ }
737
+ }
738
+ if (!unwanted) return;
739
+ for (const entry of [...this._entries.values()]) {
740
+ if (unwanted.has(entry.data)) this._drop(entry);
741
+ }
742
+ for (const data of unwanted) {
743
+ data.abort?.();
744
+ this._data.delete(data.key);
745
+ }
746
+ }
747
+
608
748
  private _dropSurface(entry: CachedTile): void {
609
749
  if (entry.shown) this._release(entry.shown);
610
750
  if (entry.drawing) this._release(entry.drawing);
@@ -647,14 +787,32 @@ export class TileCache {
647
787
  return this._entries.values();
648
788
  }
649
789
 
650
- /** Every source tile whose bytes are held. What labels are collected
651
- * from: a label belongs to the tile the data came from, and past a
652
- * source's depth many renderings share one of those. */
790
+ /** Every source tile whose bytes are held — including those of sources no
791
+ * longer on the map, which is what makes switching back free and why a
792
+ * reader filters on `source`. What labels are collected from: a label
793
+ * belongs to the tile the data came from, and past a source's depth many
794
+ * renderings share one of those. */
653
795
  dataEntries(): IterableIterator<TileDataEntry> {
654
796
  return this._data.values();
655
797
  }
656
798
  }
657
799
 
800
+ /**
801
+ * Whether a rendering can be shown for `generation`: any can when none is
802
+ * given, which is `progressive`; one no style drew — a raster tile's — can
803
+ * in every generation; any other only in the one it was drawn under.
804
+ */
805
+ export function drawnFor(
806
+ render: TileRender,
807
+ generation: number | undefined,
808
+ ): boolean {
809
+ return (
810
+ generation === undefined ||
811
+ !render.styled ||
812
+ render.generation === generation
813
+ );
814
+ }
815
+
658
816
  /** A source's pyramid, memoized per source object so the defaults are not
659
817
  * refilled per frame. */
660
818
  const pyramids = new WeakMap<