@maplibre/geojson-vt 6.1.0 → 6.1.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maplibre/geojson-vt",
3
- "version": "6.1.0",
3
+ "version": "6.1.1",
4
4
  "description": "Slice GeoJSON data into vector tiles efficiently",
5
5
  "type": "module",
6
6
  "exports": {
@@ -25,30 +25,26 @@
25
25
  "unpkg": "dist/geojson-vt.js",
26
26
  "devDependencies": {
27
27
  "@eslint/js": "^10.0.1",
28
- "@rollup/plugin-node-resolve": "^16.0.3",
29
- "@rollup/plugin-terser": "^1.0.0",
30
- "@rollup/plugin-typescript": "^12.3.0",
31
28
  "@types/benchmark": "^2.1.5",
32
29
  "@types/geojson": "^7946.0.16",
33
- "@types/node": "^25.5.2",
34
- "@vitest/coverage-v8": "^4.1.2",
30
+ "@types/node": "^26.0.1",
31
+ "@vitest/coverage-v8": "^4.1.8",
35
32
  "benchmark": "^2.1.4",
36
- "eslint": "^10.2.0",
37
- "rollup": "^4.60.1",
38
- "tslib": "^2.8.1",
39
- "tsx": "^4.21.0",
40
- "typedoc": "^0.28.18",
41
- "typescript": "^6.0.2",
42
- "typescript-eslint": "^8.58.0",
43
- "vitest": "^4.0.17"
33
+ "eslint": "^10.6.0",
34
+ "rolldown": "^1.1.3",
35
+ "tsx": "^4.22.4",
36
+ "typedoc": "^0.28.19",
37
+ "typescript": "^6.0.3",
38
+ "typescript-eslint": "^8.62.1",
39
+ "vitest": "^4.1.9"
44
40
  },
45
41
  "license": "ISC",
46
42
  "scripts": {
47
43
  "lint": "eslint",
48
44
  "test": "vitest",
49
45
  "coverage": "vitest run --coverage",
50
- "build": "rollup -c && tsc -p tsconfig.declaration.json",
51
- "watch": "rollup -cw",
46
+ "build": "rolldown -c && tsc -p tsconfig.declaration.json",
47
+ "watch": "rolldown -cw",
52
48
  "start": "npm run watch",
53
49
  "bench": "tsx bench/benchmark.ts && tsx --expose-gc bench/memory-bench.ts",
54
50
  "docs": "typedoc && mkdir -p docs/debug && cp -r debug/* docs/debug && find docs/debug -name '*.html' -exec sed -i 's|../dist/geojson-vt-dev.js|https://unpkg.com/@maplibre/geojson-vt@latest/dist/geojson-vt.js|g' {} +",
@@ -63,6 +59,6 @@
63
59
  "url": "https://github.com/maplibre/geojson-vt"
64
60
  },
65
61
  "dependencies": {
66
- "kdbush": "^4.0.2"
62
+ "kdbush": "^4.1.0"
67
63
  }
68
64
  }
@@ -0,0 +1,40 @@
1
+ import {test, expect, describe} from 'vitest';
2
+ import {convertToInternal} from './convert';
3
+ import {defaultOptions} from './geojsonvt';
4
+
5
+ /**
6
+ * Wraps a geometry in `depth` nested GeometryCollections.
7
+ */
8
+ function nestGeometryCollections(depth: number, inner: GeoJSON.Geometry): GeoJSON.Geometry {
9
+ let geometry = inner;
10
+ for (let i = 0; i < depth; i++) {
11
+ geometry = {type: 'GeometryCollection', geometries: [geometry]};
12
+ }
13
+ return geometry;
14
+ }
15
+
16
+ const point: GeoJSON.Point = {type: 'Point', coordinates: [0, 0]};
17
+
18
+ function feature(geometry: GeoJSON.Geometry): GeoJSON.Feature {
19
+ return {type: 'Feature', geometry, properties: null};
20
+ }
21
+ describe('convertToInternal', () => {
22
+ test('converts a geometry nested in GeometryCollections', () => {
23
+ const features = convertToInternal(feature(nestGeometryCollections(3, point)), defaultOptions);
24
+
25
+ expect(features).toHaveLength(1);
26
+ expect(features[0].type).toBe('Point');
27
+ });
28
+
29
+ test('allows nesting up to the supported depth', () => {
30
+ const features = convertToInternal(feature(nestGeometryCollections(1024, point)), defaultOptions);
31
+
32
+ expect(features).toHaveLength(1);
33
+ expect(features[0].type).toBe('Point');
34
+ });
35
+
36
+ test('throws when GeometryCollection nesting exceeds the supported depth', () => {
37
+ expect(() => convertToInternal(feature(nestGeometryCollections(1025, point)), defaultOptions))
38
+ .toThrow('GeometryCollection nesting exceeds supported depth: 1024');
39
+ });
40
+ })
package/src/convert.ts CHANGED
@@ -3,6 +3,8 @@ import {simplify} from './simplify';
3
3
  import {createFeature, optimizeLineMemory} from './feature';
4
4
  import type {GeoJSONVTInternalFeature, GeoJSONVTOptions, SliceArray} from './definitions';
5
5
 
6
+ const MAX_GEOMETRY_COLLECTION_DEPTH = 1024;
7
+
6
8
  /**
7
9
  * converts GeoJSON to internal source features (an intermediate projected JSON vector format with simplification data)
8
10
  * @param data
@@ -28,11 +30,15 @@ export function convertToInternal(data: GeoJSON.GeoJSON, options: GeoJSONVTOptio
28
30
  return features;
29
31
  }
30
32
 
31
- function featureToInternal(features: GeoJSONVTInternalFeature[], geojson: GeoJSON.Feature, options: GeoJSONVTOptions, index?: number) {
33
+ function featureToInternal(features: GeoJSONVTInternalFeature[], geojson: GeoJSON.Feature, options: GeoJSONVTOptions, index?: number, depth = 0) {
32
34
  if (!geojson.geometry) return;
33
35
 
36
+ if (depth > MAX_GEOMETRY_COLLECTION_DEPTH) {
37
+ throw new Error('GeometryCollection nesting exceeds supported depth: ' + MAX_GEOMETRY_COLLECTION_DEPTH);
38
+ }
39
+
34
40
  if (geojson.geometry.type === 'GeometryCollection') {
35
- convertGeometryCollection(features, geojson, geojson.geometry, options, index);
41
+ convertGeometryCollection(features, geojson, geojson.geometry, options, index, depth + 1);
36
42
  return;
37
43
  }
38
44
 
@@ -82,14 +88,14 @@ function getFeatureId(geojson: GeoJSON.Feature, options: GeoJSONVTOptions, index
82
88
  return geojson.id;
83
89
  }
84
90
 
85
- function convertGeometryCollection(features: GeoJSONVTInternalFeature[], geojson: GeoJSON.Feature, geometry: GeoJSON.GeometryCollection, options: GeoJSONVTOptions, index?: number) {
91
+ function convertGeometryCollection(features: GeoJSONVTInternalFeature[], geojson: GeoJSON.Feature, geometry: GeoJSON.GeometryCollection, options: GeoJSONVTOptions, index?: number, depth = 0) {
86
92
  for (const geom of geometry.geometries) {
87
93
  featureToInternal(features, {
88
94
  id: geojson.id,
89
95
  type: 'Feature',
90
96
  geometry: geom,
91
97
  properties: geojson.properties
92
- }, options, index);
98
+ }, options, index, depth);
93
99
  }
94
100
  }
95
101
 
package/src/difference.ts CHANGED
@@ -95,7 +95,7 @@ export function applySourceDiff(source: GeoJSONVTInternalFeature[], dataDiff: Ge
95
95
  }
96
96
 
97
97
  if (removeFeatures.length) {
98
- affected.push(...removeFeatures);
98
+ affected = affected.concat(removeFeatures);
99
99
  const removeIds = new Set(removeFeatures.map(f => f.id));
100
100
  source = source.filter(f => !removeIds.has(f.id));
101
101
  }
@@ -103,15 +103,15 @@ export function applySourceDiff(source: GeoJSONVTInternalFeature[], dataDiff: Ge
103
103
  if (diff.add.size) {
104
104
  let addFeatures = convertToInternal({type: 'FeatureCollection', features: Array.from(diff.add.values())}, options);
105
105
  addFeatures = wrap(addFeatures, options);
106
- affected.push(...addFeatures);
107
- source.push(...addFeatures);
106
+ affected = affected.concat(addFeatures);
107
+ source = source.concat(addFeatures);
108
108
  }
109
109
  }
110
110
 
111
111
  if (diff.update.size) {
112
112
  // Features can be duplicated across the antimeridian (wrap) in a single tile, so must update all instances with the same id
113
113
  const oldFeaturesMap = new Map<string | number, GeoJSONVTInternalFeature[]>();
114
- const keepFeatures = [];
114
+ let keepFeatures: GeoJSONVTInternalFeature[] = [];
115
115
  for (const feature of source) {
116
116
  if (diff.update.has(feature.id)) {
117
117
  oldFeaturesMap.set(feature.id, [...(oldFeaturesMap.get(feature.id) || []), feature]);
@@ -124,8 +124,8 @@ export function applySourceDiff(source: GeoJSONVTInternalFeature[], dataDiff: Ge
124
124
  if (!oldFeatures || oldFeatures.length === 0) continue;
125
125
  const updatedFeatures = getUpdatedFeatures(oldFeatures, update, options);
126
126
 
127
- affected.push(...oldFeatures, ...updatedFeatures);
128
- keepFeatures.push(...updatedFeatures);
127
+ affected = affected.concat(oldFeatures, updatedFeatures);
128
+ keepFeatures = keepFeatures.concat(updatedFeatures);
129
129
  }
130
130
  source = keepFeatures;
131
131
  }