@mapwhit/tilerenderer 0.47.1 → 0.48.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 (76) hide show
  1. package/build/min/package.json +1 -1
  2. package/package.json +1 -2
  3. package/src/data/array_types.js +1 -1
  4. package/src/data/bucket/circle_bucket.js +1 -1
  5. package/src/data/bucket/fill_bucket.js +1 -1
  6. package/src/data/bucket/fill_extrusion_bucket.js +1 -1
  7. package/src/data/bucket/heatmap_bucket.js +1 -1
  8. package/src/data/bucket/line_bucket.js +1 -1
  9. package/src/data/bucket/symbol_bucket.js +26 -12
  10. package/src/data/dem_data.js +1 -1
  11. package/src/data/feature_index.js +43 -82
  12. package/src/data/program_configuration.js +19 -11
  13. package/src/data/segment.js +2 -2
  14. package/src/geo/transform.js +4 -2
  15. package/src/gl/color_mode.js +6 -6
  16. package/src/index.js +3 -1
  17. package/src/render/glyph_atlas.js +1 -1
  18. package/src/render/glyph_manager.js +43 -48
  19. package/src/render/image_atlas.js +1 -1
  20. package/src/render/image_manager.js +9 -37
  21. package/src/source/geojson_source.js +49 -93
  22. package/src/source/geojson_worker_source.js +33 -134
  23. package/src/source/image_source.js +9 -14
  24. package/src/source/load_tilejson.js +27 -34
  25. package/src/source/raster_dem_tile_source.js +27 -40
  26. package/src/source/raster_tile_source.js +53 -62
  27. package/src/source/rtl_text_plugin.js +3 -1
  28. package/src/source/source_cache.js +23 -21
  29. package/src/source/source_state.js +17 -26
  30. package/src/source/tile.js +6 -5
  31. package/src/source/tile_id.js +1 -1
  32. package/src/source/vector_tile_source.js +56 -73
  33. package/src/source/vector_tile_worker_source.js +20 -85
  34. package/src/source/worker.js +37 -103
  35. package/src/source/worker_tile.js +39 -84
  36. package/src/style/load_sprite.js +14 -17
  37. package/src/style/properties.js +1 -1
  38. package/src/style/style.js +22 -37
  39. package/src/style/style_layer/symbol_style_layer_properties.js +1 -1
  40. package/src/style/style_layer_index.js +17 -23
  41. package/src/style-spec/expression/compound_expression.js +30 -16
  42. package/src/style-spec/expression/definitions/coercion.js +13 -0
  43. package/src/style-spec/expression/definitions/comparison.js +193 -0
  44. package/src/style-spec/expression/definitions/formatted.js +123 -0
  45. package/src/style-spec/expression/definitions/index.js +10 -60
  46. package/src/style-spec/expression/definitions/interpolate.js +17 -7
  47. package/src/style-spec/expression/definitions/literal.js +5 -0
  48. package/src/style-spec/expression/parsing_context.js +4 -0
  49. package/src/style-spec/expression/types.js +12 -1
  50. package/src/style-spec/feature_filter/index.js +1 -1
  51. package/src/style-spec/reference/v8.json +120 -49
  52. package/src/symbol/anchor.js +1 -1
  53. package/src/symbol/collision_index.js +23 -16
  54. package/src/symbol/get_anchors.js +11 -22
  55. package/src/symbol/grid_index.js +176 -182
  56. package/src/symbol/mergelines.js +51 -48
  57. package/src/symbol/opacity_state.js +1 -1
  58. package/src/symbol/placement.js +8 -2
  59. package/src/symbol/quads.js +7 -6
  60. package/src/symbol/shaping.js +185 -40
  61. package/src/symbol/symbol_layout.js +9 -6
  62. package/src/symbol/transform_text.js +12 -1
  63. package/src/ui/camera.js +82 -85
  64. package/src/ui/map.js +13 -57
  65. package/src/util/actor.js +46 -42
  66. package/src/util/browser.js +6 -0
  67. package/src/util/dictionary_coder.js +13 -21
  68. package/src/util/dispatcher.js +14 -17
  69. package/src/util/image.js +1 -1
  70. package/src/util/loader/image.js +11 -11
  71. package/src/util/polyfill.js +16 -0
  72. package/src/util/task_queue.js +39 -43
  73. package/src/util/transfer_registry.js +167 -0
  74. package/src/util/web_worker_transfer.js +5 -190
  75. package/src/source/raster_dem_tile_worker_source.js +0 -26
  76. package/src/style-spec/expression/definitions/equals.js +0 -93
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Adds a static method `withResolvers` to the Promise object if it does not already exist.
3
+ *
4
+ * @see https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers
5
+ */
6
+ if (typeof Promise.withResolvers !== 'function') {
7
+ Promise.withResolvers = function () {
8
+ let resolve;
9
+ let reject;
10
+ const promise = new Promise((res, rej) => {
11
+ resolve = res;
12
+ reject = rej;
13
+ });
14
+ return { promise, resolve, reject };
15
+ };
16
+ }
@@ -1,57 +1,53 @@
1
1
  const assert = require('assert');
2
2
 
3
- // can't mark opaque due to https://github.com/flowtype/flow-remove-types/pull/61
4
-
5
- class TaskQueue {
6
- constructor() {
7
- this._queue = [];
8
- this._id = 0;
9
- this._cleared = false;
10
- this._currentlyRunning = false;
11
- }
12
-
13
- add(callback) {
14
- const id = ++this._id;
15
- const queue = this._queue;
16
- queue.push({ callback, id, cancelled: false });
3
+ module.exports = taskQueue;
4
+
5
+ function taskQueue(thisArg) {
6
+ const queues = {
7
+ running: [],
8
+ later: []
9
+ };
10
+ let id = Number.MIN_SAFE_INTEGER;
11
+ let cleared = false;
12
+
13
+ return {
14
+ add,
15
+ remove,
16
+ run,
17
+ clear
18
+ };
19
+
20
+ function add(fn) {
21
+ if (id === Number.MAX_SAFE_INTEGER) id = Number.MIN_SAFE_INTEGER;
22
+ id += 1;
23
+ queues.later.push({ fn, id, cancelled: false });
17
24
  return id;
18
25
  }
19
26
 
20
- remove(id) {
21
- const running = this._currentlyRunning;
22
- const queue = running ? this._queue.concat(running) : this._queue;
23
- for (const task of queue) {
24
- if (task.id === id) {
25
- task.cancelled = true;
26
- return;
27
- }
27
+ function remove(id) {
28
+ const task = queues.running.find(t => t.id === id) ?? queues.later.find(t => t.id === id);
29
+ if (task) {
30
+ task.cancelled = true;
28
31
  }
29
32
  }
30
33
 
31
- run() {
32
- assert(!this._currentlyRunning);
33
- const queue = (this._currentlyRunning = this._queue);
34
-
35
- // Tasks queued by callbacks in the current queue should be executed
36
- // on the next run, not the current run.
37
- this._queue = [];
38
-
39
- for (const task of queue) {
40
- if (task.cancelled) continue;
41
- task.callback();
42
- if (this._cleared) break;
34
+ function run() {
35
+ assert(queues.running.length === 0);
36
+ queues.running = queues.later;
37
+ queues.later = [];
38
+ for (const { fn, cancelled } of queues.running) {
39
+ if (cancelled) continue;
40
+ fn.call(thisArg);
41
+ if (cleared) break;
43
42
  }
44
-
45
- this._cleared = false;
46
- this._currentlyRunning = false;
43
+ queues.running.length = 0;
44
+ cleared = false;
47
45
  }
48
46
 
49
- clear() {
50
- if (this._currentlyRunning) {
51
- this._cleared = true;
47
+ function clear() {
48
+ if (queues.running.length > 0) {
49
+ cleared = true;
52
50
  }
53
- this._queue = [];
51
+ queues.later.length = 0;
54
52
  }
55
53
  }
56
-
57
- module.exports = TaskQueue;
@@ -0,0 +1,167 @@
1
+ const assert = require('assert');
2
+
3
+ module.exports = {
4
+ register,
5
+ serialize,
6
+ deserialize
7
+ };
8
+
9
+ const registry = new Map();
10
+
11
+ /**
12
+ * Register the given class as serializable.
13
+ *
14
+ * @param options
15
+ * @param options.omit List of properties to omit from serialization (e.g., cached/computed properties)
16
+ * @param options.shallow List of properties that should be serialized by a simple shallow copy, rather than by a recursive call to serialize().
17
+ *
18
+ * @private
19
+ */
20
+ function register(name, klass, { omit, shallow } = {}) {
21
+ assert(!registry.has(name), `${name} is already registered.`);
22
+ Object.defineProperty(klass, '_classRegistryKey', {
23
+ value: name,
24
+ writeable: false
25
+ });
26
+ registry.set(name, { klass, omit, shallow });
27
+ }
28
+
29
+ register('Object', Object);
30
+
31
+ /**
32
+ * Serialize the given object for transfer to or from a web worker.
33
+ *
34
+ * For non-builtin types, recursively serialize each property (possibly
35
+ * omitting certain properties - see register()), and package the result along
36
+ * with the constructor's `name` so that the appropriate constructor can be
37
+ * looked up in `deserialize()`.
38
+ *
39
+ * If a `transferables` array is provided, add any transferable objects (i.e.,
40
+ * any ArrayBuffers or ArrayBuffer views) to the list. (If a copy is needed,
41
+ * this should happen in the client code, before using serialize().)
42
+ *
43
+ * @private
44
+ */
45
+ function serialize(input, transferables) {
46
+ if (isSerializablePrimitive(input)) {
47
+ return input;
48
+ }
49
+
50
+ if (input instanceof ArrayBuffer) {
51
+ transferables?.push(input);
52
+ return input;
53
+ }
54
+
55
+ if (ArrayBuffer.isView(input)) {
56
+ transferables?.push(input.buffer);
57
+ return input;
58
+ }
59
+
60
+ if (input instanceof ImageData) {
61
+ transferables?.push(input.data.buffer);
62
+ return input;
63
+ }
64
+
65
+ if (Array.isArray(input)) {
66
+ return input.map(item => serialize(item, transferables));
67
+ }
68
+
69
+ if (typeof input === 'object') {
70
+ const klass = input.constructor;
71
+ const name = klass._classRegistryKey;
72
+ if (!name) {
73
+ throw new Error(`can't serialize object of unregistered class`);
74
+ }
75
+ assert(registry.has(name));
76
+
77
+ // (Temporary workaround) allow a class to provide static
78
+ // `serialize()` and `deserialize()` methods to bypass the generic
79
+ // approach.
80
+ // This temporary workaround lets us use the generic serialization
81
+ // approach for objects whose members include instances of dynamic
82
+ // StructArray types. Once we refactor StructArray to be static,
83
+ // we can remove this complexity.
84
+ const properties = klass.serialize ? klass.serialize(input, transferables) : {};
85
+
86
+ if (!klass.serialize) {
87
+ const { omit, shallow } = registry.get(name);
88
+ for (const key in input) {
89
+ if (!Object.hasOwn(input, key)) continue;
90
+ if (omit?.includes(key)) continue;
91
+ const value = input[key];
92
+ properties[key] = shallow?.includes(key) ? value : serialize(value, transferables);
93
+ }
94
+ if (input instanceof Error) {
95
+ properties.message = input.message;
96
+ }
97
+ } else {
98
+ // make sure statically serialized object survives transfer of $name property
99
+ assert(!transferables || properties !== transferables[transferables.length - 1]);
100
+ }
101
+
102
+ if (properties.$name) {
103
+ throw new Error('$name property is reserved for worker serialization logic.');
104
+ }
105
+ if (name !== 'Object') {
106
+ properties.$name = name;
107
+ }
108
+
109
+ return properties;
110
+ }
111
+
112
+ throw new Error(`can't serialize object of type ${typeof input}`);
113
+ }
114
+
115
+ function deserialize(input) {
116
+ if (
117
+ isSerializablePrimitive(input) ||
118
+ input instanceof ArrayBuffer ||
119
+ ArrayBuffer.isView(input) ||
120
+ input instanceof ImageData
121
+ ) {
122
+ return input;
123
+ }
124
+
125
+ if (Array.isArray(input)) {
126
+ return input.map(deserialize);
127
+ }
128
+
129
+ if (typeof input === 'object') {
130
+ const name = input.$name ?? 'Object';
131
+
132
+ const { klass, shallow } = registry.get(name);
133
+ if (!klass) {
134
+ throw new Error(`can't deserialize unregistered class ${name}`);
135
+ }
136
+
137
+ if (klass.deserialize) {
138
+ return klass.deserialize(input);
139
+ }
140
+
141
+ const result = Object.create(klass.prototype);
142
+
143
+ for (const key of Object.keys(input)) {
144
+ if (key === '$name') continue;
145
+ const value = input[key];
146
+ result[key] = shallow?.includes(key) ? value : deserialize(value);
147
+ }
148
+
149
+ return result;
150
+ }
151
+
152
+ throw new Error(`can't deserialize object of type ${typeof input}`);
153
+ }
154
+
155
+ function isSerializablePrimitive(input) {
156
+ return (
157
+ input == null ||
158
+ typeof input === 'boolean' ||
159
+ typeof input === 'number' ||
160
+ typeof input === 'string' ||
161
+ input instanceof Date ||
162
+ input instanceof RegExp ||
163
+ input instanceof Boolean ||
164
+ input instanceof Number ||
165
+ input instanceof String
166
+ );
167
+ }
@@ -1,5 +1,3 @@
1
- const assert = require('assert');
2
-
3
1
  const Grid = require('grid-index');
4
2
  const Color = require('../style-spec/util/color');
5
3
  const {
@@ -11,31 +9,11 @@ const {
11
9
  const CompoundExpression = require('../style-spec/expression/compound_expression');
12
10
  const expressions = require('../style-spec/expression/definitions');
13
11
 
14
- const registry = {};
15
-
16
- /**
17
- * Register the given class as serializable.
18
- *
19
- * @param options
20
- * @param options.omit List of properties to omit from serialization (e.g., cached/computed properties)
21
- * @param options.shallow List of properties that should be serialized by a simple shallow copy, rather than by a recursive call to serialize().
22
- *
23
- * @private
24
- */
25
- function register(name, klass, options = {}) {
26
- assert(!registry[name], `${name} is already registered.`);
27
- Object.defineProperty(klass, '_classRegistryKey', {
28
- value: name,
29
- writeable: false
30
- });
31
- registry[name] = {
32
- klass,
33
- omit: options.omit || [],
34
- shallow: options.shallow || []
35
- };
36
- }
37
-
38
- register('Object', Object);
12
+ const { register, serialize, deserialize } = require('./transfer_registry');
13
+ module.exports = {
14
+ serialize,
15
+ deserialize
16
+ };
39
17
 
40
18
  Grid.serialize = function serializeGrid(grid, transferables) {
41
19
  const buffer = grid.toArrayBuffer();
@@ -63,166 +41,3 @@ for (const name in expressions) {
63
41
  if (expressions[name]._classRegistryKey) continue;
64
42
  register(`Expression_${name}`, expressions[name]);
65
43
  }
66
-
67
- /**
68
- * Serialize the given object for transfer to or from a web worker.
69
- *
70
- * For non-builtin types, recursively serialize each property (possibly
71
- * omitting certain properties - see register()), and package the result along
72
- * with the constructor's `name` so that the appropriate constructor can be
73
- * looked up in `deserialize()`.
74
- *
75
- * If a `transferables` array is provided, add any transferable objects (i.e.,
76
- * any ArrayBuffers or ArrayBuffer views) to the list. (If a copy is needed,
77
- * this should happen in the client code, before using serialize().)
78
- *
79
- * @private
80
- */
81
- function serialize(input, transferables) {
82
- if (
83
- input === null ||
84
- input === undefined ||
85
- typeof input === 'boolean' ||
86
- typeof input === 'number' ||
87
- typeof input === 'string' ||
88
- input instanceof Boolean ||
89
- input instanceof Number ||
90
- input instanceof String ||
91
- input instanceof Date ||
92
- input instanceof RegExp
93
- ) {
94
- return input;
95
- }
96
-
97
- if (input instanceof ArrayBuffer) {
98
- if (transferables) {
99
- transferables.push(input);
100
- }
101
- return input;
102
- }
103
-
104
- if (ArrayBuffer.isView(input)) {
105
- const view = input;
106
- if (transferables) {
107
- transferables.push(view.buffer);
108
- }
109
- return view;
110
- }
111
-
112
- if (input instanceof ImageData) {
113
- if (transferables) {
114
- transferables.push(input.data.buffer);
115
- }
116
- return input;
117
- }
118
-
119
- if (Array.isArray(input)) {
120
- const serialized = [];
121
- for (const item of input) {
122
- serialized.push(serialize(item, transferables));
123
- }
124
- return serialized;
125
- }
126
-
127
- if (typeof input === 'object') {
128
- const klass = input.constructor;
129
- const name = klass._classRegistryKey;
130
- if (!name) {
131
- throw new Error(`can't serialize object of unregistered class`);
132
- }
133
- assert(registry[name]);
134
-
135
- const properties = klass.serialize
136
- ? // (Temporary workaround) allow a class to provide static
137
- // `serialize()` and `deserialize()` methods to bypass the generic
138
- // approach.
139
- // This temporary workaround lets us use the generic serialization
140
- // approach for objects whose members include instances of dynamic
141
- // StructArray types. Once we refactor StructArray to be static,
142
- // we can remove this complexity.
143
- klass.serialize(input, transferables)
144
- : {};
145
-
146
- if (!klass.serialize) {
147
- for (const key in input) {
148
- // any cast due to https://github.com/facebook/flow/issues/5393
149
- if (!input.hasOwnProperty(key)) continue;
150
- if (registry[name].omit.indexOf(key) >= 0) continue;
151
- const property = input[key];
152
- properties[key] = registry[name].shallow.indexOf(key) >= 0 ? property : serialize(property, transferables);
153
- }
154
- if (input instanceof Error) {
155
- properties.message = input.message;
156
- }
157
- } else {
158
- // make sure statically serialized object survives transfer of $name property
159
- assert(!transferables || properties !== transferables[transferables.length - 1]);
160
- }
161
-
162
- if (properties.$name) {
163
- throw new Error('$name property is reserved for worker serialization logic.');
164
- }
165
- if (name !== 'Object') {
166
- properties.$name = name;
167
- }
168
-
169
- return properties;
170
- }
171
-
172
- throw new Error(`can't serialize object of type ${typeof input}`);
173
- }
174
-
175
- function deserialize(input) {
176
- if (
177
- input === null ||
178
- input === undefined ||
179
- typeof input === 'boolean' ||
180
- typeof input === 'number' ||
181
- typeof input === 'string' ||
182
- input instanceof Boolean ||
183
- input instanceof Number ||
184
- input instanceof String ||
185
- input instanceof Date ||
186
- input instanceof RegExp ||
187
- input instanceof ArrayBuffer ||
188
- ArrayBuffer.isView(input) ||
189
- input instanceof ImageData
190
- ) {
191
- return input;
192
- }
193
-
194
- if (Array.isArray(input)) {
195
- return input.map(deserialize);
196
- }
197
-
198
- if (typeof input === 'object') {
199
- const name = input.$name || 'Object';
200
-
201
- const { klass } = registry[name];
202
- if (!klass) {
203
- throw new Error(`can't deserialize unregistered class ${name}`);
204
- }
205
-
206
- if (klass.deserialize) {
207
- return klass.deserialize(input);
208
- }
209
-
210
- const result = Object.create(klass.prototype);
211
-
212
- for (const key of Object.keys(input)) {
213
- if (key === '$name') continue;
214
- const value = input[key];
215
- result[key] = registry[name].shallow.indexOf(key) >= 0 ? value : deserialize(value);
216
- }
217
-
218
- return result;
219
- }
220
-
221
- throw new Error(`can't deserialize object of type ${typeof input}`);
222
- }
223
-
224
- module.exports = {
225
- register,
226
- serialize,
227
- deserialize
228
- };
@@ -1,26 +0,0 @@
1
- const DEMData = require('../data/dem_data');
2
-
3
- class RasterDEMTileWorkerSource {
4
- constructor() {
5
- this.loaded = {};
6
- }
7
-
8
- loadTile(params, callback) {
9
- const { uid, encoding, rawImageData } = params;
10
- const dem = new DEMData(uid, rawImageData, encoding);
11
-
12
- this.loaded = this.loaded || {};
13
- this.loaded[uid] = dem;
14
- callback(null, dem);
15
- }
16
-
17
- removeTile(params) {
18
- const loaded = this.loaded;
19
- const uid = params.uid;
20
- if (loaded?.[uid]) {
21
- delete loaded[uid];
22
- }
23
- }
24
- }
25
-
26
- module.exports = RasterDEMTileWorkerSource;
@@ -1,93 +0,0 @@
1
- const { toString, ValueType, BooleanType, CollatorType } = require('../types');
2
-
3
- function isComparableType(type) {
4
- return type.kind === 'string' || type.kind === 'number' || type.kind === 'boolean' || type.kind === 'null';
5
- }
6
-
7
- /**
8
- * Special form for ==, !=, implementing the following signatures:
9
- * - (T1: Comparable, T2: Comparable) => boolean { T1 == T2 }
10
- * - (Comparable, value) => boolean
11
- * - (value, Comparable) => boolean
12
- *
13
- * Where Comparable = string | number | boolean | null.
14
- *
15
- * Evaluation semantics for the value cases are equivalent to Javascript's
16
- * strict equality (===/!==) -- i.e., when the value argument's type doesn't
17
- * match that of the Comparable argument, == evaluates to false, != to true.
18
- *
19
- * @private
20
- */
21
- function makeComparison(op, negate) {
22
- return class Comparison {
23
- constructor(lhs, rhs, collator) {
24
- this.type = BooleanType;
25
- this.lhs = lhs;
26
- this.rhs = rhs;
27
- this.collator = collator;
28
- }
29
-
30
- static parse(args, context) {
31
- if (args.length !== 3 && args.length !== 4) return context.error('Expected two or three arguments.');
32
-
33
- const lhs = context.parse(args[1], 1, ValueType);
34
- if (!lhs) return null;
35
- const rhs = context.parse(args[2], 2, ValueType);
36
- if (!rhs) return null;
37
-
38
- if (!isComparableType(lhs.type) && !isComparableType(rhs.type)) {
39
- return context.error(
40
- `Expected at least one argument to be a string, number, boolean, or null, but found (${toString(lhs.type)}, ${toString(rhs.type)}) instead.`
41
- );
42
- }
43
-
44
- if (lhs.type.kind !== rhs.type.kind && lhs.type.kind !== 'value' && rhs.type.kind !== 'value') {
45
- return context.error(`Cannot compare ${toString(lhs.type)} and ${toString(rhs.type)}.`);
46
- }
47
-
48
- let collator = null;
49
- if (args.length === 4) {
50
- if (lhs.type.kind !== 'string' && rhs.type.kind !== 'string') {
51
- return context.error('Cannot use collator to compare non-string types.');
52
- }
53
- collator = context.parse(args[3], 3, CollatorType);
54
- if (!collator) return null;
55
- }
56
-
57
- return new Comparison(lhs, rhs, collator);
58
- }
59
-
60
- evaluate(ctx) {
61
- const equal = this.collator
62
- ? this.collator.evaluate(ctx).compare(this.lhs.evaluate(ctx), this.rhs.evaluate(ctx)) === 0
63
- : this.lhs.evaluate(ctx) === this.rhs.evaluate(ctx);
64
-
65
- return negate ? !equal : equal;
66
- }
67
-
68
- eachChild(fn) {
69
- fn(this.lhs);
70
- fn(this.rhs);
71
- if (this.collator) {
72
- fn(this.collator);
73
- }
74
- }
75
-
76
- possibleOutputs() {
77
- return [true, false];
78
- }
79
-
80
- serialize() {
81
- const serialized = [op];
82
- this.eachChild(child => {
83
- serialized.push(child.serialize());
84
- });
85
- return serialized;
86
- }
87
- };
88
- }
89
-
90
- module.exports = {
91
- Equals: makeComparison('==', false),
92
- NotEquals: makeComparison('!=', true)
93
- };