pmtiles-swarm 0.68.2 → 0.68.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,25 @@
7
7
  ### 🐞 Bug fixes
8
8
  - _...Add new stuff here..._
9
9
 
10
+ ## 0.68.3
11
+ ### 🐞 Bug fixes
12
+ - **Exporting a stack failed on its first merged tile.** "Cannot transfer object of unsupported
13
+ type", and the export stopped — reported on the stack, with its checkpoint kept, but stopped.
14
+
15
+ The pixel worker hands a decoded tile over rather than copying it, because a raster is most of a
16
+ megabyte per source and copying each one is work on the very thread the worker exists to keep
17
+ free. It only did that where the buffer looked like it owned its memory: byte offset zero, and a
18
+ backing buffer exactly its own length.
19
+
20
+ A tile decoded by `sharp` passes that check and cannot be transferred anyway. Its memory comes
21
+ from libvips, so the backing store is externally allocated and Node refuses it — while looking,
22
+ by every property there is to look at, exactly like one it would accept. There is nothing to
23
+ test for, so the copy is now unconditional.
24
+
25
+ The tests never caught it because every one of them built its rasters with `Buffer.alloc`, whose
26
+ memory Node owns and will happily hand over. There is a test now that decodes a tile through the
27
+ codec first, and it fails against the old code.
28
+
10
29
  ## 0.68.2
11
30
  ### 🐞 Bug fixes
12
31
  - **Archives were listed under a heading that said Stacks.** The catalogue page's Archives
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmtiles-swarm",
3
- "version": "0.68.2",
3
+ "version": "0.68.3",
4
4
  "description": "BitTorrent distribution for PMTiles map archives: create torrents, watch folders, publish and subscribe to RSS feeds, and seed through qBittorrent or an embedded client",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/pixels.js CHANGED
@@ -75,28 +75,25 @@ export class PixelWorker {
75
75
  const id = this.#next;
76
76
  this.#next += 1;
77
77
 
78
- // Rasters are handed over rather than cloned, and where possible without
79
- // being copied first either. A decoded tile is most of a megabyte per
80
- // source, and copying every one of them is work on the very thread this
81
- // exists to keep free -- enough of it to cost more than it saves.
78
+ // Copied into a buffer this thread allocated, then transferred.
82
79
  //
83
- // Copied only when the buffer does not own its memory. Node pools
84
- // allocations under 4 KiB, and transferring a pooled buffer would hand
85
- // over the whole pool with everything else in it; a raster is far larger
86
- // than that and so is always its own allocation, but the check is what
87
- // makes that a fact rather than an assumption.
80
+ // An earlier version handed the raster over as it stood where it looked
81
+ // like it owned its memory -- byteOffset zero and a buffer exactly its own
82
+ // length -- to save copying most of a megabyte per source. A decoded tile
83
+ // passes that check and cannot be transferred anyway: `sharp` gets its
84
+ // memory from libvips, so the backing store is externally allocated, and
85
+ // Node refuses it with "Cannot transfer object of unsupported type". There
86
+ // is no property that tells the two apart, so there is nothing to check
87
+ // for -- the copy is the only thing that is always right.
88
88
  //
89
- // Either way the caller gives up these rasters. Nothing reads them after a
90
- // merge, which is what makes that safe.
89
+ // The caller gives up these rasters either way. Nothing reads a
90
+ // contribution after its merge, which is what makes that safe.
91
91
  const transfers = [];
92
- const owned = (bytes) =>
93
- bytes.byteOffset === 0 && bytes.buffer.byteLength === bytes.byteLength;
94
92
  const contributions = job.contributions.map((contribution) => {
95
93
  if (!contribution?.raster?.data) return contribution;
96
94
  const source = contribution.raster.data;
97
- const bytes = owned(source)
98
- ? source
99
- : Uint8Array.prototype.slice.call(source);
95
+ const bytes = new Uint8Array(source.byteLength);
96
+ bytes.set(source);
100
97
  transfers.push(bytes.buffer);
101
98
  return {
102
99
  ...contribution,